Track outbound links using Google Analytics

Track every­thing”, lest vital vis­i­tor trends fall through the cracks — that’s my newly endorsed web ana­lyt­ics doc­trine. As a pre­cur­sor to the quan­ti­ta­tive ‘what’ and the qual­i­ta­tive ‘why’ we need that cold hard data before analy­sis can begin; Google Ana­lyt­ics is the pop­u­lar har­vester of choice and out of the box it grabs a lot. Vis­its, Pageviews, Screen res­o­lu­tion, et al — GA seem­ingly has all your con­ven­tional data needs cov­ered. But one sig­nif­i­cant trend is lack­ing — how vis­i­tors leave your site, specif­i­cally through out­bound links on a page, data that inevitably leads to a what and an avenue for inves­ti­gat­ing the why. For instance, “Which part­ner sites are attract­ing the high­est click throughs?” or more gen­er­ally “Why do vis­i­tors leave my site?”.

GA gives the abil­ity to cre­ate your own events with a cat­e­gory, action, label and numer­i­cal value using the syntax:

_trackEvent(category, action, optional_label, optional_value)

Hence, on an out­bound link click, by call­ing this JavaScript method you can trig­ger a tracked event in GA. An obtru­sive onclick attribute on every out­bound link is both cum­ber­some to imple­ment and dif­fi­cult to man­age, it also goes against the best prac­tices of pro­gres­sive enhance­ment and unobtrusiveness.

The solu­tion is to attach a click event lis­tener to each of the out­bound links on the page, and the ques­tion becomes how to do that. CSS3 comes with a cou­ple of handy new selec­tors that we can use in com­bi­na­tion with Pro­to­type or jQuery to root out the cor­rect links. The appro­pri­ate selectors:

E[foo^=“bar”] an E ele­ment whose “foo” attribute value begins exactly with the string “bar“
E[foo*=“bar”] an E ele­ment whose “foo” attribute value con­tains the sub­string “bar“
E:not(s) an E ele­ment that does not match sim­ple selec­tor s

The magic out­bound link selec­tor then becomes one of the fol­low­ing, depend­ing on your needs:

/* Any link that does not contain yourdomain.com */
a:not(a[href*="yourdomain.com"])

/* Any link that does not start with yourdomain.com */
a:not(a[href^="yourdomain.com"])

/* Any link that does not start with yourdomain.com or www.yourdomain.com */
a:not(a[href^="yourdomain.com"]):not(a[href^="www.yourdomain.com"])

/* Any link that starts with http - e.g. any non relative links */
a[href^="http"]

/* Catch all - any link that starts with http but doesn't link to your domain */
a[href^="http"]:not(a[href*="yourdomain.com"])

With an array of all the out­bound links at hand, adding a click lis­tener is sim­ple. But we do need to set up the cat­e­gory, action and label. I have opted to cre­ate an arbi­trary “Out­bound Link” cat­e­gory that uses the link’s text (with HTML tags stripped out) as the action and the url as the label:

Event.observe(outboundLink, 'click', function() {
        // category, action, label
        pageTracker._trackEvent('Outbound Link', outboundLink.innerHTML.replace(/(<([^>]+)>)/ig,""), outboundLink.href);
}

The com­plete code

Using Pro­to­type ver­sion 1.6 the final code might look like this:

Update: As pointed out in the com­ments, hard cod­ing a domain into your code isn’t the best idea, window.location.hostname is a good alter­na­tive. This may not always work if you do not want to exclude subdomains.

var domainName = "domainname.com";
// Select all outbound links
$$('a[href^="http"]:not(a[href*="'+domainName+'"])').each(function(outboundLink) {
        // Add listener to each of the links
        Event.observe(outboundLink, 'click', function() {
        // category, action, label
        pageTracker._trackEvent('Outbound Link', outboundLink.innerHTML.replace(/(<([^>]+)>)/ig,""), outboundLink.href);
        }
});

2 Comments

  1. Paul Armstrong
  2. Paul Hayes

    A good point, I have updated the post.