Solving Google Tag Manager Race Conditions with eventCallback

Google Tag Manager is a great solution for implementing Web analytics on AJAX-heavy apps. But at times it may seem like it adds more complexity than it relieves. Synchronizing data and events in the dataLayer is an example of this. Sometimes you will want to fire a tag that aims to send data that will show up in the dataLayer after an AJAX call and because you don’t have any guarantee about the timing of this AJAX call you may run into a bit of a race condition.

Fire Events With Data

In the world of javascript you might rely on a call back function to solve this problem. This same idea works with Google Tag Manager, but it has its own way of going about it. The Google Tag Manager solution to this type of problem is to push an event to the dataLayer with the new AJAX delivered data and then set firing rules for any beacons that depend on that information to said event. For instance:


  "newDataAboutX" : {
    "thing1" : "xyz",
    "thing2" : 12
  "event" : "dataAboutXReceived"
Then you would set all beacons that require data about X to fire when:
{{event}} Equals dataAboutXReceived
You can then use dataLayer variables, {{newDataAboutX.thing1}} and  {{newDataAboutX.thing2}} in any beacons that fire on dataAboutXReceived and be sure that they are available.  *A note about accessing dataLayer variables: You can access nested dataLayer variables with dot notation. This also extends to arrays. (for example: myDataLayerArray.3).

Google Tag Manager ‘eventCallback’ Function

If that isn’t enough, Google Tag Manager offers an ‘eventCallback’ function for any object that is pushed to the dataLayer. This is a callback function that is called once all tags that are triggered by this rule are fired. This is often used to navigate to another page after capturing data about the event that would normally cause a URL change. ie: outbound link clicks, navigation clicks or Enhanced Ecommerce  promotion clicks, product listing clicks and product adds to cart.
For example:


        'actionField':{'list':'Search Results'}, 
          'price': productObj.price,
          'brand': productObj.brand,
          'variant': productObj.variant
       document.location = productObj.url

Leave a Comment

Your email address will not be published. Required fields are marked *