Skip to content
A simple google analytics event tracking helper.
Find file
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Track That

Code Climate

A small javascript library that makes implementing Google Analytics Event Tracking super easy

Requires jQuery 1.3 or greater


  • A DSL for grouping and defining tracking events
  • DevMode for ensuring the correct data is being sent to GA before you roll to production
  • Use of jQuery's on() function means you can handle js events of all types (default is click)
  • Allows for binding events to DOM elements that get loaded via AJAX
  • Encourages separation of tracking functionality from other page logic
  • DSL minifies nicely due to array style paramater passing

Getting Started

Basic Usage

Install and Setup

Add track_that.js to your project and ensure it gets loaded by your pages.

Now you can start defining event definitions. These will need to be run after the page is ready.

It is also a good idea to wrap this section in a call to TrackThat.enabled(). This is not required, but will speed things up if Google Analytics is not included on the page.

$(document).ready( function(){
  if( TrackThat.enabled() ){
    // insert tracking definitions here

Now that you know where to put your calls to TrackThat, let's look at some basic use cases.

Click Tracking

category() is used to define a group of events that all share the same Category.

The two params are a string and an array of event definitions (also arrays).

TrackThat.category('Home Page', [
    ['Sidebar', 'Callout Click', $('#sidebar_callout')], // event definition 1
    ['Sidebar', 'Ad Click', $('div.sidebar_ad')]  // event definition 2

The first param in the event definition ('Sidebar') is the Action and the second ('Callout Click') is the Label. The third is a jQuery result of the element(s) you wish to bind the event to.

When a user clicks the matching element, the specified strings will be sent to Google Analytics. For example, any .sidebar_ad click will trigger a

_gaq.push(['_trackEvent', 'Home Page', 'Sidebar', 'Ad Click']);

Google Analytics only requires a Category and Action. If you wish to omit Label, you can pass '' or null for the label param.

Dynamic Values

The previous definitions are great if you want to send the same 3 strings to google for similar events but we often need to track things more dynamically. For example let's say you want to track usage of a navbar:

<ul id='top_nav'>
  <li><a href='/home'>HomePage</a></li>
  <li><a href='/artists'>Artists</a></li>
  <li><a href='/help'>Help</a></li>

You can track all three with one event definition

TrackThat.category('Navigation', [
  ['Top Nav Click', 'text()', $('#top_nav a')]

When a link is clicked, the value for the Label will be obtained by calling text() on the anchor tag. For example, if the help link was clicked, it would send 'Navigation', 'Top Nav Click' and 'Help'.

Other dynamic options are:

  • 'text()' - calls text()
  • 'val()' - calls val()
  • 'attr:xxx' - will call attr() with the parameter you specify in place of xxx
  • 'prop:xxx' - will call prop() with the parameter you specify in place of xxx

Action and Label values can both be obtained dynamically but Category must be a hardcoded string.

Advance Usage

AJAX Loaded Elements

The optional 4th param in an event definition is a jQuery selector to be passed to on(). For example, let's say you have a recommendation widget that loads some links in after the fact:

<div id='recommendations'>
  <!-- contents loaded via AJAX -->

You could track clicks to anchor tags indside #recommendations like this:

TrackThat.category('Sidebar', [
  ['Recommendation Click', 'attr:href', $('#recommendations'), 'a']

Non-Click Event Types

The final param to the event definition array is an event type. By default this is 'click', but let's say you have a select tag and you would like to track when a user changes it's value. You could do the following:

TrackThat.category('Filter Controls', [
  ['Dropdown Change', 'val()', $('#filter_controls'), 'select.sorter', 'change']

You can pass any event name that on() understands.

Manually Pushing An Event

As a last resort if you cannot get an event triggering properly (often due to a plugin/event calling .preventDefault ), you can manually send the data you want to GA using pushEvent():

TrackThat.pushEvent($(this), {category: 'Homepage', action: 'Sidebar', label: 'text()'} );

The action and label params support the same variable attribute values as TrackThat.category(): 'text()', 'val()', and 'attr:xxx'

You can also pass a function to pushEvent as long as you return category/action/label in a hash:

TrackThat.pushEvent($(this), function(elem){
  var act ='action') + ':' +'detail');
  return {category: 'Product Overlay Trigger', action: act, label: ''};

Dev Mode

If you set the following before your calls to category() ( and to TrackThat.enabled() )

TrackThat.devmode = true;

a javascript alert will trigger containing the Category, Action and Label values that would be sent separated by the pipe character. It looks like:

Sidebar | Recommendation Click | /help_page

Don't forget to remove the devmode line when you are done or it will behave the same way in production!

Best Practices

The more event tracking you have, the more insight you will have into how users interact with your website. However, you don't want this to have a large impact on javscript load times or to bloat the files sent to the user's browser. With that in mind, here are some things you can do to minimize the impact that event tracking has on your site's browser footprint:

Use Fast Selectors

Each event definition requires the use of jQuery selectors. If you have 50+ events defined, your code will now be spending much more time searching for DOM elements so you had best make these as efficient as possible. This article provides a good overview of selector optimization, but in short: use ID selectors when possible, avoid nesting selectors, and keep in mind that Track That is using on() for event binding.

// Bad
['Sidebar', 'Ad Click', $('.sidebar .banner_ad a')] // calls $('.sidebar .banner_ad a').on('click', function()...
// Better
['Sidebar', 'Ad Click', $('#sidebar'), '.banner_ad a'] // calls $('$sidebar').on('click', '.banner_ad a', function()...
// Best
['Sidebar', 'Ad Click', $('#sidebar'), 'a.ad_link'] // calls $('$sidebar').on('click', 'a.ad_link', function()...

Use Variables

If you repeat a string or a selector multiple times, you can achieve greater levels of javascript minification and faster run times by storing the values in variables and re-using them in each definition. For example, let's say you are tracking a bunch of events on the same section of your site:

TrackThat.category('Newsfeed', [
  ['Top Controls', 'Filter Click', $('#newsfeed'), 'a.filter'],
  ['Top Controls', 'Sort Click', $('#newsfeed'), 'a.sorter'],
  ['Top Controls', 'Reload Click', $('#newsfeed'), 'a.reloader']

There is a lot of redundancy here, none of which can be minified and the #newsfeed selection happens 3 different times. Let's optimize with some variables.

var top_controls = 'Top Controls';
var newsfeed = $('#newsfeed');

TrackThat.category('Newsfeed', [
  [top_controls, 'Filter Click', newsfeed, 'a.filter'],
  [top_controls, 'Sort Click', newsfeed, 'a.sorter'],
  [top_controls, 'Reload Click', newsfeed, 'a.reloader']

Just as readable to the developer, but can get minified down to:

var b="Top Controls";var d=$("#newsfeed");TrackThat.category("Newsfeed",[[b,"Filter Click",d,"a.filter"],[b,"Sort Click",d,"a.sorter"],[b,"Reload Click",d,"a.reloader"]]);

Use A Closure

Javascript compression can be greatest when the minifier is certain that variable names won't conflict. You can help them out by scoping all your tracking code inside a closure. I tend to do mine like this:

(function($, document) {
  // all your shtuff here
})(jQuery, document);


To my co-workers at Moxie Software for their feedback and input on this project.

Something went wrong with that request. Please try again.