Double Tracking in GA without Named Trackers – Part 1

This is a post in three parts. This first part covers the problem we want to solve, and introduces the concept of “tasks” and “plugins”. The second part takes a look at the code for a GA plugin that aims to solve the problem, while the third part goes into the configuration options. So if you are not interested in background information you might skip this (and possibly the second) part.

David Vallejo ak.a. “thyngster” is, much like me, a web analyst who keeps a blog and likes to share information with others – to that effected he has started a “hackathon” , an opportunity for programmers to work together on a piece of code. The idea is to create a plugin for the Universal Analytics tracking code that allows data to multiple properties.

As I’ve said before I’m not that interested in plugins (since I cannot use them in Google Tag Manager and I’m very much a GTM guy), but I am interested in communicating with like-minded people, so I took a stab at this. You can watch my results at github (this still needs a bit of work before I can do a pull request), but maybe I start by explaining what problem is supposed to be solved by this.

A Word of Warning First

As with the other posts on this blog this is not development proper, this is doodling, i.e. implementing an idea to a degree that demonstrates the principle without looking to much at edge cases. Unlike with the other code in this blog this is dangerous with a GA plugin – all other examples here run in a specific context (your command line, or a specific browser) and not much harm is done if they fail.  The point of a GA plugin is that it is deployed to the wild and runs in your clients browsers – if anything goes wrong here there might be greater harm; the plugin might not work, it might break your tracking, or it might break other JavaScript on the page alltogether. I have done a few common sense things, looking at the results with different browsers, including polyfills for some array functions in older browsers etc. But this is not in any way rigorously tested like the code provided by Google, so if you plan on actually using this you should do your own testing first.

The Problem

Well, it’s not actually a problem, more of an inconvenience (am I’m using that right ? What I mean is  “a pain in the buttocks”). There are use cases where you want to track to multiple GA properties – e.g. if you do not have a premium account and still want to rollup reporting, or if you want to allow a third party to implement tracking code on your site (not a good idea but apparently a real life use case). If you simply create two default trackers the second will overwrite the first and you will track to only one property. The usual approach to deal with this is to create named trackers (or one default tracker and one tracker with a name; the default name is “t0”):

ga('create', 'UA-123456-7', 'auto');
ga('create', 'UA-765432-1', 'auto', 'myTracker');
ga('send','pageview');
ga('myTracker.send','pageview');

The obvious problem is that not only do you have to create two trackers, you also have to do all interaction calls twice, once for each tracker. Not a big problem with just a pageview, but when you implement event tracking and user timings and social trackings and transactions you might end up with a lot of redundant code (to shove in a bit of advertising for my favorite tool, GTM automatically creates named trackers using a random name, so you can implement any number of tracking tags without having them interfere with each other).

There are different ways to deal with that. One is to not directly implement tracking calls, but to put them in a wrapper function that collects all available trackers, iterates through them and makes the call for each of them. The other approach involves modifying “tasks” in Google Analytics.

Tasks in GA

As the documentation says

Each time the send command is called, analytics.js executes a sequence of tasks to validate, construct, and send a measurement protocol request from the user’s browser to Google Analytics.

So tasks are javascript functions that are called one after another when you want to send data to GA, to verify that there is actually a working configuration to allow the call to be made.  There is a check if the page is actually visible or rendered in a browsers preview window, if the code is able to set cookies, if the code needs to take into account information from older GA code versions (e.g. the notorious utm cookies), and tasks which retrieve data from the browser and assemble it into the “payload”, the string that is finally sent to the Google servers where it’s evaluated and used to populate reports.

Tasks are designed to be hackable, and in fact Google’s own example shows how to send a duplicate hit (in this case to a local url) in the aptly named sendHitTask:

ga(function(tracker) {

 // Grab a reference to the default sendHitTask function.
 var originalSendHitTask = tracker.get('sendHitTask');

 // Modifies sendHitTask to send a copy of the request to a local server after
 // sending the normal request to www.google-analytics.com/collect.
 tracker.set('sendHitTask', function(model) {
 originalSendHitTask(model);
 var xhr = new XMLHttpRequest();
 xhr.open('POST', '/localhits', true);
 xhr.send(model.get('hitPayload'));
 });
 });

ga('send', 'pageview');

This modifies the “sendHitTask” (the javascript function in charge of sending the data) to send a copy of the “payload” (the actual tracking information) to the local/relative Url “/localhits”, useful for example if you want to collect the raw data for your own analysis. The original sendHitTask is stored to a variable and executed alongside the local hit. I think you can see now where this is heading.

Executing Tasks in a Plugin

If you override the sentHitTask the target url does not have to be your own server. It might as well be a remote URL, for example a hit to another Google Analytics  property. The payload is by definition already a valid url string for a tracking call, and all you have to do is to change the parameter that determines in which property the hit is supposed to be collected. You can do it from within a GA plugin.

Again the documentation:

Plugins are scripts that enhance the functionality of analytics.js to help solve problems and aid in measuring user interaction.

People have always hacked into the GA tracking code, but now there is a sanctioned and documented way to do so. The documentation gives us this as the most basic example for a plugin:

// Defines the plugin constructor.
function MyPlugin() {
  console.log('myplugin has been required...');
}

// Registers the plugin for use.
ga('provide', 'myplugin', MyPlugin);

In this case “MyPlugin” is the actual plugin code where you’d implement whatever feature you want to add to GA – for example accessing and amending the sendHitTask of the tracker to implement a duplicate hit. The “provide” call to the command queue informs the GA code that a new function is now available.

Of course every realistic implementation will be much more complicated. I will not go into any detail here, the linked documentation is rather good and you can look into the github repo how I implemented specific solutions.

Rather I will, in the second part to this post, explain how the “Dual Tracking” plugin is used, and I think this helps more to understand the way plugins work than turning this into an exploration of  JS code. So stay tuned for the sequel.

 

Leave a Reply

Your email address will not be published. Required fields are marked *