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.