Skip navigation
BLOG  |  DECEMBER, 2009

Google Analytics: Getting Out of the Way in a Good Way

December 1, 2009 at 10:55 am
by Nolan

Loading third-party JavaScript (which is code usually loaded from a domain on another server) can often do bad things to your pages' performance. Putting JavaScript on a page blocks, which in software-speak means that nothing else can happen while it is loading and executing. The reason for this is that JavaScript can change the page after it executes which means that the browser needs to wait until the code is done executing before it go on to the next thing. Why is this a problem?



The issue with loading JavaScript, especially third-party JavaScript, is that the your site's performance is at the mercy of someone else's server. If you put a piece of JavaScript code at the top of your page from another domain, the rest of your page will wait until their server responds. It's never fun waiting on someone else to finish their job so you can finish yours, and that is precisely what browsers have to do. If their server is slow, your page will be slow to load, too.

The currently recommended way to insert JavaScript is to place it as close to the bottom of your pages as possible. This allows the browser to download and get all the images, HTML, and CSS and render them so that your page will at least look presentable and be interactive until the JavaScript is finished loading. Most of the third-party JavaScript code we see at Newfangled are from site trackers, like Omniture and Google Analytics, and since these do not affect the page's structure at all, it is almost always best to put these at the bottom.

So why doesn't everyone always put the tracking code at the bottom? There is a slight downside to putting this tracking code at the bottom of your HTML. Let's say the page gets loaded and before the JavaScript is fully loaded, the user has already clicked on a link and is going to the next page. Since the browser hasn't loaded the tracking code yet, that user does not get counted. Granted, they need to be a quick clicker, but a visitor leaving the page before the tracking code is done can skew your tracking data and that is not a good thing.

And now for the well-buried lede, Google Analytics announced today that their Analytics code can be loaded asynchronously, which means that the browser doesn't need to wait on the JavaScript to download and execute before it can go on to the next thing. This means that the JavaScript can go to the top of the page, with little to no penalty on page performance, while improving the accuracy of your tracking data. Wins all around.

As a software engineer, I was curious how they got this to work, so if you're not interested in the nitty gritty, you can jump down to the comments section and leave a note--I won't mind a bit.

Taking a look at the snippet, the first thing you'll notice is that you don't call the tracker object's functions directly, but instead queue them up in an array-like object, called _gaq (which I presume stands for "Google Analytics queue"). There is a conditional assignment to _gaq: it looks for a _gaq object already in existence, or just uses an new array. An instruction will be pushed onto this object and the Analytics code executes it when it is ready.

The Analytics code from Google instantiates its own _gaq, which will happen at some arbitrary time during the page load. I imagine that when the Analytics code loads, it looks for a _gaq already set, if it sees it, it takes all the instructions listed in the extant array and transfers them over to their own _gaq object, and then loops through and executes them. Google's _gaq object has its own push method that probably calls the pushed function immediately. This is key to interfacing with the asynced Analytics code, as the tracker API stays consistent both before and after the Google JavaScript is loaded. This way you can scatter _gaq.push() throughout your page, and it is either queuing these instructions up for when the Analytics code is present, or executing them immediately if it the Analytics code has already been loaded. Nice.

The next part of the snippet listed is an anonymous function containing the instructions to create a script node, set the node's source to the Analytics code and appends it to the document. Creating the script node this way instead of the standard way with HTML allows this script to download and execute in a non-blocking manner. This anonymous function keeps the ga variable leaking out into the global namespace, which is a nice JavaScript idiom, and the proper way to write any JavaScript that will co-exist with other pieces of JavaScript.

The script node creation code also adds an "async" attribute to the script tag, indicating how the script is being loaded. Without this, the script would not know if it is being loaded in the traditional manner as just a normal script tag, or with the new async method and then act accordingly.

This is a nice improvement to Google Analytics and eliminates the trade-off between page performance and data integrity.


Comments
Brian Chiou | December 2, 2009 12:00 AM

Great post Nolan. Would you recommend using this 'beta' tracking code now? or, wait until Google releases it officially?


Nolan | December 2, 2009 12:00 AM

@Jillian: Thanks for reading!

@Brian: I'd say with Google's use of 'beta' it is probably good to go today. I would bet that someone using today would start to see more data and a probably slightly better conversion rates as the page loads would go down (less load time, more clicking). Thanks for reading!
Jillian Kuhn | December 2, 2009 12:00 AM

I can't say I followed all the 'nitty gritty,' but good post! A few of our clients have had issues with third-party javascript, and this certainly helps me better understand what's going on.