When you use the dataLayer.push() command on a page with a Google Tag Manager container, you pass information to GTM’s internal data model and potentially fire tags (if the push() contained an event key). You can also add the eventCallback key to these pushes. The value of this key should be a function, and this function is then executed once the container finishes processing any tags that might have fired on that dataLayer.push().

This is useful if you want to give Google Tag Manager time to complete its operations before proceeding with other actions on the page, for example.

There’s a wrinkle, though. Because Google Tag Manager supports adding multiple containers to the page, the eventCallback is called once for every single container on the page.

“But I don’t use multiple containers on the page”, I hear you exclaim. Good for you! However, if you are running an Optimize experiment on the page, or if you are also loading gtag.js, eventCallback will be invoked once per each implementation thereof, too. Why? Because they use Google Tag Manager as the underlying tech.

In this tip, we’ll learn how to detect which Google Tag Manager container invoked the callback and use that to effectively deduplicate the execution of our code.

Tip 74: eventCallback automatically receives the Container ID as the method argument

The tip is simple (as these things usually tend to be). The Google Tag Manager container ID (e.g. GTM-12345) which invoked the eventCallback method will be automatically passed as a parameter to the function you have set up as the eventCallback.

If you have multiple containers on the page, eventCallback will fire once for each container, once they finish firing whatever tags the dataLayer.push() triggered. Each time a container invokes the eventCallback method, its container ID will be the argument.

As an example, let’s say I have three Google Tag Manager containers running on the site.

  1. Google Tag Manager container with ID GTM-12345

  2. Google Optimize container with ID GTM-23456

  3. gtag.js library collecting to UA-12345-1

Next, I’ll run the following code in the JavaScript console:

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'GTMEvent',
  eventCallback: function(containerId) {
    console.log('Container ID: ' + containerId);
  }
});

The output in the console looks something like this:

Container ID: GTM-12345
Container ID: GTM-23456
Container ID: UA-12345-1

As you can see, with each iteration of the callback, the container ID was automatically assigned as an argument to the function. With this information, it’s easy to deduplicate your eventCallback method so that it only reacts to the “correct” container.

For example, here I want to execute some code only when GTM-12345 invokes the callback:

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'GTMEvent',
  eventCallback: function(containerId) {
    if (containerId === 'GTM-12345') {
      // Run some code
    }
    // Ignore if not GTM-12345
  }
});

By simply checking what the container ID passed as an argument was, it’s trivial to make sure your eventCallback code isn’t executed over and over again with each additional container on the page.