10 Ways Your Google Tag Manager Setup Might Be Broken

Last year, I wrote two posts about ways that your GA setup might be broken without you realizing it.  Since then, Google Tag Manager has exploded onto the scene, earning a 62% tag management market share of the top 100,000 websites.  Compared to last year, usage of GTM on these sites has grown an impressive 142%.

As with Google Analytics, you can get started relatively easily, but also easily fall into data collection dangers, inadvertently corrupting your data without realizing it.  Below are 10 of the most common issues we see with GTM setups, often as they relate to Google Analytics.  Avoid these pitfalls as you head into the new year!

1) You specify element-level conditions with "Enable When" instead of with "Fire On."

GTM has two configuration options that sound similar, but have important differences -- “Enable When” and “Fire On.”

Here’s “Enable When” --

“Fire On” appears directly below --

The “Enable When” option will appear when you choose to “Check Validation” or “Wait for Tags.”  In most cases, you should wait for tags on link clicks and form submits.  Waiting avoids race conditions where a click moves the user away from the current page before the tracking has a chance to fire.  Race conditions often lead to severely undercounted event data.

Because checking for validation and waiting for tags uses JavaScript to modify the behavior of your site, there’s the small possibility that these options will affect your actual site functionality.  As a result, GTM encourages you to add these listeners in as few places as possible.  For example, if you only need to track form submits on a single donation page, then you can listen for events only on that page.

“Enable When” relates to when the event listener actually listens, while “Fire On” relates to when Tag Manager should send the tags.  Here’s where you can go wrong: you add element-level conditions -- such as class, id, or destination URL -- to the “Enable When” condition instead of the “Fire On” condition.  The listener currently only respects page-level definitions (such as page URLs or attributes defined in the dataLayer ahead of the Tag Manager script).  It will ignore element-level definitions: “Enable When” either applies to a page, or it doesn’t.  As a result, if you handle all configurations through “Enable When,” only your page-level conditions will apply, and you’ll likely fire your tracking on unexpected interactions.

Unless you can restrict your listener based on a page-level condition, you should “Enable When” the URL matches the RegEx .* (all URLs), and always handle element-level conditions through the “Fire On” section.

2) You mix inline tracking with GTM-only tracking, but don’t specify an empty tracking object in GTM.*

Maybe you have pre-existing pageview and event tracking directly on your site, but you decide you want to use GTM to build on it.  You can certainly mix on-page and GTM tracking, but you need to take special care.  Google Analytics uses tracking objects; one use case is for tracking to two web properties.  In that instance, you must specify a second tracker name:

 <span style="line-height: 1.6em;">ga('create', 'UA-XXXXX-Y', 'auto');</span>
ga('create', 'UA-XXXXX-Z', 'auto', 'arbitrarySecondTrackerName');

By default, on-page GA code uses an empty tracker name.  Tag Manager, on the other hand, uses a dynamic randomly generated tracker name in order to prevent settings from one GA tag from accidentally applying to another.  If you've set tracker-wide settings and you want to unify your on-page and GTM tagging, then you need to define an empty tracking object in GTM.

Do so in your GTM Google Analytics tag by selecting “More Settings” > “Advanced Configuration” > “Set Tracker Name”, checking its box, and leaving the tracker name blank (assuming your on-page GA code uses an unnamed tracker).

If you add any GA tracking through a Custom HTML tag instead of the template, consider it the same as if you had added the script directly to your site -- you’ll need to specify an unnamed tracker in any of your template tags that do use GA.

(* Update: As Simo points out in the comment at the bottom of this post: 1) There are certain instances when this setup will not break your tracking. 2) The tracking can break if you've set tracker-wide settings in the on-page tracker and 3) Using named trackers in GTM can have other implications, like unintentionally sending hit-scoped custom dimensions with subsequent hits on the same page that you didn't intend. Thanks, Simo!)

3) You declare the dataLayer or use dataLayer.push in the wrong places.

We see people make this mix-up surprisingly often.  Follow this simple rule:

If adding code ahead of the main GTM snippet, define the dataLayer.  If adding code after the main GTM snippet, push to the dataLayer.

You often may want to add information to the dataLayer ahead of the GTM snippet loading.  Examples include defining page types or product SKUs.  When you define it ahead of the GTM snippet, you can access this information on-load of a pageview.

Ahead of the GTM snippet, you’d add something like:

 dataLayer = [{
 'pageType': 'Product Detail Page',
 'productPageSku': 'ABC123'
 }];

When the Tag Manager snippet loads, it defines a dataLayer if one does not already exist.  So, if you add the code shown above, but put it after the GTM snippet, you’ll overwrite the dataLayer variable and break your tracking on the page.

If you need to track certain information after the GTM snippet has loaded -- for example, sending an event -- you do so using dataLayer.push instead:

 <span style="line-height: 1.6em;">dataLayer.push({'event': 'event_name'});</span>

If you push to the dataLayer ahead of the main GTM snippet, you’ll get a JavaScript error because the variable hasn’t been defined yet.

4) Outside of GTM, you have additional event listeners that are using event.stopPropagation().

When you use event.stopPropagation(), you prevent an event from bubbling up the DOM tree.  As a result, events such as link clicks stop before they reach GTM, and GTM never hears them.  Clicks can recover from use of event.stopPropagation(), but link clicks cannot.  When you’re debugging, if GTM is only detecting a click event (which can’t wait for tags) but no link click event on a link, check to see if other event listeners are stopping propagation of the event.

5) You use "contains" in a trigger condition that can be case-insensitive.

“Contains” operators in Google Analytics are case-insensitive, so you may expect that the Tag Manager “contains” operators work the same way.  Not the case!  If your conditions should be case-insensitive, use the “matches RegEx (ignore case)” operator instead.  Otherwise, triggers may not work as consistently as you think.

6) You use a Universal Analytics tag, but don’t add in a field to set cookieDomain to ‘auto’.

The tracking code that the GA admin provides includes a line of code like this:

 ga('create', 'UA-XXXXX-Y', 'auto');

The ‘auto’ is important -- it specifies the domain where your cookies are set.  Usually, you will want to set your cookies at the highest-level domain possible, so that Google Analytics can automatically track across subdomains.  (Note: there are certainly exceptions and times when you need to set the cookie to a different domain, but these instances are relatively rare for most sites.)

When you use Tag Manager’s Google Analytics template, you’d expect that the default settings supplied are the same -- but the ‘auto’ cookieDomain setting is an exception.  You must manually specify this setting in GTM.  

What happens if you don’t?

Say you have two domains, www.example.com and blog.example.com.  If a visitor comes to www.example.com, the _ga cookie writes to “www.example.com”.  If a visitor then goes to the blog, a second _ga cookie will be written to “blog.example.com.”  To understand that these sessions actually came from the same user, GA must read from a shared cookie.  The ‘auto’ cookieDomain setting writes the _ga cookie at “.example.com,” allowing it to be read from both subdomains.

To set the cookieDomain in the template tag, select “More Settings” > “Fields to Set” > “Add Fields.”

7) You have inconsistent domain settings for pageviews and events.

With inline GA code, you don’t have to define the cookieDomain with each event you send.  In Tag Manager, you do.  Make sure that consistent cookieDomain settings (and any other custom settings) apply consistently across both your pageview and event tags.  The easiest way to ensure consistency is to make a tag containing all your correct settings, and copy that tag whenever you need to create a new one, modifying as needed.

8) You’ve left the “Check Validation” box marked.

In a trigger, “Check Validation” checks for event.defaultPrevented().  The setting will not fire tags if default actions are prevented -- but often, these tags are still valid.  I usually un-check this setting:

The downside to this change is that an event will still fire if a user unsuccessfully submits a form (for example, there’s a form field error).  I actually prefer to have this data, to compare total submits to unique submits.  And if you’re using the event as a GA goal, goals only increment once per session, so you won’t inflate your conversion data by firing events on unsuccessful submissions.  One inaccuracy you could potentially introduce is counting a goal if a user tries unsuccessfully to submit a form, never does, and then leaves -- you’d unnecessarily count a conversion there.  In my opinion, that caveat to the data is often worth the other benefits.

9) You set too many tags to fire on the same condition, exceeding the number of HTTP requests a browser allows.

This limitation is a result of browsers, rather than of Tag Manager, but the consideration is still important.  Browsers limit the number of HTTP requests that can happen at a time.  If you fire 10 different tags all on the same dataLayer event, for example, some tags will likely not fire.

(Thanks to Albert for suggesting numbers 8 and 9!)

10) You don’t cross-browser test.

This should go without saying, but cross-browser test as much as possible!  We’ve seen form submit tracking prevent forms from submitting in IE7 (though are you really still supporting that?).  Custom JavaScript variables should be QAed like any other code.

Browserstack is our current cross-browser testing method of choice.  Consider adding UTM parameters identifying each browser, testing for functionality, and then QAing the data that appears in your unfiltered GA view.  Make sure all your pageviews, events, and other data are appearing and associated with the UTM source and medium you specified.

As Google Tag Manager Partners, we see get a glimpse into the roadmap and vision for the product.  The team at Google is continuously investing to improve the product and make GTM as airtight and as possible.  Don’t be surprised if, by this time next year, Google makes it a lot harder to make some of these mistakes!  What other common pitfalls have you come across?

Paul is a senior digital analyst, where he works with clients such as Stanley Black & Decker, the University of Virginia, Lenovo, and the Wildlife Conservation Society. He believes in using data to prove the value of creativity, cut out digital clutter, and resolve disputes.

More posts by Paul