Here’s a tip on how to avoid a horrible, horrible mistake with Google Tag Manager.

Tip 7: Always use .push() with dataLayer

When you assign a value to a variable using the equals ( = ) sign, you are actually reallocating the variable to a new value, and the garbage collection system of the runtime environment sweeps the previous value to bit heaven.

Let’s put it simply: if you redefine dataLayer after the GTM container snippet, you will break GTM’s proprietary functions. No, I’m not trying to be dramatic, it’s the truth. You cause havoc because GTM modifies the native push() method that all Arrays have, adding stuff of little importance such as a listener which fires tags when an ‘event’ key is pushed!.

By redefining dataLayer your tags will no longer fire. Oops!

But hey, we’re often instructed to use variable assignment when creating dataLayer before the container snippet. Right? Well, yes, that’s what we’re instructed to do but that’s not necessarily the best practice. Having just one declaration there works like a charm, but what about:

  <script>
    dataLayer = [{
      'businessCriticalVar' : 'businessCriticalVal'
    }];
  </script>
  ... some other code ...
  <script>
    dataLayer = [{
      'anotherCriticalVar' : 'anotherCriticalVal'
    }];
  </script>
</head>
<body>
<!-- GTM Container Snippet -->

Well, you might have guessed it. The second assignment overwrites the first one, and dataLayer only has anotherCriticalVar available for the benefit of your tags.

So how to avoid this?

Simple: use only push() when interacting with dataLayer. That way you’ll never overwrite anything in the Array, you’ll just add new stuff to the end.

In GTM tags (Custom HTML, for example), you can just go ahead and use dataLayer.push(), since you can be 100 % sure that dataLayer is an Array with a push() function (the container snippet takes care of this for you). But when you’re working on the page template, where it’s not necessarily a given that dataLayer has been defined as an Array, always use the following syntax to safeguard against problems:

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  'someVar' : 'someVal'
});

The first line basically checks if a global variable called dataLayer has already been declared. If it has, it’s left alone and execution proceeds to the push() block. If, however, dataLayer has NOT been defined, the first line then assigns a new, empty Array to it. This ensures that the following push() will always work.

So here’s the recap:

  1. When working on the page template, always check whether or not dataLayer has been defined, and initialize it as a new Array if necessary

  2. Always, ALWAYS, use push() when interacting with dataLayer

DISCLAIMER: The window.dataLayer = window.dataLayer || []; fails if dataLayer HAS been defined but not as an Array. This is probably quite rare, but you should be aware of what variable has been assigned to GTM by looking at the container snippet’s self-invoking function parameters.