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 19th, 2011 | Author: bart | Filed under: Javascript, JQuery, SEO, Web Development | Tags: google analytics, statistics | 1 Comment »
Outgoing links on your websites cause 3 things:
- Take linkjuice away from your page
- Drive traffic away from your webiste
- They don’t allow you to measure the amount of clicks on that link
The first problem, you have to sort manually by adding the rel=”nofollow” attribute to all external links, as recommended by Google.
The second and third problem, can be easily fixed by using jQuery. I’ll show you how:
Opening external links in a new tab
By opening those links in a new tab, your page stays open, therefore not driving the user away from your page.
Normally, this is done by manually appending target=”_blank” to each link. Let’s let jQuery do that for us.
$(document).ready(function(){
$("a[@href^='http']").attr('target','_blank');
});
(Do note that I chose to define links starting with ‘http’ as external links)
Tracking clicks on external Links
We can track links by using Google Analytics Event tracking:
$(document).ready(function(){
$("a[@href^='http']").click(function(){
_gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
});
});
Putting it all together
$(document).ready(function(){
$("a[@href^='http']")
.attr('target','_blank')
.click(function(){
_gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
});
});
Help! My internal links also start with ‘http’
No problem, you can do like me and borrow this trick from Karl Swedberg:
$('a').filter(function() { return this.hostname && this.hostname !== location.hostname; })
.attr('target','_blank')
.click(function(){
_gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
});
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: January 25th, 2011 | Author: bart | Filed under: Java, JQuery, SEO, Web Development | Tags: ajax, cache, expires, internet explorer, jquery | No Comments »
Recently I discovered Internet Explorer caches some AJAX calls.
I was using jQuery to make some AJAX calls in a web-admin interface I’m building. I noticed none of the data changed as I tried to refresh (using an AJAX call). conclusion:: IE caches AJAX calls… very annoying.
You could go around and alter every method in your Struts/Spring/… application to force no-cache. But that would take some time. Instead, I wrote a Filter.
Hold on though, you don’t want every page to get the no-cache headers, that would seriously decrease your site performance (all pages would be force-reloaded instead of browser-cached). So we’ll only filter out AJAX calls.
Luckily, jQuery passes a header argument: X-Requested-With: XmlHttpRequest

X-Requested-With
The Code!
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AjaxCacheFilter implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
if ("XMLHttpRequest".equals(((HttpServletRequest) request).getHeader("x-requested-with"))) {
((HttpServletResponse)response).setDateHeader("Expires", 0);
((HttpServletResponse)response).addHeader("Cache-Control", "no-cache");
((HttpServletResponse)response).addHeader("Pragma", "No-Cache");
}
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
And add it as the last filter in your web.xml
<filter>
<filter-name>ajaxCache</filter-name>
<filter-class>
com.yoursite.web.filters.AjaxCacheFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>ajaxCache</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Hope it helps somebody! If you used it, let me know in comments. I’d love to know!
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!