{"id":165649,"date":"2025-03-31T12:35:54","date_gmt":"2025-03-31T12:35:54","guid":{"rendered":"https:\/\/peraltafinancing.com\/analytics\/fun-with-google-tag-manager-part-2\/"},"modified":"2025-03-31T12:35:54","modified_gmt":"2025-03-31T12:35:54","slug":"fun-with-google-tag-manager-part-2","status":"publish","type":"post","link":"https:\/\/fivemor.com\/?p=165649","title":{"rendered":"Fun With Google Tag Manager: Part 2"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<p>Apologies for leaving you hanging. It\u2019s now almost three weeks since I published the <a href=\"https:\/\/www.simoahava.com\/analytics\/fun-with-google-tag-manager-part-1\/\">first part of this post<\/a>, and I\u2019m sure you\u2019ve been holding your breath ever since.<\/p>\n<p>There\u2019s been a lot going on since the last post. First, my favorite sports team in the world, San Antonio Spurs, <a href=\"http:\/\/nba.si.com\/2014\/06\/15\/spurs-win-title-heat-2014-nba-finals\/\">won their fifth NBA championship<\/a> from the defending champs, Miami Heat. Next, my wife and I moved to our new house, and we\u2019ve been remodeling ever since. It\u2019s been hectic with work and life getting mixed up in a potpourri of saw dust and web analytics, but now it\u2019s time to return back to the wonderful world of Google Tag Manager!<\/p>\n<p>I promised you four new tips in this one, but I\u2019m going to top myself and give you six gems from the world of tag management. Here\u2019s what you\u2019ll get:<\/p>\n<ol>\n<li>\n<p>dataLayer declaration and push<\/p>\n<\/li>\n<li>\n<p>Using eventCallback in dataLayer.push()<\/p>\n<\/li>\n<li>\n<p>Stopping a Timer Listener<\/p>\n<\/li>\n<li>\n<p>Naming and version control conventions<\/p>\n<\/li>\n<li>\n<p>Fire a single tag multiple times<\/p>\n<\/li>\n<li>\n<p>{{true}} and {{false}}<\/p>\n<\/li>\n<\/ol>\n<p>                <span class=\"simmer\"><br \/>\n  <span class=\"close\">X<\/span><\/p>\n<p>\n    <span class=\"fa fa-md fa-bell\"\/><br \/>\n    <strong>The Simmer Newsletter<\/strong>\n  <\/p>\n<p>\n    Subscribe to the <a href=\"https:\/\/www.simoahava.com\/newsletter\/\">Simmer newsletter<\/a> to get the latest news and content from Simo Ahava into your email inbox!\n  <\/p>\n<p>  <\/span><\/p>\n<h2 id=\"datalayer-declaration-and-push\">dataLayer declaration and push<\/h2>\n<p><a href=\"https:\/\/developers.google.com\/tag-manager\/devguide\">Google Tag Manager<\/a> uses <code>dataLayer<\/code> as its own proprietary data model. <code>dataLayer<\/code> is a JavaScript object of Array type. This means that it has some methods unique to Arrays, such as <code>push()<\/code>.<\/p>\n<p>(See my comment to this post <a href=\"https:\/\/www.simoahava.com\/analytics\/fun-google-tag-manager-part-2\/\">here<\/a> for an overview of how to access Array objects vs. object properties.)<\/p>\n<p>The thing is, you can\u2019t use <code>dataLayer.push()<\/code> if you haven\u2019t declared <code>dataLayer<\/code> as an array first. The repercussions of this are that if you try to use <code>dataLayer.push()<\/code> before <code>dataLayer<\/code> has been declared as an Array, or if it\u2019s been declared as something different (such as a normal object or string), you\u2019ll get some errors:<\/p>\n<div style=\"aspect-ratio: 454 \/ 203;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/datalayer-errors.jpg\" title=\"Errors with dataLayer\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"203\" width=\"454\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/datalayer-errors.jpg#ZgotmplZ\" alt=\"Errors with dataLayer\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>So here\u2019s the first tip:<\/p>\n<p><strong>You need to declare <code>dataLayer<\/code> as an Array before you can use its push() method.<\/strong><\/p>\n<p>To turn <code>dataLayer<\/code> into an array, you need the following code <em>before the container snippet<\/em>:<\/p>\n<p>If you don\u2019t declare it with this explicit statement, then <strong><a href=\"https:\/\/www.simoahava.com\/analytics\/container-snippet-gtm-secrets-revealed\/\">GTM will declare dataLayer<\/a> for you<\/strong>. This is very important, since it ensures that you will always have <code>dataLayer<\/code> available for your tags.<\/p>\n<p>The thing with JavaScript objects and primitives (numbers, strings, etc.) is that if you <strong>redefine<\/strong> 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\u2019s also no way of protecting a global variable such as <code>dataLayer<\/code> from being redefined as a different type, so precautions must be taken so that you don\u2019t mess things up.<\/p>\n<p>Why is this important? Well, if you have more than one <code>dataLayer<\/code> declaration on your page template OR in your GTM tags, you will <strong>erase all previous information in the structure<\/strong>! Oops. Here\u2019s an example:<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#00a\">var<\/span> dataLayer = [{<span style=\"color:#a50\">'pageCategory'<\/span>: <span style=\"color:#a50\">'home'<\/span>, <span style=\"color:#a50\">'logged-in'<\/span>: <span style=\"color:#a50\">'true'<\/span>}];\n...\n<span style=\"color:#00a\">var<\/span> dataLayer = [{<span style=\"color:#a50\">'event'<\/span>: <span style=\"color:#a50\">'allDone'<\/span>}];\n<\/code><\/pre>\n<\/div>\n<p>After the first line of code, <code>dataLayer<\/code> has a single object with two properties: <code>pageCategory<\/code> and <code>logged-in<\/code>. A little on further down the code is the second declaration. Now, after this code is run, <code>dataLayer<\/code> will still only have one object, but with just the <code>event<\/code> property! Can you see how harmful this is? None of the previous information is recoverable after this.<\/p>\n<p>The safest way to prevent this is to preface the ONLY <code>dataLayer<\/code> declaration on the page with the following line:<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n<\/code><\/pre>\n<\/div>\n<p>And then only use <strong>dataLayer.push()<\/strong> to add objects to the Array. This line ensures that if <code>dataLayer<\/code> has already been declared, it won\u2019t be overwritten. It\u2019s not foolproof, since it doesn\u2019t test whether the global variable <code>dataLayer<\/code> is of type Array or not, but I think it\u2019s good enough. If you have another JavaScript library which HAPPENS to use a variable called <code>dataLayer<\/code> as well, you might be in trouble. But this is what testing and debugging is for.<\/p>\n<p>So here\u2019s my final tip for this section:<\/p>\n<p><strong>Declare dataLayer JUST ONCE and use dataLayer.push() for all interactions afterwards.<\/strong><\/p>\n<p>In your GTM tags you can just use <code>dataLayer.push()<\/code>, and you don\u2019t need to check whether <code>dataLayer<\/code> 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.<\/p>\n<h2 id=\"using-eventcallback-in-datalayerpush\">Using eventCallback in dataLayer.push()<\/h2>\n<p>You can use the <code>eventCallback<\/code> dataLayer variable in the <code>push()<\/code> method to execute code after all dependent tags have fired. I know, that was a mouthful but it\u2019s really simple. Take this example:<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\">dataLayer.push({\n  <span style=\"color:#a50\">'event'<\/span>: <span style=\"color:#a50\">'fireEvent'<\/span>,\n  <span style=\"color:#a50\">'eventCallback'<\/span>: <span style=\"color:#00a\">function<\/span>() {\n    console.log(<span style=\"color:#a50\">\"Event has fired\"<\/span>);\n  }\n});\n<\/code><\/pre>\n<\/div>\n<p>Well, it\u2019s a pretty lousy example, but it does what it\u2019s meant to. After all tags that fire upon <strong>{{event}} equals fireEvent<\/strong> have completed, the eventCallback function will execute and you should see the text in the JavaScript console.<\/p>\n<p><code>eventCallback<\/code> is, in essence, a shorthand for the proprietary <strong><a href=\"https:\/\/www.simoahava.com\/analytics\/macro-magic-google-tag-manager\/\">hitCallback<\/a><\/strong> feature that you can invoke in your Google Analytics tags.<\/p>\n<p>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.<\/p>\n<h2 id=\"stopping-a-timer-listener\">Stopping a Timer Listener<\/h2>\n<p>You know of the <a href=\"https:\/\/support.google.com\/tagmanager\/answer\/3415369?hl=en#TimerListener\">Timer Listener<\/a>, 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.<\/p>\n<div style=\"aspect-ratio: 391 \/ 314;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/timer-listener.jpg\" title=\"Timer Listener\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"314\" width=\"391\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/timer-listener.jpg#ZgotmplZ\" alt=\"Timer Listener\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The thing is, you might want to halt the listener before the limit is reached. For example, if you\u2019re 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.<\/p>\n<p>To halt a timer, you need to use the <code>window.clearInterval()<\/code> method. It requires a parameter, namely the ID of the timer that is firing.<\/p>\n<p>GTM\u2019s timer listener is your run-of-the-mill JavaScript <code>setInterval()<\/code> timer, and its ID is stored in, what else, a dataLayer variable called <code>gtm.timerId<\/code>. So to halt the timer, you need to send the content of <code>gtm.timerId<\/code> as the parameter of <code>window.clearInterval()<\/code>. For this to work, you\u2019ll need to create a new Data Layer Variable Macro which refers to gtm.timerId:<\/p>\n<div style=\"aspect-ratio: 534 \/ 359;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/timer-id.jpg\" title=\"Data Layer Timer ID\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"359\" width=\"534\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/timer-id.jpg#ZgotmplZ\" alt=\"Data Layer Timer ID\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>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:<\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#0aa\">window<\/span>.clearInterval({{timer id}});\n<\/code><\/pre>\n<\/div>\n<p>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 <strong>{{event}} equals your_timer_event<\/strong> as one of the rule conditions of the tag that stops the timer).<\/p>\n<h2 id=\"naming-and-version-control-conventions\">Naming and version control conventions<\/h2>\n<p>GTM doesn\u2019t exactly shine when it comes to managing a bucketload of tags, macros, and rules (TMRs). Because of this, it\u2019s really important to adopt a good naming convention so that you can make sense of what you have in your container.<\/p>\n<p>For alternative approaches (more explicit naming to satisfy the in-tool search), check Doug Hall\u2019s original, <a href=\"http:\/\/online-behavior.com\/analytics\/tag-manager-conventions\">excellent post on online-behavior<\/a>. A <a href=\"http:\/\/www.analyticspros.com\/blog\/tag-management\/naming-conventions-for-process-optimization\/\">more recent post by Justin Goodman<\/a> covers similar ground.<\/p>\n<p>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\u2019s readable.<\/p>\n<p>Here\u2019s what I use.<\/p>\n<p><strong>TAGS<\/strong><br \/><em>Tag type &#8211; purpose<\/em><br \/>HTML &#8211; Weather API Call<br \/>HTML &#8211; Social Share Tracking<br \/>UA &#8211; Page View Tracking<br \/>Listener &#8211; Link Click<br \/>Listener &#8211; Click<\/p>\n<p>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.<\/p>\n<div style=\"aspect-ratio: 635 \/ 219;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/naming-conventions.jpg\" title=\"GTM Naming Conventions\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"219\" width=\"635\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/naming-conventions.jpg#ZgotmplZ\" alt=\"GTM Naming Conventions\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p><strong>RULES<\/strong><br \/><em>Key macro &#8211; trigger<\/em><br \/>Event &#8211; gtm.js<br \/>Event &#8211; Outbound Link Click<br \/>URL &#8211; Thank you page<\/p>\n<p>The key macro is what drives the rule. Most often its an <strong>{{event}}<\/strong>, but every now and then you might have the same event across many rules, and then you\u2019ll need to use some other macro to express the difference between the two rules. An example of this is the URL rule above. It\u2019s underlying <strong>{{event}}<\/strong> is gtm.js, so I have to use the URL condition to make it different from all the other gtm.js rules.<\/p>\n<p><strong>MACROS<\/strong><br \/><em>What is returned<\/em><br \/>Random Number<br \/>Debug Mode Status<br \/>Element URL<br \/>URL Hostname<\/p>\n<p>With macros, we\u2019re only interested in what they return, since that\u2019s what macros are used for. So in the macro name, it\u2019s important to express just what is returned when the macro is called.<\/p>\n<p>As for version control, my tip is this:<\/p>\n<p><strong>Name your versions AND add notes!<\/strong><\/p>\n<div style=\"aspect-ratio: 798 \/ 84;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/version-control.jpg\" title=\"Name your versions and add notes\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"84\" width=\"798\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/version-control.jpg#ZgotmplZ\" alt=\"Name your versions and add notes\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>That\u2019s it. It\u2019s 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\u2019re dealing with a huge version history. Be pedantic about this and make sure it\u2019s part of your quality assurance process for tag management!<\/p>\n<h2 id=\"fire-a-single-tag-multiple-times\">Fire a single tag multiple times<\/h2>\n<p>Here\u2019s 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\u2019t have a switch with which you can fire the same tag multiple times with different parameters, so you\u2019d need to create a separate tag for each tracker.<\/p>\n<p>However, there\u2019s a workaround. You can use <code>hitCallback<\/code>, the Lookup Table Macro and a global JavaScript variable to fire your tag multiple times with different values in the fields!<\/p>\n<p>(<strong>Note:<\/strong> GTM\u2019s Debug mode doesn\u2019t let you push items into <code>dataLayer<\/code>, even if you\u2019re doing it from a returned function (which is totally valid). Unfortunately this means that you won\u2019t be able to test this solution in the Debug mode, and you\u2019ll have to publish the container to test it.)<\/p>\n<p>Here\u2019s what you need:<\/p>\n<p>JAVASCRIPT VARIABLE MACRO {{tag callback counter}}:<\/p>\n<div style=\"aspect-ratio: 509 \/ 270;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/javascript-variable.jpg\" title=\"JavaScript variable macro\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"270\" width=\"509\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/javascript-variable.jpg#ZgotmplZ\" alt=\"JavaScript variable macro\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>LOOKUP TABLE MACRO {{tracker name}}:<\/p>\n<div style=\"aspect-ratio: 632 \/ 404;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/lookup-tracker-name.jpg\" title=\"Lookup Table Tracker Name\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"404\" width=\"632\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/lookup-tracker-name.jpg#ZgotmplZ\" alt=\"Lookup Table Tracker Name\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>HITCALLBACK MACRO {{tag callback function}}:<\/p>\n<div style=\"aspect-ratio: 669 \/ 541;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/custom-javascript-callback.jpg\" title=\"Custom JavaScript callback\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"541\" width=\"669\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/custom-javascript-callback.jpg#ZgotmplZ\" alt=\"Custom JavaScript callback\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>So, before we check how the tag is set up, let\u2019s go over these macros. The <strong>{{tag callback counter}}<\/strong> is a JavaScript variable macro which refers to the global JS variable you set up later in <strong>{{tag callback function}}<\/strong>. The idea here is that the <strong>{{tracker name}}<\/strong> 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.<\/p>\n<p>The key is to use your first tracker as the <strong>default value of the Lookup Table macro<\/strong>. This is because when the tag first fires (on <strong>{{event}} equals gtm.js<\/strong>), the JavaScript variable that <strong>{{tag callback counter}}<\/strong> refers to will not exist yet (since it\u2019s defined in the CALLBACK of this tag).<\/p>\n<p>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 <code>maxRepeat<\/code> 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\u2019t have a row in the table!<\/p>\n<p>In your tag, add the following in the Fields to Set:<\/p>\n<div style=\"aspect-ratio: 654 \/ 184;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/hitcallback.jpg\" title=\"hitCallback field in tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"184\" width=\"654\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/hitcallback.jpg#ZgotmplZ\" alt=\"hitCallback field in tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>This will ensure that the callback function is executed every time the tag has fired.<\/p>\n<p>Now that you have your Lookup Table, you can use it in the Tracker Name field of your tag:<\/p>\n<div style=\"aspect-ratio: 613 \/ 318;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/tracker-name.jpg\" title=\"Tracker Name\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"318\" width=\"613\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/tracker-name.jpg#ZgotmplZ\" alt=\"Tracker Name\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>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.<\/p>\n<p>Finally, you need to add TWO rules to the tag. That\u2019s two rules, not two conditions. The rules are<\/p>\n<p><strong>{{event}} equals gtm.js<\/strong><\/p>\n<p>and<\/p>\n<p><strong>{{event}} equals tagCallback<\/strong><\/p>\n<div style=\"aspect-ratio: 364 \/ 270;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/06\/rules.jpg\" title=\"Two firing rules for the tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"270\" width=\"364\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/06\/rules.jpg#ZgotmplZ\" alt=\"Two firing rules for the tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Having two rules means that the tag will fire when and if either one is matched. So first it will fire upon <strong>{{event}} equals gtm.js<\/strong>, since that\u2019s the event that is pushed when GTM is first loaded. Next, it will fire every time <strong>{{event}} equals tagCallback<\/strong>, so twice in my example. Thus, the tag fires three times with three different tracker names.<\/p>\n<p>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\u2019re set!<\/p>\n<p>Here\u2019s a quick recap of what happens:<\/p>\n<ol>\n<li>\n<p>Tag is fired upon <strong>{{event}} equals gtm.js<\/strong>. Since <strong>{{tag callback counter}}<\/strong> can\u2019t find the global variable, the Lookup Table macro <strong>{{tracker name}}<\/strong> returns the default value, which is localTrackerA<\/p>\n<\/li>\n<li>\n<p>When the tag has fired, the counter is created with value 0, and the tagCallback event is pushed into dataLayer<\/p>\n<\/li>\n<li>\n<p>tagCallback triggers the tag again, and this time the Lookup Table finds the counter with value 0, and returns localTrackerB<\/p>\n<\/li>\n<li>\n<p>When the tag has fired, the counter number is increased to 1, and the tagCallback event is pushed into dataLayer<\/p>\n<\/li>\n<li>\n<p>tagCallback triggers the tag for the third time, and again the Lookup Table finds the counter with value 1, thus rollupTracker is returned<\/p>\n<\/li>\n<li>\n<p>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.<\/p>\n<\/li>\n<\/ol>\n<p>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.<\/p>\n<h2 id=\"true-and-false\">{{true}} and {{false}}<\/h2>\n<p>This one\u2019s a quicky but pretty important. Create two Custom JavaScript macros:<\/p>\n<p><strong>{{true}}<\/strong><\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#00a\">function<\/span>() { <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>; }\n<\/code><\/pre>\n<\/div>\n<p><strong>{{false}}<\/strong><\/p>\n<div class=\"highlight\">\n<pre style=\"background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4\"><code class=\"language-javascript\" data-lang=\"javascript\"><span style=\"color:#00a\">function<\/span>() { <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">false<\/span>; }\n<\/code><\/pre>\n<\/div>\n<p>Why, you ask? Well, let\u2019s say you want to set the Anonymize IP setting to <em>true<\/em> for one domain and <em>false<\/em> 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 \u201ctrue\u201d and \u201cfalse\u201d, you notice that things don\u2019t work as you\u2019d 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 <em>Boolean<\/em> type, otherwise it fails.<\/p>\n<p>To circumvent this problem, instead of typing \u201ctrue\u201d and \u201cfalse\u201d into GTM\u2019s fields, use the macros you just created. They return <em>true<\/em> and <em>false<\/em> in proper Boolean type! This way you will be able to pass the correct value types to the settings which require Boolean values.<\/p>\n<p>Naturally, this should be fixed by adding Boolean true and false as possible values in all GTM fields.<\/p>\n<h2 id=\"conclusions\">Conclusions<\/h2>\n<p>Well there you have it! Another round of GTM magic. I can\u2019t wait to experiment more and uncover even more cool stuff to share with you. Be sure to join our amazing <a href=\"https:\/\/plus.google.com\/u\/0\/communities\/104865292981489764063\">Google+ community<\/a> which has served as inspiration for most of these tips.<\/p>\n<p>Also, if you happen to be in any of the following upcoming conferences, come say hi to me:<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Apologies for leaving you hanging. It\u2019s now almost three weeks since I published the first part of this post, and I\u2019m sure you\u2019ve been holding your breath ever since. There\u2019s 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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":165650,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[1304,1531,14495,3341,1791],"dealstore":[],"offerexpiration":[],"class_list":["post-165649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-fun","tag-google","tag-manager","tag-part","tag-tag"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Fun With Google Tag Manager: Part 2 - Som2ny Network<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fivemor.com\/?p=165649\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fun With Google Tag Manager: Part 2 - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"Apologies for leaving you hanging. It\u2019s now almost three weeks since I published the first part of this post, and I\u2019m sure you\u2019ve been holding your breath ever since. There\u2019s 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 [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fivemor.com\/?p=165649\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-31T12:35:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1\" \/>\n\t<meta property=\"og:image:height\" content=\"1\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fivemor.com\/?p=165649#article\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\"},\"headline\":\"Fun With Google Tag Manager: Part 2\",\"datePublished\":\"2025-03-31T12:35:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649\"},\"wordCount\":2525,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg\",\"keywords\":[\"Fun\",\"Google\",\"Manager\",\"PART\",\"TAG\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fivemor.com\/?p=165649#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fivemor.com\/?p=165649\",\"url\":\"https:\/\/fivemor.com\/?p=165649\",\"name\":\"Fun With Google Tag Manager: Part 2 - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649#primaryimage\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg\",\"datePublished\":\"2025-03-31T12:35:54+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fivemor.com\/?p=165649#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fivemor.com\/?p=165649\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/?p=165649#primaryimage\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fivemor.com\/?p=165649#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/fivemor.com\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fun With Google Tag Manager: Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fivemor.com\/#website\",\"url\":\"https:\/\/fivemor.com\/\",\"name\":\"Som2ny Network\",\"description\":\"Daily Deals\",\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fivemor.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/fivemor.com\/#organization\",\"name\":\"Som2ny Network\",\"url\":\"https:\/\/fivemor.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png\",\"width\":300,\"height\":86,\"caption\":\"Som2ny Network\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png\",\"caption\":\"admin\"},\"sameAs\":[\"https:\/\/fivemor.com\"],\"url\":\"https:\/\/fivemor.com\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Fun With Google Tag Manager: Part 2 - Som2ny Network","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fivemor.com\/?p=165649","og_locale":"en_US","og_type":"article","og_title":"Fun With Google Tag Manager: Part 2 - Som2ny Network","og_description":"Apologies for leaving you hanging. It\u2019s now almost three weeks since I published the first part of this post, and I\u2019m sure you\u2019ve been holding your breath ever since. There\u2019s 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 [&hellip;]","og_url":"https:\/\/fivemor.com\/?p=165649","og_site_name":"Som2ny Network","article_published_time":"2025-03-31T12:35:54+00:00","og_image":[{"url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg","width":1,"height":1,"type":"image\/jpeg"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fivemor.com\/?p=165649#article","isPartOf":{"@id":"https:\/\/fivemor.com\/?p=165649"},"author":{"name":"admin","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371"},"headline":"Fun With Google Tag Manager: Part 2","datePublished":"2025-03-31T12:35:54+00:00","mainEntityOfPage":{"@id":"https:\/\/fivemor.com\/?p=165649"},"wordCount":2525,"commentCount":0,"publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"image":{"@id":"https:\/\/fivemor.com\/?p=165649#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg","keywords":["Fun","Google","Manager","PART","TAG"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fivemor.com\/?p=165649#respond"]}]},{"@type":"WebPage","@id":"https:\/\/fivemor.com\/?p=165649","url":"https:\/\/fivemor.com\/?p=165649","name":"Fun With Google Tag Manager: Part 2 - Som2ny Network","isPartOf":{"@id":"https:\/\/fivemor.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/fivemor.com\/?p=165649#primaryimage"},"image":{"@id":"https:\/\/fivemor.com\/?p=165649#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg","datePublished":"2025-03-31T12:35:54+00:00","breadcrumb":{"@id":"https:\/\/fivemor.com\/?p=165649#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fivemor.com\/?p=165649"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/?p=165649#primaryimage","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/datalayer-errors.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/fivemor.com\/?p=165649#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fivemor.com\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Fun With Google Tag Manager: Part 2"}]},{"@type":"WebSite","@id":"https:\/\/fivemor.com\/#website","url":"https:\/\/fivemor.com\/","name":"Som2ny Network","description":"Daily Deals","publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fivemor.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/fivemor.com\/#organization","name":"Som2ny Network","url":"https:\/\/fivemor.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/#\/schema\/logo\/image\/","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2026\/07\/4a0953c4-logo-300x86-1.png","width":300,"height":86,"caption":"Som2ny Network"},"image":{"@id":"https:\/\/fivemor.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/729ae85bf62b9917e93538db2f2688ca?s=96&r=g&default=https%3A%2F%2Ffivemor.com%2Fwp-content%2Fplugins%2Fbuddypress-first-letter-avatar%2Fimages%2Fdefault%2F96%2Flatin_a.png","caption":"admin"},"sameAs":["https:\/\/fivemor.com"],"url":"https:\/\/fivemor.com\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/165649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=165649"}],"version-history":[{"count":0,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/165649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/media\/165650"}],"wp:attachment":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=165649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=165649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=165649"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=165649"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=165649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}