Google Analytics
for Web Developers

The features you're not using,
but probably should be.

Philip Walton / philipwalton.com / @philwalton

Question:

How many people here use Google Analytics?

How many of you do more than just copy and paste the JavaScript tracking snippet?

How did we get here?

Websites used to be so simple.
One request. One pageview. The End.

Now the web stack is extremely complex, and sites are more interactive than ever.

Yet most developers still just copy and paste the snippet, which only tracks a few basic metrics.

The goals of this talk

I know I can't possibly teach you everything about Google Analytics in 45 minutes.

Instead, I hope to get you thinking, show you some things you may not have seen, and inspire you to learn more on your own.

Fundamentals

The Analytics Data Model

Users  →  Sessions  →  Hits

One or more hits belong to a session, and one or more sessions belong to a user.

What does a hit look like?

Hits are HTTP requests sent to the Measurement Protocol:

https://www.google-analytics.com/collect

For example:

https://www.google-analytics.com/collect?v=1&t=pageview&tid=UA-70063124-1&cid=1715546980.1443552756&dl=http%3A%2F%2Fwww.example.com&ul=en-us&de=UTF-8&dt=Test%20Page&sd=24-bit&sr=2560x1600&vp=1265x869&je=1&fl=19.0%20r0

Dimensions & Metrics

A metric is a quantitative measurement. It's always a numeric type. (Session, Pageviews)

A dimension is a cross-section of a metric. It's usually a string. (Browser, Country)

Dimensions and metrics can be scoped to a:

Features

Tracking pageviews

You can use pageview tracking to find out what pages people are visiting on your site.

Pageview tracking is included in the JavaScript tracking snippet.

The JavaScript tracking snippet

(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-XXXXX-Y', 'auto'); ga('send', 'pageview');

What does this code actually do?

When in doubt, use the debugger!

The debug version of analytics.js makes it easy to see exactly what's going on under the hood:

(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_debug.js**','ga'); Debugger demo →

Cool, so pageview tracking code is included in the default JavaScript tracking snippet, which means I don't have to worry about it…right?

Dun, dun, dun!

What about Single Page Applications?

The snippet tracks the initial pageview, but does it also listen for changes to the URL and track those?

Let's find out →

When building single page applications, it's important to always update your tracker objects whenever any page-related data changes.

Learn more →

Tracking events

You can use event tracking to capture generic user interactions that happen during a session.

Event hits contain the following dimensions:

Usage

ga('send', 'event', { eventCategory: 'Outbound link', eventAction: 'click', eventLabel: link.href });

or...

ga('send', 'event', 'Outbound Link', 'click', link.href);

This code tracks click events on links to external sites:

ga('create', 'UA-12345-1', 'auto'); $(document).on('click', 'a', function() { if (this.hostname != location.hostname) { **ga('send', 'event', 'Outbound Link', 'click', this.href);** } });

But actually, there's a problem.

View the problem →

Setting the transport to "beacon" will ensure hits are always sent. Fall back to opening in a new tab.

ga('create', 'UA-12345-1', 'auto'); **ga('set', 'transport', 'beacon');** $(document).on('click', 'a', function() { if (this.hostname != location.hostname) { **if (!navigator.sendBeacon) this.target = '_blank';** ga('send', 'event', 'Outbound Link', 'click', this.href); } }); View demo →

Tracking performance

You can use user timing tracking to measure how long it takes something to happen.

Timing hits contain the following dimensions:

And the following metric:

Usage

ga('send', 'timing', { timingCategory: 'Fonts', timingVar: 'load', timingValue: elapsedTime, // Up to you to calculate timingLabel: 'fonts.googleapis.com' });

or...

ga('send', 'timing', 'Fonts', 'load', elapsedTime, 'fonts.googleapis.com');

This code tracks how long it takes to load Google Web Fonts on your site using webfont.js:

<script async src="//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script> <script> performance.mark('fonts:start'); WebFontConfig = { google: { families: ['Lobster::latin'] }, active: function() { performance.mark('fonts:end'); performance.measure('fonts:load', 'fonts:start', 'fonts:end') var fontsLoad = performance.getEntriesByName('fonts:load')[0]; **ga('send', 'timing', 'Fonts', 'load', fontsLoad.duration);** } }; </script> User timing demo →

Tracking exceptions

You can use exception tracking to discover when your code fails in unexpected ways.

Exception hits contain the following dimensions:

Usage

ga('send', 'exception', { exDescription: error.message exFatal: false // Optional });

This code tracks any errors in the following function:

try { someFunctionThatIsKnownToBeFlaky(); } catch(error) { **ga('send', 'exception', {exDescription: error.message});** } Exception demo →

As JavaScript Promises gain popularity, exception tracking for asynchronous code will be as easy as appending a .catch() handler to a promise chain:

fetch('/my-api-endpoint.json') .then(convertResultToTsv()) .then(saveDataToTheDataStore()) .then(informAnyListeners()) .catch(function(error) { **ga('send', 'exception', {exDescription: error.message});** });

You can even track "uncaught" exceptions:

window.onerror = function(message, url, line, col) { var desc = message + ' (' + line + ':' + col + ') URL: ' + url; **ga('send', 'exception', {exDescription: desc});** };

What if there's something I want to track
that's not built in to Google Analytics?

Defining your own
dimensions & metrics

You can create custom dimensions & metrics to track and categorize data not already captured by Google Analytics.

Custom dimensions & metrics are just like regular dimensions and metrics, but they're user-defined.

Examples of a custom dimension

Examples of a custom metric

Breakpoint tracking

When building a responsive website using media queries, it's important to know what media query is active.

This is data that viewport size and device type alone cannot accurately tell you.

The active media query is just another dimensions you can track!

Using custom dimensions

var breakpoints = { sm: '(max-width: 767px)', md: '(min-width: 768px) and (max-width: 991px)', lg: '(min-width: 992px) and (max-width: 1199px)', xl: '(min-width: 1200px)' }; Object.keys(breakpoints).forEach(function(breakpoint) { var mql = window.matchMedia(breakpoints[breakpoint]); if (mql.matches) { **ga('set', 'dimension1', breakpoint);** } }); Breakpoint tracking example →   Learn more →

Custom Reporting

If you're sending custom data to Google Analytics, it's essential that you know how to report on that data.

Examples

Open Google Analytics →

Filters vs. Segments

A filter eliminates rows from the result set returned by a query.

A segment narrows the original data that the query operates on.

Final thoughts

As the web changes and becomes more complex, it gets harder and harder to rely on one-size-fits-all solutions.

Measuring user interaction is critical to making informed decisions about your site or application.

As you're attending the talks, and learning about new technologies, keep these analytics concepts in mind.

The End

Twitter
@philwalton
Website
philipwalton.com
Github
github.com/philipwalton
Slides
github.com/philipwalton/talks