Google Analytics doesn’t track file downloads automatically. I needed unobtrusive and framework agnostic download tracking for Google Analytics. That’s when Entourage.js was born.
Entourage.js is Automatic Download Tracking for Asynchronous Google Analytics.
To be honest, I wish this extension wasn’t necessary. I wish Google Analytics tracked file downloads automatically and out-of-the-box, but it doesn’t. An extension was needed - so be it. But if it was going to be done, I wanted to make sure it was done right!
I set goals for Entourage.js before a single line of code was written. Entourage.js needed to embody the following:
Google suggests adding an onClick event to each anchor tag you use for file downloads. I don’t want to have to do that each time I have a download. I would rather drop an extension that would do this consistently and automatically each time.
Entourage.js automatically tracks the name and extension of each file downloaded with the following convention:
For example, in Google Analytics Top Content, the downloads Entourage.js would look like:
Entourage.js also had to be framework agnostic. I know a lot of people have or will roll framework specific solutions. That’s great for them, but it wasn’t going to work for me.
I use and love jQuery just as much as the other guy. In fact, I use it in all of my company’s products. That said, there are people with just as much love for Prototype.js or MooTools.
I respect that. I don’t believe they should have to download another framework in this case. I don’t believe a framework is critical to this solution scope at all.
This is Google’s recommended way to track downloads:
I believe in standards based development. I believe we honor our profession when we encourage each other towards best practices.
I believed then and I believe now that the spirit of the solution is best honored with an Unobtrusive implementation that leaves the structure of the HTML5 markup clean and readable. Entourage.js does just that.
The final goal of the project was to have a small footprint. I needed something that was fast to download and painless to install in each project. I needed the extension to be as small as possible.
Here’s were we are at today:
Compiled and gzipped, Entourage.js is less than 1kb. It’s fast, dependable and - for now - I’m happy with the results.
Installation is clean and simple. Download Entourage.js. Place the following script declaration in you head tag:
Just above your Google Analytics Queue array declaration:
Then place your asynchronous call to load Google Analytics to somewhere just before your body tag:
Follow a similar hierarchy and you are set.
The simplicity and ease-of-use speak for themselves. But, I also believe in sharing and I think there is much we can learn from dissecting the internals of Entourage.js.
All 579 bytes of the code base are broken up into three top level modules: The Event Handler, Entourage and GetFileName.
This means Entourage.js introduces no new Global variables. So there is no chance of objects from extension clobbering objects in your project.
Entourage.js is completely independent and self-contained. This means you can plug it into your own project - worry free! There’s value there.
The event handler caches a list of document links. Then it assigns the Entourage callback to each link’s onclick event. Many would create custom events to monitor this behavior, but I find the native onclick event more than adequate for the job.
Also, it’s important to note the onload event. Executing after the onload event has fired ensures the DOM is loaded by the time Entourage is ready to go to work.
Another interesting note here is the ever vigilant for loop. I could have used a for in loop like this:
The problem here is each link object is not ordered as you would expect. Also, since hasOwnProperty is a method, it could be overwritten or replaced with an unexpected value. This could cause bugs that are hard to track.
Overall, I found the simple for loop fast, adequate and less prone to logic errors.
Some of the more popular file downloads to track are: *.pdf and *.zip
Once you’re in Entourage, that means the link’s callback was called. At that point, the variable this now contains the link object. Here, the pathname is the link property of concern to us.
If the fileType is present in the whitelist, the pathname is used to extract the download’s fileName. Then the download’s autograph is added to the Google Analytics Queue.
I chose to use _trackPageview to track the file download. The download metric would then show under Top Content as a PageView metric.
Another option is to use _trackEvent to track the file download. In my mind, _trackPageview via Top Content felt more simple and accessible, so I chose that route. Reasonable minds could differ here, so I’ll leave it to the SEO Experts to debate which is “best”.
Get True FileName from Link Pathname
Still with me? Good! GetFileName is probably thee most important method in Entourage.js!
It is incredibly difficult to extract a download’s fileName from a link’s pathname property.
There could be a hash (#) in the URL. You have to account for this.
There could also be a query (?) in the URL. You have to account for this.
And, of course, there is the fully qualified URL preceding the fileName. You have to account for this too.
You have to account for each situation and most times that isn’t easy. Entourage.js accomplishes each scenario well, without bloated code or overcomplicated algorithms. Clean and Simple.
The Big Picture
The Big Picture is I believe you’ll love Entourage.js. It’s lightweight and standards based with measurable goals and forethought.
Bottom line is if you need to track downloads with Google Analytics, then don’t roll your own framework. Download Entourage.js and spend less time coding and more time working on your core business.
Update: Entourage.js 1.1.0
####10,000 Foot View
Single Global Variable: Inspect the DOM, you’ll find a single Global Variable called entourage.
Public and Private Members: Used the Module Design Pattern to establish both public and private object members. It’s a little less restrictive than Object Literal Notation and gets the job done! Check the DOM, getFileName and autograph are not accessible outside the entourage namespace.
Cleaner FileType Whitelist: Reduced the whitelist to the most popular file extensions. Added support for Office 2007 documents and Open Office documents.
Strict Comparison: Used strict comparison on conditionals. Increases reliability and increases speed.
Link Count Cache: Cached link.length for comparison during initialization. Link.length doesn’t have to be calculated each iteration - this increases the performance.
Global Namespace: Explicitly added Entourage to the Global Namespace.
JSHint: Ran Entourage.js through JSHint - a fork of Douglas Crockford’s JSLint. The Google Analytics Queue doesn’t exist until the onclick event. It didn’t like that, but that’s expected. Also, it didn’t like the new operator. Called it a “Weird construction”. I can deal with a little weird…Barring those two expected, I’d say Entourage.js passed 100%.
See an overview of the code at 10,000 FT:
Usability and User Experience
I follow a couple core principles when it comes to designing products. At the base of the pillar is Usability and User Experience. I kept _trackPageview because I believe it is more usable and provides a better tracking experience.
From discussion, I think we’ve seen that neither _trackEvent or _trackPreview offer the “perfect” solution. Both skew the data. Analyzing my own Google Analytics data, I can say - with peace of mind - the skew is neglible at best.
Once the data is skewed, I believe the question of which method skews the data most is less relevant than thee most important metric - Usuability.
I setup an experiment to test this idea. One implemented Entourage.js as a _trackEvent and the other as a _trackPreview. To get access to download count for a file, I found this:
Two extra clicks for _trackEvent. That really is a big deal! But, even if I find it negligible, what wasn’t negligible was how I felt using Top Content via _trackPageview versus Event Tracking via _trackEvent.
Using Top Content, I felt the User Interface was easier to use and I felt like I could get to my data quicker. I felt the opposite with Event Tracking.
With Event Tracking, I felt the segmentation was overkill and I felt it wasn’t necessarily suited for the file tracking problem domain. I could understand if I had an app or video where I wanted to track feature usage - I get that! But here, all I want to do is track file downloads and I felt Event Tracking got in the way more than it helped.
Of course, other than the extra two clicks, everything I’ve said about Event Tracking is purely subjective. It’s how I feel about that aspect of Google Analytics’ Interface. Others - no doubt - will have their own personal opinion. I’m Ok with that! Please feel free to express the same in the comments.
Unfortunately or Fortunately - I’m undecided - you can find sources supporting either side on whether we should use _trackPageview or _trackEvent.
Maybe it’s just me, but maybe our Google Overloads want us to realize something:
It’s more important how you use the data than how you view it.
@Rene: Thanks for suggesting to make the whitelist more readable.
@Justo @Scott: For highlighting the _trackPageview and _trackEvent issue and putting it up for discussion.
@X10: For catching the repeating file type.
@Rob: For bringing some clarity to _trackEvent affect on Bounce Rate.
@Stjepan: For suggesting the faster for loop and bringing some technical depth to the discussion.