Cheat And Win With Google Tag Manager: Easy Dynamic Content Tracking

January 14, 2014 | Dorcas Alexander

Sometimes Tag Manager is so easy it feels like cheating. In a good way. Like getting a super acorn power-up and turning into Flying Squirrel Mario.


Recently I used my flying squirrel powers to beat the dynamic content boss. My client wanted to track how visitors used a couple different search forms, each with multiple options. Every time an option was selected, new search results would appear dynamically and a parameter would be added to the URL hash.

For example, if the visitor chose to view all the seminars on day 1, the URL would become /seminarsearch#day=1. Search those seminars by topic X and the URL would change to /seminarsearch#day=1&topic=x.

Or it might be a different search form, say for vendors, and the URL might look like /vendorsearch#category=abc&location=bldg2.

How was I going to tackle all those moving parts and get the data I needed into Google Analytics? I wrote a couple different pieces of code that were unsatisfactory for one reason or another.

And then I found my super acorn.


Deceptively simple! Don’t worry about listening for clicks and trying to identify if they’re the clicks I’m interested in. Just detect when the hash changes and send an event to the data layer. This tag fires on every search form page.

Now I use the data layer event to control all kinds of tracking. When a visitor interacts with one of my search forms, an event rule (“event=hashchange”) fires these tags:

  1. a virtual pageview – it’s a new page of content, so I treat it that way – I capture the URL with the hash, which means for each of those extended URLs I get all the page metrics in my GA content reports (not to mention more useful flow viz reports and the ability to create goal funnels, although I haven’t done that yet)
  2. a search form click event – so I can get site usage and ecommerce metrics, along with the hierarchy of the GA event reports
  3. plus scroll tracking events! – from Justin Cutroni’s scroll tracking code, which I adapted for Tag Manager (did the visitor start scrolling through the search results and did they scroll all the way to the bottom? I included the custom variable for how fast they scrolled)

Here’s the adapted part (get the entire original tag here):

// If user starts to scroll send an event
if (bottom > scrollerLocation && !scroller) {
    currentTime = new Date();
    scrollStart = currentTime.getTime();
    timeToScroll = Math.round((scrollStart - beginning) / 1000);
    if (!debugMode) {
        dataLayer.push({'event':'scrolling', 'eventAction':'start-scrolling', 'eventLabel':'{{url path}}', 'eventValue':timeToScroll});
    } else {
        alert('started scrolling ' + timeToScroll);
    scroller = true;

// If user has hit the bottom of the results, then send an event
if (bottom >= $('#results').scrollTop() + $('#results').innerHeight() && !endContent) {
    currentTime = new Date();
    contentScrollEnd = currentTime.getTime();
    timeToContentEnd = Math.round((contentScrollEnd - scrollStart) / 1000);
    if (!debugMode) {
        if (timeToContentEnd < 30) {
            dataLayer.push({'customVarKey':'scroller-type', 'customVarValue':'scanner'});
        } else {
            dataLayer.push({'customVarKey':'scroller-type', 'customVarValue':'reader'});
        dataLayer.push({'event':'scrolling', 'eventAction':'content-bottom', 'eventLabel':'{{url path}}', 'eventValue':timeToContentEnd});
    } else {
        alert('end content section '+ timeToContentEnd);
    endContent = true;
    didComplete = true;

The scroll tracking tag fires either after the window loads or when the hash changes, with a simple revision of the rule from "event equals hashchange" to "event matches RegEx gtm.load|hashchange". That way I don't have to wait for the visitor to click any options, in case they start scrolling through the default content (featured seminars or vendors).

And then finally I have tags that fire when the scroll tracking tag pushes events to the data layer. These tags send my events and custom variables to Google Analytics.

custom var gtm

Remember: to make sure your custom variable info is not just set, but also sent, hitch it to an event. Tag Manager makes it easy with the options under "More Settings" as shown above.

Has dynamic content made it more difficult to get the data you need to answer important questions? How have you tackled it? Please share in the comments.