a walk through the new google analytics code

Google is holding public beta for their new Universal Analytics product. The tracking code is an interesting read, and in any case it’s probably a good idea to know what’s happening with a script you include on a page.

Here it is in its entirety.

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXX-Y');
ga('send', 'pageview');

That’s a little much, so let’s break it down.

The immediately invoked function expression (pronounced “iffy”) is a common javascript idiom. By taking advantage of function level scope the code inside is protected from the rest of the page. Here the parameters to the function are single characters to minimize the code, aliasing longer variables like window, document, or the string 'script'.

(function(i,s,o,g,r,a,m) {
  …
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

I find it amusing the developers chose to spell out the word “isogram” with the function parameters, since their very use is an application of the principle Don’t Repeat Yourself.

If you counted you noticed there are seven parameters named but only five passed in. This little hack declares a and m to be local variables as well, but in four characters fewer than an explicit var statement.

  i['GoogleAnalyticsObject'] = r;    // r = 'ga'

Remember that i means window, so the first thing to do is set a global variable named GoogleAnalyticsObject that says the name of the real analytics object, which we’ll create next.

This fragment features another javascript idiom, the conditional assignment. The phrase a = a || b initializes a with b only if a is not already defined.

  i[r] = i[r] || function() {
    …
  },

Keeping in mind that r is the name of the analytics object ('ga'), we define it as a function in the global scope (a property on window). When the function ga is called, the arguments array is added to the queue (q), which is itself initialized if necessary.

// window.ga = function() {
    ( i[r].q = i[r].q || [] ).push( arguments )
// }

Now that we’ve initialized the analytics object, let’s set the load time of the page to the current time. The multiplication by one coerces the date into a regular number, a timestamp.

  i[r].l = 1 * new Date();

Now we’ll make use of the local variables a and m. They’ll both be script tags, a a new one and m another already on the page.

  a = s.createElement(o),         // o = 'script'
  m = s.getElementsByTagName(o)[0];

Set the new script tag to load Google’s analytics script (asynchronously, if supported) and then append the tag to the page.

  a.async = 1;
  a.src = g;    // g = 'http://url.of.analytics/script'
  m.parentNode.insertBefore(a,m)

Finally we make use of the global ga function defined above to add two items to the event queue: the creation of the tracker and the initial pageview.

ga('create', 'UA-XXXXXXXX-X', 'example.com');
ga('send', 'pageview');

At this point we can inspect ga and see the following structure.

window.ga.q = [
  ['create', 'UA-XXXXXXXX-X', 'example.com'],
  ['send', 'pageview']
]

The browser is now fetching Google’s script asynchronously. When it loads, the events in the queue will finally be sent to the server.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>