{"id":163372,"date":"2025-03-29T16:33:46","date_gmt":"2025-03-29T16:33:46","guid":{"rendered":"https:\/\/peraltafinancing.com\/analytics\/custom-event-listeners-for-gtm\/"},"modified":"2025-03-29T16:33:46","modified_gmt":"2025-03-29T16:33:46","slug":"custom-event-listeners-for-gtm","status":"publish","type":"post","link":"https:\/\/fivemor.com\/?p=163372","title":{"rendered":"Custom Event Listeners For GTM"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<p>(<strong>UPDATE 1 Oct 2014<\/strong> Due to a change in how macros work in Debug Mode, the {{generic event handler}} macro no longer works when testing in Debug Mode. That means that you\u2019ll have to test your custom listener in a live container (I know, ouch!). If you want to test in Debug Mode, you\u2019ll have to skip using the {{generic event handler}} as a macro, and instead copy the inner function into the Custom HTML Tag, give the function a name, and use that as the callback in <code>addEventListener<\/code> or <code>attachEvent<\/code>.<\/p>\n<p>Also, to preserve the \u2018gtm.\u2019 namespace for native GTM features only, I have changed the prefix of the custom event name from \u2018gtm.\u2019 to \u2018event.&#8217;)<\/p>\n<p>When the good folks at Mountain View introduced <a href=\"https:\/\/www.simoahava.com\/analytics\/auto-event-tracking-google-tag-manager\/\">auto-event tracking<\/a> for <a href=\"https:\/\/www.google.com\/tagmanager\">Google Tag Manager<\/a>, a collective sigh was heard around the world (I\u2019m just slightly exaggerating).<\/p>\n<p>Finally, the true power of GTM was unleashed.<\/p>\n<p>With auto-event tracking, one of the more difficult aspects of web analytics, tracking user interactions beyond the page load, was greatly simplified.<\/p>\n<div style=\"aspect-ratio: 1719 \/ 672;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/custom-listeners.jpg\" title=\"Custom Event Listener for GTM\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"672\" width=\"1719\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/custom-listeners.jpg#ZgotmplZ\" alt=\"Custom Event Listener for GTM\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>However, as a species we are in a perpetual state of dissatisfaction.<\/p>\n<p>When we got the Click, the Link Click and the Form Submit, we wanted more. So then we got the <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-history-listener\/\">History listener<\/a>. Again, we wanted more. And we got the <a href=\"https:\/\/www.simoahava.com\/analytics\/fun-with-google-tag-manager-part-1\/\">Error listener<\/a>. And then we wanted more again.<\/p>\n<p>To satisfy this undying thirst for more listeners, the community has been very helpful. In fact, before you read on, I want you to familiarize yourself with Doug Hall\u2019s excellent post on <a href=\"http:\/\/www.conversionworks.co.uk\/blog\/2013\/12\/13\/extending-auto-event-tracking-in-google-tag-manager\/\">extending GTM\u2019s auto-event listeners<\/a>. The following guide will expand upon the ideas put forth by Doug, while striving to approach the elegance of his prose and wisdom.<\/p>\n<p>I\u2019ve also written many posts on GTM\u2019s listeners. I\u2019ll link to them at the end of this article.<\/p>\n<p>What follows is a step-by-step guide to creating a generic listener for all the various events you want to capture that are <em>not yet<\/em> captured by GTM\u2019s own listeners. Once GTM introduces a proprietary listener for whatever event you want to handle, it would be best to start using that.<\/p>\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=\"the-listener-prototype\">The listener prototype<\/h2>\n<p>The prototype of the custom event listener will require two components:<\/p>\n<ol>\n<li>\n<p>A Custom HTML Tag for each listener type you want to activate (e.g. <em>change<\/em>, <em>blur<\/em>, <em>copy<\/em>)<\/p>\n<\/li>\n<li>\n<p>A generic Custom JavaScript Macro, which returns the handler function that pushes the event into the dataLayer<\/p>\n<\/li>\n<\/ol>\n<p>As you can see, it looks pretty simple. And it is. As long as you observe proper design patterns and best practices, these two components will get you far.<\/p>\n<h2 id=\"the-generic-event-handler-macro\">The generic event handler macro<\/h2>\n<p>Let\u2019s start with the macro, since it\u2019s the truly generic component here.<\/p>\n<p>The macro <em>returns a function<\/em>, which serves as the handler for the listener you\u2019ll create in the next step. For this function to be as generic as possible, it will be agnostic as to what the event was. It will do this by accepting the <a href=\"https:\/\/developer.mozilla.org\/en\/docs\/Web\/API\/Event\">Event object<\/a> as its parameter, and parsing that for all the data it needs.<\/p>\n<p>Showing is easier than telling, so here\u2019s the code for you to copy-paste:<\/p>\n<p><strong>Macro Name<\/strong>: {{generic event handler}}<br \/><strong>Macro Type<\/strong>: Custom JavaScript<\/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>() {\n  <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">function<\/span>(e) {\n    dataLayer.push({\n      <span style=\"color:#a50\">'event'<\/span>: <span style=\"color:#a50\">'event.'<\/span>+e.type,\n      <span style=\"color:#a50\">'gtm.element'<\/span>: e.target,\n      <span style=\"color:#a50\">'gtm.elementClasses'<\/span>: e.target.className || <span style=\"color:#a50\">''<\/span>,\n      <span style=\"color:#a50\">'gtm.elementId'<\/span>: e.target.id || <span style=\"color:#a50\">''<\/span>,\n      <span style=\"color:#a50\">'gtm.elementTarget'<\/span>: e.target.target || <span style=\"color:#a50\">''<\/span>,\n      <span style=\"color:#a50\">'gtm.elementUrl'<\/span>: e.target.href || e.target.action || <span style=\"color:#a50\">''<\/span>,\n      <span style=\"color:#a50\">'gtm.originalEvent'<\/span>: e\n    });\n  }\n}\n<\/code><\/pre>\n<\/div>\n<p>This, in my opinion, is a pretty close emulation of how GTM\u2019s listeners work. What\u2019s important is that the object pushed into dataLayer does its best to mimic the design pattern of GTM\u2019s own listeners.<\/p>\n<p>Let\u2019s go over the code line-by-line.<\/p>\n<p><code>return function(e) { ... }<\/code> is the wrapper. The point here is that this macro must <em>return a function<\/em>, since the listener we\u2019ll create in the following chapter requires a function or object as a parameter. If the macro wouldn\u2019t return a function but rather run the code itself, you\u2019d be sending some weird empty events every time the listener tag is written to the page template.<\/p>\n<p><code>dataLayer.push({ ... });<\/code> is where the magic happens. Here the triggered event is pushed into dataLayer by observing the design patterns of GTM\u2019s own listeners. Now, you can observe these patterns if you want, or you can use your own syntax. I\u2019m a big fan of symmetry, which is why I prefer to follow GTM\u2019s syntax. This might result in some conflicts if GTM introduces a similar event listener out-of-the-box, but in that case it would be a good idea to migrate to this proprietary listener anyway.<\/p>\n<p><code>'event': 'event.'+e.type,<\/code> pushes a value into the \u2018event\u2019 data layer variable. It takes the <code>type<\/code> property from the event object, which is a string representing what type of listener was fired, e.g. \u201cchange\u201d, \u201cblur\u201d, \u201ccopy\u201d. So if the event was of type <em>change<\/em>, this push would actually look like: <code>'event': 'event.change'<\/code>. (By the way, remember <a href=\"https:\/\/www.youtube.com\/watch?v=ULjNjzY7Ei0\">E-Type<\/a>?)<\/p>\n<p><code>'gtm.element': e.target,<\/code> pushes the element the event occurred on into the dataLayer variable \u2018gtm.element\u2019. This is a design pattern, and if you look at your click listeners and link click listeners, a similar object is always found in those as well. The idea here is that you can then use your Data Layer Variable Macro to explore properties of this \u2018gtm.element\u2019 object if you want to dig deeper into the DOM.<\/p>\n<p><code>'gtm.elementClasses': e.target.className || '',<\/code> pushes the class of the event target into the variable \u2018gtm.elementClasses\u2019. If there is no class on the HTML object, an empty string is pushed instead.<\/p>\n<p><code>'gtm.elementId': e.target.id || '',<\/code> pushes the ID of the event target into the variable \u2018gtm.elementId\u2019. If there is no ID on the HTML object, an empty string is pushed instead.<\/p>\n<p><code>'gtm.elementTarget': e.target.target || '',<\/code> pushes the target of the event target (sounds weird) into the variable \u2018gtm.elementTarget\u2019. If there is no target attribute on the HTML object, an empty string is pushed instead.<\/p>\n<p><code>'gtm.elementUrl': e.target.href || e.target.action || '',<\/code> pushes either the href or the action attribute of the event target into the variable \u2018gtm.elementUrl\u2019. If there are no such attributes on the HTML object, an empty string is pushed instead.<\/p>\n<p><code>'gtm.originalEvent': e<\/code> is my own addition to this design pattern. Every now and then you might want to access the original event, exposed by the listeners. With GTM\u2019s out-of-the-box listeners, this is currently not possible, since they only expose the <code>e.target<\/code> property of this event object. However, especially if you want to do stuff like identify clicks created by code and not by the user, access to the event object is a must. I hope this will be a standard feature in GTM\u2019s own listeners as well.<\/p>\n<p>So that\u2019s what the macro looks like. It\u2019s possible some of the patterns need more work, and nothing is stopping you from extending the number of variables that are pushed into the dataLayer. I consider these variables to be the <em>minimum<\/em> set you\u2019ll need in order to provide enough information for your tags while still remaining economical and conscious of best practices.<\/p>\n<h2 id=\"the-listener-tag\">The listener tag<\/h2>\n<p>Now that we have our generic event handler, the next step is to create a tag which sets up the listener. The key here is recognizing just which listener you want to set up. Also, for symmetry\u2019s sake I will only show how to prime the event listener on the <code>document<\/code> node, because that\u2019s the generic way AND the way GTM\u2019s own proprietary listeners work. If you want, you can attach the listeners to specific DOM nodes, which reduces the risk of <a href=\"https:\/\/www.simoahava.com\/analytics\/dont-gtm-listeners-work\/\">propagation problems<\/a>, but as a solution it won\u2019t be as generic any more.<\/p>\n<p>First, here\u2019s the listener code itself. Put this in a Custom HTML Tag, and add a firing rule which uses either <strong>{{event}} equals gtm.js<\/strong> if you\u2019re attaching the listener on the <code>document<\/code> node, or <strong>{{event}} equals gtm.dom<\/strong> if you\u2019re listening on specific HTML elements.<\/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-html\" data-lang=\"html\">script&gt;\n  (<span style=\"color:#00a\">function<\/span>() {\n    <span style=\"color:#00a\">var<\/span> eventType = <span style=\"color:#a50\">\"change\"<\/span>; <span style=\"color:#aaa;font-style:italic\">\/\/ Modify this to reflect the event type you want to listen for\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#00a\">if<\/span> (<span style=\"color:#0aa\">document<\/span>.addEventListener) { \n      <span style=\"color:#0aa\">document<\/span>.addEventListener(eventType, {{generic event handler}}, <span style=\"color:#00a\">false<\/span>); \n    } <span style=\"color:#00a\">else<\/span> <span style=\"color:#00a\">if<\/span> (<span style=\"color:#0aa\">document<\/span>.attachEvent) { \n      <span style=\"color:#0aa\">document<\/span>.attachEvent(<span style=\"color:#a50\">'on'<\/span> + eventType, {{generic event handler}}); \n    }\n  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>On the first line, you specify just what type of event you want to listen for. For the full list of supported types, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Events\">follow this link<\/a>. Remember, you can also dispatch and listen to your own custom events, which makes this solution even more flexible. Here\u2019s MDN\u2019s excellent guide on <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Guide\/Events\/Creating_and_triggering_events\">creating and triggering events<\/a>.<\/p>\n<p>Anyway, here\u2019s a list of some of the most popular event types:<\/p>\n<ul>\n<li>\n<p><em>beforeunload<\/em> &#8211; Fire a listener when the window, the document, and all resources are about to be unloaded (e.g. when someone is closing the browser window).<\/p>\n<\/li>\n<li>\n<p><em>blur<\/em> &#8211; An element has lost focus (e.g. the user has left a form field). Note, this doesn\u2019t bubble by default, meaning a listener on the <code>document<\/code> node won\u2019t be able to catch it. To activate event delegation, you\u2019ll need to set the last parameter in the <code>document.addEventListener()<\/code> call to <strong>true<\/strong> instead of <strong>false<\/strong>.<\/p>\n<\/li>\n<li>\n<p><em>change<\/em> &#8211; The value of an element changes between receiving and losing focus (e.g. the user enters a form field, types something in, and leaves the field).<\/p>\n<\/li>\n<li>\n<p><em>click<\/em> &#8211; A click is registered on an element (use GTM\u2019s Click Listener instead).<\/p>\n<\/li>\n<li>\n<p><em>contextmenu<\/em> &#8211; The right mouse button is clicked.<\/p>\n<\/li>\n<li>\n<p><em>copy<\/em> &#8211; Text is copied to the clipboard.<\/p>\n<\/li>\n<li>\n<p><em>cut<\/em> &#8211; Text is cut to the clipboard.<\/p>\n<\/li>\n<li>\n<p><em>dblclick<\/em> &#8211; A double-click is registered on an element.<\/p>\n<\/li>\n<li>\n<p><em>focus<\/em> &#8211; An element has received focus (e.g. the user has left a form field). Note, this doesn\u2019t bubble by default, meaning a listener on the <code>document<\/code> node won\u2019t be able to catch it. To activate event delegation, you\u2019ll need to set the last parameter in the <code>document.addEventListener()<\/code> call to <strong>true<\/strong> instead of <strong>false<\/strong>.<\/p>\n<\/li>\n<li>\n<p><em>keydown<\/em> &#8211; A key is pressed down.<\/p>\n<\/li>\n<li>\n<p><em>keyup<\/em> &#8211; A pressed down key is released.<\/p>\n<\/li>\n<li>\n<p><em>mousedown<\/em> &#8211; The mouse button is pressed down.<\/p>\n<\/li>\n<li>\n<p><em>mouseenter<\/em> &#8211; The mouse pointer is moved over the element where the listener is attached. Won\u2019t really work if the listener is on the <code>document<\/code> node.<\/p>\n<\/li>\n<li>\n<p><em>mouseleave<\/em> &#8211; The mouse pointer is moved off the element where the listener is attached. Won\u2019t really work if the listener is on the <code>document<\/code> node.<\/p>\n<\/li>\n<li>\n<p><em>mouseout<\/em> &#8211; The mouse pointer is moved off the element where the listener is attached or one of its children.<\/p>\n<\/li>\n<li>\n<p><em>mouseover<\/em> &#8211; The mouse pointer is moved over the element where the listener is attached or one of its children.<\/p>\n<\/li>\n<li>\n<p><em>mouseup<\/em> &#8211; The pressed down mouse button is released.<\/p>\n<\/li>\n<li>\n<p><em>orientationchange<\/em> &#8211; The orientation (portrait \/ landscape) of the screen changes.<\/p>\n<\/li>\n<li>\n<p><em>reset<\/em> &#8211; A form is reset.<\/p>\n<\/li>\n<li>\n<p><em>scroll<\/em> &#8211; A document view or element is scrolled.<\/p>\n<\/li>\n<li>\n<p><em>submit<\/em> &#8211; A form submit is registered (use GTM\u2019s Form Submit Listener instead).<\/p>\n<\/li>\n<\/ul>\n<p>When the Custom HTML Tag is written on the page, it attaches the listener of your choice on the document node. The event handler is the generic event handler function you created in the previous chapter. Then, when the event occurs, the function is executed with the event object as its parameter. This event object is then parsed and pushed into dataLayer with a bunch of properties that you can access with the Data Layer Variable Macro.<\/p>\n<h2 id=\"example-with-the-change-listener\">Example with the Change Listener<\/h2>\n<p>Here\u2019s a simple example. I have some form fields on a web page. Whenever a value of a form field changes, i.e. a user writes \/ edits \/ deletes text in it, I want to push a virtual pageview with the URL path <strong>\/form\/(field-name)-(field-value)<\/strong>. So if the form field\u2019s name is \u201csearch\u201d and value is \u201cGTM\u201d, I want to send the virtual pageview with the path <strong>\/form\/search-GTM<\/strong>.<\/p>\n<p>So let\u2019s get started. I have my <strong>{{generic event handler}}<\/strong> macro which I created earlier, and I have my Change Listener Tag firing on <strong>{{event}} equals gtm.js<\/strong> as you can see:<\/p>\n<div style=\"aspect-ratio: 1110 \/ 566;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/change-listener.jpg\" title=\"Change Listener\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"566\" width=\"1110\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/change-listener.jpg#ZgotmplZ\" alt=\"Change Listener\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, I\u2019ll need to create two new Data Layer Variable Macros to capture the field name and field value, respectively. First, here\u2019s the Data Layer Variable Macro <strong>{{field name}}<\/strong>:<\/p>\n<div style=\"aspect-ratio: 618 \/ 534;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/data-layer-macro-field-name.jpg\" title=\"Data Layer Macro field name\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"534\" width=\"618\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/data-layer-macro-field-name.jpg#ZgotmplZ\" alt=\"Data Layer Macro field name\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>As you can see, I use \u201c(not set)\u201d as the placeholder if the field has no name attribute.<\/p>\n<p>And here\u2019s the Data Layer Variable Macro <strong>{{field value}}<\/strong> for the field value:<\/p>\n<div style=\"aspect-ratio: 622 \/ 534;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/data-layer-macro-field-value.jpg\" title=\"Data Layer Macro field value\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"534\" width=\"622\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/data-layer-macro-field-value.jpg#ZgotmplZ\" alt=\"Data Layer Macro field value\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Again, I use \u201c(not set)\u201d if the field has no value.<\/p>\n<p>Finally, I\u2019ll need my virtual pageview tag. It\u2019s just a normal Universal Analytics pageview tag, but it uses the <strong>Document Path<\/strong> field. Also, the firing rule for this tag needs to be <strong>{{event}} equals event.change<\/strong>, so that the tag fires only when a \u2018change\u2019 event is registered by the custom listener.<\/p>\n<div style=\"aspect-ratio: 1470 \/ 1044;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/virtual-pageview-tag.jpg\" title=\"Virtual Pageview Tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1044\" width=\"1470\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/virtual-pageview-tag.jpg#ZgotmplZ\" alt=\"Virtual Pageview Tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>I concatenate the string \u201c\/form\/{{field name}}-{{field value}}\u201d, since the macros are resolved at runtime, and I\u2019ll end up with a nice, clean URL path.<\/p>\n<p>I manage to test this live by typing text into the search field and leaving the field. The event.change listener fires, and my debug panel shows that the Document Path has been processed correctly:<\/p>\n<div style=\"aspect-ratio: 684 \/ 381;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2014\/08\/change-test.jpg\" title=\"Testing the change listener\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"381\" width=\"684\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2014\/08\/change-test.jpg#ZgotmplZ\" alt=\"Testing the change listener\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Naturally, don\u2019t forget to check GA\u2019s Real Time report to verify the data is flowing in correctly.<\/p>\n<h2 id=\"conclusions\">Conclusions<\/h2>\n<p>This post was about creating a generic event handler for all your custom listener needs. I urge you to explore beyond the out-of-the-box setups that GTM provides. However, once there\u2019s overlap with GTM\u2019s features, I strongly suggest you leverage the tag manager\u2019s own listeners, since that will ensure that they\u2019ll stay up-to-date with possible changes under the hood. I also recommend that you try to observe best practices, and that you emulate GTM\u2019s design patterns to your best ability.<\/p>\n<p>Like I said, I\u2019ve written a lot about GTM\u2019s listeners in various posts. Here are some guides you might enjoy reading as well:<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/dont-gtm-listeners-work\/\">Why Don\u2019t My GTM Listeners Work?<\/a><br \/>\nThis is still one of the most asked questions I get. Please, read this post. You\u2019ll learn about event delegation, and why so often interfering code prevents events from bubbling up to GTM\u2019s listeners. Here\u2019s a more recent rant on the topic: <a href=\"https:\/\/plus.google.com\/109635181158374226872\/posts\/23Qh9dvSar9\">My Google+ rant<\/a>.<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-dom-listener\/\">Google Tag Manager: The DOM Listener<\/a><br \/>\nYou can use MutationObserver to listen for changes on the page that occur without an actual event firing or page refreshing.<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-history-listener\/\">Google Tag Manager: The History Listener<\/a><br \/>\nA review of GTM\u2019s History Listener.<\/p>\n<p>Also, I allude to listeners in most of my Google Tag Manager posts, so be sure to <a href=\"https:\/\/www.simoahava.com\/tags\/google-tag-manager\">read the rest of them<\/a> if you have time.<\/p>\n<p>This was a long and rather advanced guide. Go and eat an ice cream, you\u2019ve earned it!<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>(UPDATE 1 Oct 2014 Due to a change in how macros work in Debug Mode, the {{generic event handler}} macro no longer works when testing in Debug Mode. That means that you\u2019ll have to test your custom listener in a live container (I know, ouch!). If you want to test in Debug Mode, you\u2019ll have [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":163373,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[834,9252,32680,44120],"dealstore":[],"offerexpiration":[],"class_list":["post-163372","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-custom","tag-event","tag-gtm","tag-listeners"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Custom Event Listeners For GTM - 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=163372\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom Event Listeners For GTM - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"(UPDATE 1 Oct 2014 Due to a change in how macros work in Debug Mode, the {{generic event handler}} macro no longer works when testing in Debug Mode. That means that you\u2019ll have to test your custom listener in a live container (I know, ouch!). If you want to test in Debug Mode, you\u2019ll have [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fivemor.com\/?p=163372\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-29T16:33:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1719\" \/>\n\t<meta property=\"og:image:height\" content=\"672\" \/>\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=163372#article\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\"},\"headline\":\"Custom Event Listeners For GTM\",\"datePublished\":\"2025-03-29T16:33:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372\"},\"wordCount\":2393,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg\",\"keywords\":[\"Custom\",\"event\",\"GTM\",\"listeners\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fivemor.com\/?p=163372#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fivemor.com\/?p=163372\",\"url\":\"https:\/\/fivemor.com\/?p=163372\",\"name\":\"Custom Event Listeners For GTM - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372#primaryimage\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg\",\"datePublished\":\"2025-03-29T16:33:46+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fivemor.com\/?p=163372#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fivemor.com\/?p=163372\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/?p=163372#primaryimage\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg\",\"width\":1719,\"height\":672},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fivemor.com\/?p=163372#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/fivemor.com\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Custom Event Listeners For GTM\"}]},{\"@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":"Custom Event Listeners For GTM - 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=163372","og_locale":"en_US","og_type":"article","og_title":"Custom Event Listeners For GTM - Som2ny Network","og_description":"(UPDATE 1 Oct 2014 Due to a change in how macros work in Debug Mode, the {{generic event handler}} macro no longer works when testing in Debug Mode. That means that you\u2019ll have to test your custom listener in a live container (I know, ouch!). If you want to test in Debug Mode, you\u2019ll have [&hellip;]","og_url":"https:\/\/fivemor.com\/?p=163372","og_site_name":"Som2ny Network","article_published_time":"2025-03-29T16:33:46+00:00","og_image":[{"width":1719,"height":672,"url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg","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=163372#article","isPartOf":{"@id":"https:\/\/fivemor.com\/?p=163372"},"author":{"name":"admin","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371"},"headline":"Custom Event Listeners For GTM","datePublished":"2025-03-29T16:33:46+00:00","mainEntityOfPage":{"@id":"https:\/\/fivemor.com\/?p=163372"},"wordCount":2393,"commentCount":0,"publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"image":{"@id":"https:\/\/fivemor.com\/?p=163372#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg","keywords":["Custom","event","GTM","listeners"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fivemor.com\/?p=163372#respond"]}]},{"@type":"WebPage","@id":"https:\/\/fivemor.com\/?p=163372","url":"https:\/\/fivemor.com\/?p=163372","name":"Custom Event Listeners For GTM - Som2ny Network","isPartOf":{"@id":"https:\/\/fivemor.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/fivemor.com\/?p=163372#primaryimage"},"image":{"@id":"https:\/\/fivemor.com\/?p=163372#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg","datePublished":"2025-03-29T16:33:46+00:00","breadcrumb":{"@id":"https:\/\/fivemor.com\/?p=163372#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fivemor.com\/?p=163372"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/?p=163372#primaryimage","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/1743266028_custom-listeners.jpg","width":1719,"height":672},{"@type":"BreadcrumbList","@id":"https:\/\/fivemor.com\/?p=163372#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fivemor.com\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Custom Event Listeners For GTM"}]},{"@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\/163372","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=163372"}],"version-history":[{"count":0,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/163372\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/media\/163373"}],"wp:attachment":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=163372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=163372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=163372"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=163372"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=163372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}