Tracking outbound links? I bet you only measure 70 percent

A lot of site owners want to track outbound links so they can see how often they are clicked. It's also useful to see when and where people left your site. Google Analytics knows the exit time of your last page, where in normal cases the last visited page is not counted in the spend time on site/page.

But, there is a big but. A lot of outbound link tracking is done like this:

<a href="http://andrescholten.net" onclick="trackClick(this)">Nice site</a>

And this is what happens when you click on this outbound link:

  1. The onclick is executed first
  2. The trackClick function generates an IMG element with a URL that points to the Web Analytics vendor
  3. The onclick function is handled and the browser starts with the href part

And then the race starts:

  • The tracking pixel is requested from the Web Analytics vendor
  • The browser kills all activity and opens the URL in the href attribute

But we can't tell which one is first. A small delay on the Web Analytics vendor side is deadly for the tracking, often the pixel request is killed by the browser. You can see this in a simple tool that shows you all activity in your browser. Because Yoasts' post is was the trigger to blog this I will use his site as an example.

Take a look at his Clicky outbound link tracking post. It has an outbound link in the first sentence. And this happens when I'm clicking it:

The first two lines are the main Clicky script with all tracking functionality and the basic pageview measurement. The third line is the outbound link tracking: in this case the tracking is send. The line is red because the browser stops waiting for the response, but that isn't necessary for the tracking. Sometimes this line isn't generated and no tracking is done...

A solution

In the post title I mentioned 70%, but that's merely a guess based on what I have seen in cases where I solved this. After implementing a little timeout before the link opens we saw a lot more outgoing links being measured. I already mentioned the solution: a little timeout to give the tracing some time to execute before the link opens.

But there are a few caveats using this technique:

  • Using "window.open" triggers the popup blocker of Internet Explorer 9+. That's because the link is opened with a script in stead of a user initiated click. We have to use location.href to prevent that from happening.

  • Using "location.href" doesn't pass on referrer information in Internet Explorer 6, 7 and 8. External site won't see traffic coming from you.

This is de jQuery code I use right now to track outgoing links:

if(typeof jQuery == 'function')  
{
  jQuery(function () 
  {
    jQuery('a[href^="http"]').click(function (e) 
    {
      var url = this.toString();
      if (url.indexOf(document.domain) == -1) 
      {
        _gaq.push(['_trackEvent', 'clickouts', jQuery(this).attr('href').replace(/https?:\/\/(.*)/,"$1")]);
        var target = jQuery(this).attr('target');
        if (target == "") { target = "_self"; }
        setTimeout(function() 
        {
          var a = document.createElement("a");
          if ((!a.click) || ((jQuery.browser.msie) && (parseInt(jQuery.browser.version) > 8))) {
            location.href = url; // for chrome and IE9+, target is lost
          } else {
            a.setAttribute("href", url);
            a.setAttribute("target", target);
            a.style.display = "none";
            aElm = document.body.appendChild(a);
            aElm.click(); //  for IE6,7,8 to pass on referrer
          }
        }, 50); // 50ms should be enough timeout
      }
      e.preventDefault();
    });
  });
};

Is this the best way to track outgoing links? For what I've seen this is one of the best and most reliable approaches. But I'm happy to receive additions that makes it even better.

Ps. In this example I used Google Analytics to track outgoing links, but you can change that part to whatever tracking you want.

Update

Eduardo Cereto proposed to use the mousedown event without an additional timeout. I tested this on several sites and it looks like the most reliable solution right now. The code is much easier also:

jQuery(function () 
{
  jQuery('a[href^="http"]').mousedown(function () 
  {
    var url = this.toString();
    if (url.indexOf(document.domain) == -1) 
    {
      _gaq.push(['_trackEvent', 'clickouts', jQuery(this).attr('href').replace(/https?:\/\/(.*)/,"$1")]);
    }
  });
});

Click to activate social bookmarks

 
  • http://www.cardinalpath.com Eduardo Cereto

    It's a good point and I've studied the subject a lot in the past.

    I used to have a timeout like this. But it turned out that 50ms increased the coverage but still was not 100% effective. So we increased that, and at some point the user started to notice that increase, and started to click multiple times firing the outbound event multiple times. I also never licked the idea of interrupting the original event since it may affect other listeners that may be setup.

    I decided to go for a slightly different approach. Instead of listening for click I listen to mousedown. On mousedown usually happens ~50ms before the click and usually there are no other listeners on this event, so less interference with an automatic timeout.

    The bonus is that it still track if the user right clicks and click on open in a new tab. Which it doesn't if you listen to 'click'.

    I think 70% is a little bit harsh, but I'm sure you lose a couple clicks every now and then. The important point is that you have something that is consistent and represent a good sample of your audience.

    • http://andrescholten.net André

      I like the idea of using the mousedown event. With that you don't need the timeout anymore. Will certainly try that.
      70% is a bit harsh, but on huge sites we saw that increase after deploying the timeout. On smaller site (smaller DOM) it is perhaps more than 70% that's being tracked.

  • Michaël van Oosten

    I haven't tested it, but this might be of interest:
    http://stackoverflow.com/questions/5554009/using-js-callback-with-google-analytics

    You should be able to push functions into _gaq. In that case you're absolutely sure measurement is finished.

    • http://andrescholten.net André

      That solution has the same problem as I mentioned in the blogpost: the tracking is ready and the IMG element is added to the DOM. But that doesn't mean the IMG itself is already being called from the Google servers.

  • Ed

    Hi Andrei,

    First of all, great post!

    When using GetClicky, how would the HTML markup look like when tracking links using Eduardo's code? - Using the mouse down event?

    I understand Eduardo's code would then go between the <head tags and the actual html link?

    How would that look like?

    Something like this?

    <a href="http://andrescholten.net">Nice site</a>

    I would like to track which links on a page gets a better CTR when experimenting with positioning and call to action text.

    • http://andrescholten.net André

      As far as I know, Clicky tracks outbound links autmatically? So you don't need to add extra code.

  • http://traffic4u.nl Mark van Kasteren

    The jQuery solution works perfectly. Google Analytics advices in their help section to use a 1 second delay for tracking outgoing links with a JavaScript solution: http://support.google.com/googleanalytics/bin/answer.py?hl=en&answer=55527

    • http://andrescholten.net André

      The timeout gave some problems with: popupblockers, people that ctrl-click to open a new tab, safari users that couldn't open links, external sites that don't receive referral info (and therefore don't know who send the traffic), etc. I tested this in many browsers, but I nowadays wouldn't recommend the timeout version, I would use the mousedown code.

  • Madarás Martin

    And what if I use _blank in link and open pages in new window? Will measure be100% objective then?

    • http://andrescholten.net/ André Scholten

      Absolutely, that's a good solution too.

    • http://gyantastic.com/online-business-for-newbies/ Ram Shengale

      I also think that's a good solution.

  • Leo

    How do you guys use this code to fire and pixel image on click?

  • https://www.holidayrentalscuracao.nl/autoverhuur debruin

    Great info, hope I'll be able to track al outbound links.