Posted: May 23rd, 2011 | Author: bart | Filed under: Javascript, JQuery, SEO, Web Development | Tags: facebook, google, google analytics | No Comments »
Following up on my previous post about Tracking External links with Google Analytics. Here’s something you can use to track Facebook likes and shares.
We’ll track clicks using the Facebook Events. Note that this only works if you’re using FBML!
Here’s the things we’re going to be tracking:
- Somebody clicks the ‘Like’ button on your website to ‘Like’ your Facebook page
- Somebody clicks the ‘Like’ button on your website to share the current page on his ‘Wall’
- Somebody clicks the ‘Send’ button to share this page with some friends on Facebook
And it’s all in here:
FB.Event.subscribe("edge.create",function(response){
if(response.indexOf("facebook.com") > 0){
//if the returned link contains 'facebook,com'. It's a 'Like' for your Facebook page
_gaq.push(['_trackEvent','Facebook','Like',response]);
}else{
//else, somebody is sharing the current page on their wall
_gaq.push(['_trackEvent','Facebook','Share',response]);
}
});
FB.Event.subscribe("message.send",function(response){
_gaq.push(['_trackEvent','Facebook','Send',response]);
});
As you may have noticed, the Facebook event contains the liked/shared/sent link as response
Posted: May 13th, 2011 | Author: bart | Filed under: Java, Web Development | Tags: appengine, google, java, translate | 1 Comment »
Google provided a few translation bots recently.
Since I do a lot of Dutch -> French translation, I quicly whipped up my own and deployed it to Google AppEngine:
For translating I used the unofficial google-api-translate-java jar file.
Here’s what you need to do:
Place the jar in war\WEB-INF\lib
war\WEB-INF\web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>Translate_Bot</servlet-name>
<servlet-class>be.bartv.translatebot.Translate_BotServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Translate_Bot</servlet-name>
<url-pattern>/translate_bot</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>xmppreceiver</servlet-name>
<servlet-class>be.bartv.translatebot.XMPPReceiverServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xmppreceiver</servlet-name>
<url-pattern>/_ah/xmpp/message/chat/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
war\WEB-INF\appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>translate-bot</application>
<version>1</version>
<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
<inbound-services>
<service>xmpp_message</service>
</inbound-services>
</appengine-web-app>
src\be.bartv.translatebot.XMPPReceiverServlet.java
package be.bartv.translatebot;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.api.GoogleAPI;
import com.google.api.translate.Language;
import com.google.api.translate.Translate;
import com.google.appengine.api.xmpp.JID;
import com.google.appengine.api.xmpp.Message;
import com.google.appengine.api.xmpp.MessageBuilder;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;
public class XMPPReceiverServlet extends HttpServlet{
private static final long serialVersionUID = 2212159648921332999L;
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
XMPPService service = XMPPServiceFactory.getXMPPService();
Message message = service.parseMessage(req);
JID jid = message.getFromJid();
String content = message.getBody();
String reply = "Hmmz. I Should return a translation now";
try {
GoogleAPI.setHttpReferrer("http://notes.bartv.be/");
reply = Translate.execute(content, Language.DUTCH, Language.FRENCH);
} catch (Exception e) {
reply = "Error occurred: "+e.getMessage();
e.printStackTrace();
}
service.sendMessage(new MessageBuilder().withBody(reply).withRecipientJids(jid).build());
}
}
Sometimes, I do get a error saying I violate Google’s Terms and conditions. No idea why tho …
Posted: March 29th, 2011 | Author: bart | Filed under: SEO, Web Development | Tags: breadcrumbs, google, optimization, seo | No Comments »
Google sometimes shows breadcrumbs in their search results.
Instead of showing the URL of the page you’re going to visit (in the green bit), hey’ll show a path kind of like so:
Homepage › Category › Subcategory > Something something.
Many SEO experts have been trying to figure out just where they come from. So have I.
So recently, on one of my websites: promoties.be. I had the chance to figure it out.
All promotions are divided into categories and subcategories. The URL of these categories are always hierarchically mapped.
e.g. http://www.promoties.be/categorie/autos-motoren-27/aanhangwagens-1419 is a subcategory of http://www.promoties.be/categorie/autos-motoren-27 making the URL logically traversable.
However a specific offer or product under this category is not in this structure. Mainly because that would make the URL way too long.
An example is http://www.promoties.be/promotie-bw1-aanhangwagen-864809. As you can see, the categories do not appear in the URL.
However the breadcrumb for this offer is as follows: Home > Promoties > Auto’s & Motoren > Aanhangwagens > Bw1 aanhangwagen with all the nested categories intact.
Now the Google search result block for this specific offer was the following:

Google search result for "Bw1 aanhangwagen"
In this case we can conclude that Google took the breadcrumbs in the search results, from the breadcrumbs on the page.
More info on breadcrumbs:
http://www.google.com/support/webmasters/bin/answer.py?answer=185417
Posted: December 3rd, 2010 | Author: bart | Filed under: SEO, Web Development | Tags: apache, google, mod_pagespeed, page, seo, speed | 1 Comment »
Google recently released a specific Apache mod: mod_pagespeed.
Here are my findings:
Introduction: goal
Often, when developing websites/webapplications, you find yourself telling yourself: I’ll quickly write that piece of CSS inline or Fudge it, I’ll leave compressing that piece of JavaScript for when I get out of development phase and maybe even never mind resizing that image, I’ll just use ‘width’ and ‘height’ to get the dimensions right.
And oh how you promise yourself you’ll fix those issues later. But let’s be honest: deadlines are cruel.
So a lot of websites go live without a lot of speed omtimizations. They get a bad score in YSlow or PageSpeed.
And the word on the street is, google prefers website that load faster!
Optimizing your CSS/JS/Images takes time. Compressing your content, combining CSS/JS also makes it difficult to adjust any of these later. You’ll have to dig through compacted code. Nobody likes that.
The solution
The new mod_pagespeed is an Apache Output Filter. This means your website renders your website (in PHP, Java, Ruby, …) and just before Apache serves your HTML page to the browser, this thing comes into action.
You can configure it to do a lot of things. I listed the ones I find most important below. But you can get the full feature list here
- Compress CSS and JS (less traffic)
- Move inline CSS/JS to an external file (so they can get cached)
- Combine external CSS/JS to one file (less requests)
- Caching (of HTML,CSS,JS,images)
- Automatically resize images based on the ‘width’ and ‘height’ attributes of an img-tag (less traffic)
- Add ‘width’ and ‘height’ attributes if you forgot any (usability)
- Base64 encode images and include them in HTML when small (less requests)
Bottomline: it’s genius
My Configuration
I played around with mod_pagespeed today. Here’s the configuration I came up with (I added comments)
(your configuration resides in /etc/apache2/mods-enabled/pagespeed.conf)
<IfModule pagespeed_module>
ModPagespeed on
AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER text/html
ModPagespeedFileCachePath "/var/mod_pagespeed/cache/"
ModPagespeedGeneratedFilePrefix "/var/mod_pagespeed/files/"
ModPagespeedRewriteLevel CoreFilters
ModPagespeedFileCachePath "/var/mod_pagespeed/cache/"
ModPagespeedGeneratedFilePrefix "/var/mod_pagespeed/files/"
#Add head section to HTML (if not already there)
ModPagespeedEnableFilters add_head
#Move CSS and JS to outline (external file)
ModPagespeedEnableFilters outline_css,outline_javascript
#If inline CSS is used, move this to head section
ModPagespeedEnableFilters move_css_to_head
#Combine external CSS files to 1 fil
ModPagespeedEnableFilters combine_css
#Compress CSS and JS by removing whitespace/comments
ModPagespeedEnableFilters rewrite_css,rewrite_javascript
#Cache/compress images. Couold also move the image to HTML code (base64 encoded) if image size is small enough
ModPagespeedEnableFilters rewrite_images
#Add longer expires headers
ModPagespeedEnableFilters extend_cache
#Insert "width" and "height" attributes if not used
ModPagespeedEnableFilters insert_img_dimensions
#Remove HTML comments
ModPagespeedEnableFilters remove_comments
# Removes quotes around HTML attributes that are not lexically required
ModPagespeedEnableFilters remove_quotes
#pagespeed enabled domain 1
ModPagespeedDomain tv.bartv.be
#Pagespeed enabled domain 2
ModPagespeedDomain cloudcast.bartv.be
#pagespeed enabled domain 3
ModPagespeedDomain notes.bartv.be
#Maximum filesize cache
ModPagespeedFileCacheSizeKb 10240
#Interval to which cache is refreshed
ModPagespeedFileCacheCleanIntervalMs 3600000
ModPagespeedLRUCacheKbPerProcess 1024
ModPagespeedLRUCacheByteLimit 16384
#Minimum allowed bytes in CSS before exporting to external CSS
ModPagespeedCssOutlineMinBytes 1000
#Minimum allowed bytes in JS before exporting to external JS
ModPagespeedJsOutlineMinBytes 3000
#Maximum allowed filesize for embedding images inline (base64)
ModPagespeedImgInlineMaxBytes 2048
</IfModule>
Carefull with writing permissions
On my webserver, I run every website under a different user account (e.g. mycoolwebsite.bartv.be is run by user ‘coolwebsite’ or something). They all belong to the group ‘www-data’.
Now one consequence of this is that the cache being written by mod_pagespeed gets written by the user running the website. So be carefull with writing permissions in /var/mod_pagespeed/
Footnote
Even though this article might suggest it. I’m in no way promoting quick and dirty development.
You could think: to hell with it, I’ll just write whatever I want, mod_pagespeed will solve it for me. Don’t
mod_pagespeed is great, but in my eyes, it helps you find errors you might have missed. And it lets you use your development CSS/JS files without compressing them first.
But don’t use it to clean up your mess!