Turbolinks, Google Analytics, and Tracking

May 20, 2016

Turbolinks does not play well with Google Analytics’ recommended setup. I thought I had fixed Google Analytics(which I will refer to as GA from now on) tracking awhile back. My assumption was that adding analytics.js inside the <head> tag, and adding the following snippet right before the closing </body> tag would work:

<script>
  ga('send', 'pageview');
</script>

I thought that by adding the snippet, every time a page is swapped in by turbolinks the script should run and send GA a hit. This is not true. The location of the current page is not sent. Instead, the location of the first page that loaded the GA script is sent. This is because location is set when analytics.js creates the tracker for the current page1. In a website without turbolinks where every redirect to another page is a complete refresh, analytics.js is reloaded, g('create', 'UA-XXXXX-Y', 'auto'); is called, and the location is properly set. To fix this, I just needed to modify the data that I sent to GA. Instead of just calling ga('send', 'pageview'), I set all my fields explicitly.

<script>
  ga('send', {
    hitType: 'pageview',
    title: document.title,
    location: location.href.split('#')[0],
    page: location.pathname,
    transport: 'beacon',
  });
</script>

Tracking clicks to my resume

My resume link opens a PDF. There’s no way for me to run Javascript to send a pageview to GA, so I have to send a pageview right as the user clicks the link. This is simple, and there are lots of guides on Google about this behavior. It’s called an outbound link, but in my case, it’s a link to a page that cannot execute Javascript. I used the following snippet to achieve this.

<script>
var resumePath = '/assets/resume.pdf'
var trackResumeLink = function() {
  if (window.ga && ga.loaded) {
    ga('send', {
      hitType: 'pageview',
      title: 'resume.pdf',
      location: location.origin + resumePath,
      page: resumePath,
      transport: 'beacon',
      hitCallback: function() { document.location = location.origin + resumePath; }
    });
  } else {
    document.location = location.origin + resumePath;
  }
}
</script>

And the on the resume link itself, I added an onclick event handler.

<a href="/assets/resume.pdf" onclick="trackResumeLink(); return false;" class="nav-link">
  1. developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers