Fun With Google Tag Manager: Part 2

Apologies for leaving you hanging. It’s now almost three weeks since I published the first part of this post, and I’m sure you’ve been holding your breath ever since.

There’s been a lot going on since the last post. First, my favorite sports team in the world, San Antonio Spurs, won their fifth NBA championship from the defending champs, Miami Heat. Next, my wife and I moved to our new house, and we’ve been remodeling ever since. It’s been hectic with work and life getting mixed up in a potpourri of saw dust and web analytics, but now it’s time to return back to the wonderful world of Google Tag Manager!

I promised you four new tips in this one, but I’m going to top myself and give you six gems from the world of tag management. Here’s what you’ll get:

  1. dataLayer declaration and push
  2. Using eventCallback in dataLayer.push()
  3. Stopping a Timer Listener
  4. Naming and version control conventions
  5. Fire a single tag multiple times
  6. {{true}} and {{false}}

dataLayer declaration and push

Google Tag Manager uses dataLayer as its own proprietary data model. dataLayer is a JavaScript object of Array type. This means that it has some methods unique to Arrays, such as push().

[See my comment to this post here for an overview of how to access Array objects vs. object properties.]

The thing is, you can’t use dataLayer.push() if you haven’t declared dataLayer as an array first. The repercussions of this are that if you try to use dataLayer.push() before dataLayer has been declared as an Array, or if it’s been declared as something different (such as a normal object or string), you’ll get some errors:
Errors with dataLayer
So here’s the first tip:

You need to declare dataLayer as an Array before you can use its push() method.

To turn dataLayer into an array, you need the following code before the container snippet:

var dataLayer = [];

If you don’t declare it with this explicit statement, then GTM will declare dataLayer for you. This is very important, since it ensures that you will always have dataLayer available for your tags.

The thing with JavaScript objects and primitives (numbers, strings, etc.) is that if you redefine a JavaScript entity, its previous state will be overwritten! JavaScript entities are dynamic, so you can redefine a string as an object, an Array as a number, and so forth without any difficulty. There’s also no way of protecting a global variable such as dataLayer from being redefined as a different type, so precautions must be taken so that you don’t mess things up.

Why is this important? Well, if you have more than one dataLayer declaration on your page template OR in your GTM tags, you will erase all previous information in the structure! Oops. Here’s an example:

var dataLayer = [{'pageCategory': 'home', 'logged-in': 'true'}];
var dataLayer = [{'event': 'allDone'}];

After the first line of code, dataLayer has a single object with two properties: pageCategory and logged-in. A little on further down the code is the second declaration. Now, after this code is run, dataLayer will still only have one object, but with just the event property! Can you see how harmful this is? None of the previous information is recoverable after this.

The safest way to prevent this is to preface the ONLY dataLayer declaration on the page with the following line:

window.dataLayer = window.dataLayer || [];

And then only use dataLayer.push() to add objects to the Array. This line ensures that if dataLayer has already been declared, it won’t be overwritten. It’s not foolproof, since it doesn’t test whether the global variable dataLayer is of type Array or not, but I think it’s good enough. If you have another JavaScript library which HAPPENS to use a variable called dataLayer as well, you might be in trouble. But this is what testing and debugging is for.

So here’s my final tip for this section:

Declare dataLayer JUST ONCE and use dataLayer.push() for all interactions afterwards.

In your GTM tags you can just use dataLayer.push(), and you don’t need to check whether dataLayer exists or not, since GTM declares it for you in the container snippet. But when working on the page template, you need to be extra careful not to overwrite the Array.

Back to top

Using eventCallback in dataLayer.push()

You can use the eventCallback dataLayer variable in the push() method to execute code after all dependent tags have fired. I know, that was a mouthful but it’s really simple. Take this example:

  'event': 'fireEvent',
  'eventCallback': function() {
    console.log("Event has fired");

Well, it’s a pretty lousy example, but it does what it’s meant to. After all tags that fire upon {{event}} equals fireEvent have completed, the eventCallback function will execute and you should see the text in the JavaScript console.

eventCallback is, in essence, a shorthand for the proprietary hitCallback feature that you can invoke in your Google Analytics tags.

You can use this for a quick callback, such as waiting for all tags to fire before a link redirects or pushing a second event as the callback to impose a rudimentary tag firing order.

Back to top

Stopping a Timer Listener

You know of the Timer Listener, right? You can use it to have an event push every X milliseconds. You can limit the number of times the timer fires, or you can just let it fire from here to eternity.
Timer Listener
The thing is, you might want to halt the listener before the limit is reached. For example, if you’re using the Timer Listener to send pulses reflecting the time the user has spent digesting content, for example, you might want to halt it once the reader reaches the end of the page to keep your events from being cluttered with timer hits.

To halt a timer, you need to use the window.clearInterval() method. It requires a parameter, namely the ID of the timer that is firing.

GTM’s timer listener is your run-of-the-mill JavaScript setInterval() timer, and its ID is stored in, what else, a dataLayer variable called gtm.timerId. So to halt the timer, you need to send the content of gtm.timerId as the parameter of window.clearInterval(). For this to work, you’ll need to create a new Data Layer Variable Macro which refers to gtm.timerId:
Data Layer Timer ID
After this, whenever you want to halt a timer, all you have to do is have the following line of JavaScript in your Custom HTML tag or your Custom JavaScript macro:

window.clearInterval({{timer id}});

This will halt the most recently fired timer. So if you have multiple timers, you might have to edit the code somewhat to find the proper timer (easiest way to do this is to use {{event}} equals your_timer_event as one of the rule conditions of the tag that stops the timer).

Back to top

Naming and version control conventions

GTM doesn’t exactly shine when it comes to managing a bucketload of tags, macros, and rules (TMRs). Because of this, it’s really important to adopt a good naming convention so that you can make sense of what you have in your container.

[For alternative approaches (more explicit naming to satisfy the in-tool search), check Doug Hall’s original, excellent post on online-behavior. A more recent post by Justin Goodman covers similar ground.]

I use a very simple naming convention in all my TMRs. It scales pretty nicely, as it works in large enterprise implementations as well as in smaller containers. Also, the most important thing is that it’s readable.

Here’s what I use.

Tag type – purpose
HTML – Weather API Call
HTML – Social Share Tracking
UA – Page View Tracking
Listener – Link Click
Listener – Click

Having the tag type is pretty redundant since you can see that in the second column of the tag list. However, I enjoy that it makes the list look a bit less cluttered.
GTM Naming Conventions
Key macro – trigger
Event – gtm.js
Event – Outbound Link Click
URL – Thank you page

The key macro is what drives the rule. Most often its an {{event}}, but every now and then you might have the same event across many rules, and then you’ll need to use some other macro to express the difference between the two rules. An example of this is the URL rule above. It’s underlying {{event}} is gtm.js, so I have to use the URL condition to make it different from all the other gtm.js rules.

What is returned
Random Number
Debug Mode Status
Element URL
URL Hostname

With macros, we’re only interested in what they return, since that’s what macros are used for. So in the macro name, it’s important to express just what is returned when the macro is called.

As for version control, my tip is this:

Name your versions AND add notes!
Name your versions and add notes
That’s it. It’s so important to annotate your container versions with information what was updated and what changed. This is the only way to stay on top of your game, especially if you’re dealing with a huge version history. Be pedantic about this and make sure it’s part of your quality assurance process for tag management!

Back to top

Fire a single tag multiple times

Here’s a common problem: You have multiple trackers firing on the same domain, but you want to use just one tag for them. Well, currently GTM doesn’t have a switch with which you can fire the same tag multiple times with different parameters, so you’d need to create a separate tag for each tracker.

However, there’s a workaround. You can use hitCallback, the Lookup Table Macro and a global JavaScript variable to fire your tag multiple times with different values in the fields!

[Note: GTM’s Debug mode doesn’t let you push items into dataLayer, even if you’re doing it from a returned function (which is totally valid). Unfortunately this means that you won’t be able to test this solution in the Debug mode, and you’ll have to publish the container to test it.]

Here’s what you need:

JAVASCRIPT VARIABLE MACRO {{tag callback counter}}:
JavaScript variable macro
LOOKUP TABLE MACRO {{tracker name}}:
Lookup Table Tracker Name
HITCALLBACK MACRO {{tag callback function}}:
Custom JavaScript callback
So, before we check how the tag is set up, let’s go over these macros. The {{tag callback counter}} is a JavaScript variable macro which refers to the global JS variable you set up later in {{tag callback function}}. The idea here is that the {{tracker name}} Lookup Table macro returns a different string, depending on what the counter is. Every time the callback is executed, the counter goes up by 1.

The key is to use your first tracker as the default value of the Lookup Table macro. This is because when the tag first fires (on {{event}} equals gtm.js), the JavaScript variable that {{tag callback counter}} refers to will not exist yet (since it’s defined in the CALLBACK of this tag).

When the callback is executed, a GTM event is pushed into dataLayer and the counter value is increased by one. You define the maximum number of times the tag should fire with the maxRepeat variable in the callback function. Just remember to have a row for each iteration in the Lookup Table, otherwise the tracker in the Default Value field of the Lookup Table will be returned for each iteration that doesn’t have a row in the table!

In your tag, add the following in the Fields to Set:
hitCallback field in tag
This will ensure that the callback function is executed every time the tag has fired.

Now that you have your Lookup Table, you can use it in the Tracker Name field of your tag:
Tracker Name
Using the macro here makes it so that with every iteration of the tag, a different value is set as the Tracker Name, thanks to the Lookup Table and the counter that increases by 1 with every pass.

Finally, you need to add TWO rules to the tag. That’s two rules, not two conditions. The rules are

{{event}} equals gtm.js


{{event}} equals tagCallback
Two firing rules for the tag
Having two rules means that the tag will fire when and if either one is matched. So first it will fire upon {{event}} equals gtm.js, since that’s the event that is pushed when GTM is first loaded. Next, it will fire every time {{event}} equals tagCallback, so twice in my example. Thus, the tag fires three times with three different tracker names.

You could use this also if you have different properties you want to track to. Just replace the tracker names with UA-XXXXX-Y codes and you’re set!

Here’s a quick recap of what happens:

  1. Tag is fired upon {{event}} equals gtm.js. Since {{tag callback counter}} can’t find the global variable, the Lookup Table macro {{tracker name}} returns the default value, which is localTrackerA
  2. When the tag has fired, the counter is created with value 0, and the tagCallback event is pushed into dataLayer
  3. tagCallback triggers the tag again, and this time the Lookup Table finds the counter with value 0, and returns localTrackerB
  4. When the tag has fired, the counter number is increased to 1, and the tagCallback event is pushed into dataLayer
  5. tagCallback triggers the tag for the third time, and again the Lookup Table finds the counter with value 1, thus rollupTracker is returned
  6. The hitCallback is fired again, but this time the maximum number of repeats is reached and the function just returns an undefined value. Thus, no callback event is pushed into dataLayer, and the tag does not fire again.

I think this is an amazing feat of strength from dynamic macros and the callback function. This should make any enterprise setup much, MUCH leaner.

Back to top

{{true}} and {{false}}

This one’s a quicky but pretty important. Create two Custom JavaScript macros:


function() { return true; }


function() { return false; }

Why, you ask? Well, let’s say you want to set the Anonymize IP setting to true for one domain and false for two other domains (this idea came from Carmen Mardiros, by the way!). You want to use a Lookup Table Macro to achieve this, but when your Lookup Table aligns domains with the return value of “true” and “false”, you notice that things don’t work as you’d like them to. The problem is that if you add text to a field in GTM, it is always cast to string type. Anonymize IP requires Boolean type, otherwise it fails.

To circumvent this problem, instead of typing “true” and “false” into GTM’s fields, use the macros you just created. They return true and false in proper Boolean type! This way you will be able to pass the correct value types to the settings which require Boolean values.

Naturally, this should be fixed by adding Boolean true and false as possible values in all GTM fields.

Back to top


Well there you have it! Another round of GTM magic. I can’t wait to experiment more and uncover even more cool stuff to share with you. Be sure to join our amazing Google+ community which has served as inspiration for most of these tips.

Also, if you happen to be in any of the following upcoming conferences, come say hi to me:


  1. Emil Venkov says

    Hi, Simo thank you for the gems :).
    I wonder something, in section Fire a single tag multiple times, where you define firing rules for the last tag ({{event}} equals gtm.js AND {{event}} equals tagCallback)), between the rules should be OR, right ?. Because now the tag will fire only if the {{event}} is simultaneously “gtm.js” and “tagCallback”, correct me if i am wrong.

    • says

      Oh man, I was sure that this time there was no room for error :)

      As I state in the text, you need to add two rules NOT two conditions. If a single rule has multiple conditions, then there’s the implicit “and” operator between them, which means that all conditions must be met for the rule to work. If, however, you use multiple rules, then there’s the perpetual “or” implied, meaning that the rule will fire whenever either one of the rules is met.

      The AND in the text wasn’t a logical operator, it was simply the conjunction “and” in the English language :) What I meant was exactly as I wrote: you need two rules (not two conditions): {{event}} equals gtm.js AND {{event}} equals tagCallback.

      I added a screenshot to clarify things.

      This is the problem when using terminology that isn’t too clear yet (especially with a relatively new product). Rule = set of conditions which must be met, condition = a part of a rule.

      Thanks for pointing out the ambiguity in the text.

      • Emil Venkov says

        Omg, sorry for the stupid comment :D, i guess the programming logic is too deep in my mind :D.

  2. says

    Hi Simo!
    Thanks for another great post. I really loved the “Fire a single tag multiple times” gems. This is brilliant and you explained it so simple!

    I have one question about the dataLayer – I have a click listener (for example) so I know gtm.element has pushed to the dL, but I’ve wondered how can I get this value without GTM (just for training).
    When I write dataLayer.gtm.element in the console it returns “TypeError: Cannot read property ‘element’ of undefined”.
    Of course if I write dataLayer[4] it returns the right object but why I can’t access this gtm.element directly?

    • says

      Well, it’s simply because dataLayer is of type Array. It’s not a single object with properties, but it’s a collection of objects with properties.

      So let’s imagine you click five times on your page. This means that five objects with property ‘gtm.element’ have been pushed to the dataLayer. If you tried to access it directly with dataLayer.gtm.element, which object would the browser know to return?

      When accessing an index in the array, you always need to specify its location. So if it’s the fifth object in the queue, you’d access it with dataLayer[4].

      You might have noticed that dataLayer[4].event works but dataLayer[4].gtm.element doesn’t. This is because when using dot notation, the browser interprets each dot-separated entity as its own property. That’s why you get the TypeError, since there’s no property “gtm” in the object.

      IF you want to access the object directly, you need to abandon dot notation and use bracket notation. So in the previous example, you’ll get the value of “gtm.element” by typing dataLayer[4][“gtm.element”]. This means “get the value of ‘gtm.element’ from the fifth index of the dataLayer Array”.

      The way the Data Layer Variable Macro works is that it circumvents this whole “which index, which property” thing by going backwards from the most recent Array index. So when you create a macro for gtm.element.parentElement.className, for example, GTM starts from the most recent object in the dL. If it finds “gtm.element.parentElement.className”, it returns its value and halts the process. If it doesn’t, it moves to the second most recent object in the queue and so forth.

      • says

        This is amazing. When I read this explanation I can feel my dopamine flowing in my blood. I’m serious.

        If I understand you properly, so when I use dL variable via GTM it does NOT interpret each dot-separated entity as its own property, but goes directly to the objects in the dL array?

      • says

        Well, actually Version 2 of the DL macro did bring the added functionality of dot notation. So I guess there’s a mechanism in place which tests for hierarchical objects (e.g. {gtm: {element: [object]}}) and for strings with dots, e.g. “gtm.element”.

        So GTM understands both: dot-separated objects AND strings with dots.

  3. says

    Hi Simo,

    I also need (multiple trackers on page) to set the Tracker name in GTM. However I noticed a warning below the option:
    “Use of named trackers is highly discouraged in GTM”

    This points to a section of a help page ( that makes absolutely no sense to me. They say to define the tracker names using the data layer, but then I still need to put those values in Google Tag Manager somewhere to link the code and the tags, so I’m gonna need to use the Tracker Name option anyway

    I’ve raised a question on StackOverflow, feel free to drop a comment or answer if you have the slightest clue as to what the warning means and how the code should be updated accordingly (if it needs to be):


  4. Chris says

    Hi Simo,

    This is probably a very simplistic question, but I am trying to implement your stopping of a Timer Listener. I am trying to do this on {{event}} equals gtm.linkClick (whereby I am firing off a different tag).
    I tried adding the following custom HTML tag that is fired upon {event}} equals gtm.linkClick – the tag fires, but fails to stop the gtm.timer from firing.

    window.clearInterval({{timer id}});

    I checked the debugger and the Macro is pulling the correct timerId.

    Any advice?

    • says

      Well, it should work perfectly with that code (just tested again).

      Quick sanity check: is the JavaScript in your Custom HTML code wrapped in <script> and </script> tags?

  5. Chris says

    Yip, it’s wrapped in the script tags (I added them in my post but they seem to have disappeared). I am seeing the following in the HTML output


    And within the Macros I am getting a value returned for timer id, which I am assuming is being pulled in via “google_tag_manager[“GTM-XXX”].macro(6)” or am I mistaken?


  6. Chris says

    Again, the script tags have been removed when posting… the HTML is wrapped in
    script id=”” type=”text/javascript” and /script (I have removed “” in the hope that this displays

  7. Jerome says


    I started implementing my own function to fire multiple tags using one tag a while ago. It worked great. It was similar to yours until I was on site at a client and for some of their pushes they are using a for loop and that destroyed my solution :(.
    If you know how to counter that, please let me know.


    • says

      Where is the for-loop? Are they sending GA hits via a Custom HTML Tag? I can’t help you counter something of which I know nothing :) If you can share an example e.g. via mail (simo at, I can take a closer look.

  8. Camiele Wenniger says

    Hi Simo, always enjoy your excellent posts, truly at the edge of GTM development!
    Dropping by in the Netherlands again anytime soon?

    Looking at your setup for One Tag – Multiple Firing, i do see a problem rising when implementing *multiple* tags with this configuration:

    Since we’d use an OR configuration for each tag we’d want to fire multiple times, then all tags will start firing on any CallBack Event, since there’s no other criteria in that Rule.. troublesome, right?
    I would assume we’d need to expand the CallBack Rule for each separate tag, to make its firing conditions specific enough for that individual tag.
    Or do you see a simpler solution (i’m sort of counting on that ;-) ?

    Secondary to this, i must say i do really miss the option to re-use separate Rules as building blocks in AND combinations. If you change/add one minor aspect in a complicated Rule, you’ll need to duplicate the Rule [which is against the GTM concept of re-usability] – i’d rather just add an AND element to an existing set of conditions. In plainer English, i don’t see why AND and OR conditions need to live in separate worlds in the Rule-sphere; it would be much better to freely allow combinations/nesting/grouping of the two in one Rule.
    Which ends my Rule-rant.
    Is that on your GTM wish-list too by any chance?
    All the best!

    • says

      Hey Camiele!

      What a wonderful question, thanks!

      The reason I didn’t even dare to poke the “Fire multiple tags multiple times” question is because there’s no elegant way to do it yet. The only thing I can think of is to create a separate callback and global counter for each tag instance. Well, you could probably do some stuff with dataLayer, using a timestamp as the identifier for each unique counter / callback, but right now I can’t wrap my head around how it would be done.

      The way it SHOULD work is if you could somehow check for which tag’s callback the event was. That way you could have a rule like

      {{event}} equals callback
      {{event origin}} equals this_tag_id

      Or something, but we’re not there yet.

      I don’t see how just modifying a rule would work either, but if you have ideas, please let me know :)

      Yes, managing rules is a bit tiresome right now. You either have the “OR” relationship you get when adding multiple rules (and even then it’s actually “IF and OR” so ALL the rules can make the tag fire, not just the first one that matches, resulting often in duplicate hits), or the “AND” relationship you have with multiple conditions.

      You can add “OR” logic to rule conditions by using the regex match: {{event}} equals ^gtm\.js|callback1|callback2 is a single condition with three possible triggers.

      But yes, better rule handling is definitely on my wishlist, and I’m pretty sure we’ll see some better logic there at some point in the not too distant future.

      I loved my last trip to Netherlands, so I’m anxiously looking / waiting for an interesting conference or a good time for vacationing in Europe to return. Plus my Stroopwafel reserves have run out :)

      • Camiele Wenniger says

        Hi Simo,
        I’ve left this to simmer for a while [by which i mean had a brain freeze],
        but the follow-up article @ marketlytics, combined with your comment from 24/06/2014 raised an idea:
        If i’m correctly following, you could store the position of an initiating event in the datalayer array [something like “.length”] as a separate Global Variable, and use that to ensure TagCallBack will only fire for that specific event… or am I missing something?
        Best wishes for the new year!

      • says

        Hi Camiele,

        I’m glad to know this article has inspired you to freeze your brain :)

        The problem is dynamic triggers. It’s easy enough to tag each event / iteration of the tag with a dynamic value (e.g. timestamp or position in dL), but the difficult bit is to make the trigger condition for the tag dynamic so it only responds to the iteration callbacks of the tag itself, and not of some other tag that is also in the loop.

        I think this is an unsolvable problem, and you’ll have to adopt something like what Marketlytics did with a different event syntax. With just one callback function, one counter, and one set of triggers you won’t be able to handle multiple tags firing.

        I might be wrong, of course, but I’ve had my brain freezes over this as well.

  9. Darren Collister says

    Hi Simo,

    Thanks heaps for this article, and for all that you do. I’ve had a lot of fun experimenting and following your guidelines but I’m running into some brick walls with using your method to Fire a single tag multiple times.

    I’ve hooked up three separate UA numbers, which are tracking pageview levels to all three accounts just fine.

    But how does this work with Event Tracking? I’ve failed and failed and failed with basic Event Tracking like PDF downloads, timer events, and outbound link tracking. I can get them defaulting to fire to “Tracker A” but no apparent combination of triggers seems to support them firing to all three accounts.

    I’m not sure how much of this might be be connected to the UI update (I’m working in v2). Can you point me in the right direction for how to best approach this please? I’m missing something stupid, I’m sure, but any thoughts on what that might be?

    • says

      I’ve wondered this as well. I am currently working on a project in Version 2 and am having the same issues. Overall everything works well with pageview tracking and I have had no issues.

      The event tracking is where everything falls apart. The most interesting thing is whatever it is, isn’t breaking the first firing to the main UA tracker, it only comes into play with the callback. It won’t go out to the next tracker.

      Any suggestions, any thoughts on what may be wrong?

  10. Emil says

    Just wanted to say, Thanks!

    Anytime I do a google search for my GTM problems ur blog is always search result number one and the answer is brilliant. Amazing!

  11. BigBubbaH says


    Great post regarding the multiple trackers, 1 tag (hard to believe there isn’t a GTM solution for this yet).

    I followed your notes however, every time I tested the event wasn’t pushed to the dataLayer.

    I found a follow up post to your original from Hussain @marketlytics. He noted that the hitCallback would not work in debug mode. Sure enough once I turned off debug and published I saw the event in the dataLayer.

  12. Svitlana says

    Hello, Simo!

    Thank you for your great posts!
    I have a question for your and was wandering if you could help me.

    I need to add the ‘impressions’ to the dataLayer in a loop.
    I tried the approach you suggested:

    { ‘name’ : ‘${}’, ‘list’ : ‘Search Results’ }
    ) ;

    It successfully adds products to the list. I get the correct structure of the dataLayer upon DOM ready with the several products in the list.
    But google analitics tag, which is fired upon DOM ready event, does not send these products!

    If I add products in an ordinary way, like

    ‘ecommerce’ : {
    ‘impressions’ :
    { ‘name’ : ‘${}’, ‘list’ : ‘Search Results’ }
    }) ;

    I have the very same dataLayer object (and data model object) upon DOM ready event, but google analitics does send the products!

    Could you please suggest what that might be? I really need your help here

    Thank you,

    • says


      The ecommerce object doesn’t work with recursive merge. It uses V1 of the data layer, which doesn’t have the merge feature. That’s why you’ll need to send the impressions as their own ‘ecommerce’ push, and that’s why updating an existing ‘ecommerce’ object won’t work.


      • Svitlana says

        Thank you for your reply, Simo. It shed some lite on the question. I’ll try to find an info about v1/v2..did not know about that , just saw some mentions about it.

        But could you please explain how is it actually works? I failed to find any information on it.
        The messages are pushed into the dataLayer, the .push is redeclared so that it updates dataModel (merges messages into it).
        Then if event is triggered or page is loaded, the GTM fires all registered tags. What information is being sent along with the tags? Who parses dataLayer and/or dataModel to get the information? GTM or GA itself?

        For an instanse, if I push the ‘ecommerce’ object in its own push (like you suggested), and do it in the loop, than only the last object is being sent with the request to GA. So, GA does not collect the messages.
        Nor it parses dataModel (because when I push into ecommerce with ‘ecommerce.impressions.push’ the dataModel does contain the merged ecommerce object, but GA does not see it )..

        I know it is a lot of question..
        But, hope, you can help me

        Thank you!

  13. Shuki Mann says

    Hi Simo,

    In the “Fire a single tag multiple times” example, why you don’t use simple dL variable and increase its value by 1 in each round?
    Instead of dataLayer.push({‘event':’tagCallback’}) I would write
    var counter +=1;

    The results will be the same, I just want to know if there is a specific reason why you use JS variable and not something else

    • says

      No there’s no reason for the choice. JS Variable is just about as simple as it gets. With dataLayer, you’re working with the data model, and there are many extra steps in the way (though they are obfuscated by the UI/UX). So as an argument for simplicity, dataLayer.push() doesn’t hold.

      If you want to avoid polluting the global namespace, then dataLayer is, of course, a better choice.

Leave a Reply

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

Please do not write HTML or other formatted code in your comments!