{"id":142798,"date":"2025-03-19T02:18:55","date_gmt":"2025-03-19T02:18:55","guid":{"rendered":"https:\/\/peraltafinancing.com\/analytics\/track-form-abandonment-with-google-tag-manager\/"},"modified":"2025-03-19T02:18:55","modified_gmt":"2025-03-19T02:18:55","slug":"track-form-abandonment-with-google-tag-manager","status":"publish","type":"post","link":"https:\/\/fivemor.com\/?p=142798","title":{"rendered":"Track Form Abandonment With Google Tag Manager"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<p><strong>Form abandonment<\/strong> isn\u2019t always easy to define. Most often, it refers to when someone starts to fill in an HTML form, but leaves the page without submitting it. As a definition, this works nicely. However, with multi-page forms it naturally refers only to the <em>last<\/em> page of the form. Also, especially with government institutions, forms can be saved to be submitted later. Here, again, <em>form abandonment<\/em> must be reconsidered.<\/p>\n<div style=\"aspect-ratio: 1740 \/ 524;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/form-abandonment.jpg\" title=\"Form abandonment in Google Tag Manager\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"524\" width=\"1740\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/form-abandonment.jpg#ZgotmplZ\" alt=\"Form abandonment in Google Tag Manager\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>In this article, I\u2019ll go over <strong>four<\/strong> different ways to track form abandonment in <a href=\"https:\/\/analytics.google.com\">Google Analytics<\/a>, using <a href=\"https:\/\/tagmanager.google.com\">Google Tag Manager<\/a> to setup the tracking. The definition I\u2019ll use is the first one: abandonment occurs when someone enters a form page, but leaves it without submitting the form. Do note that GA might not be the right tool to actually track issues with your form. There are dedicated resources for that, such as <a href=\"http:\/\/www.clicktale.com\">ClickTale<\/a> or <a href=\"http:\/\/www.hotjar.com\">Hotjar<\/a>. But if you want to measure form engagement as part of a more coherent visitor journey, then it might make sense to track this engagement (or lack thereof) in Google Analytics.<\/p>\n<p>The different methods I\u2019ll go over, in order of difficulty (as perceived by myself):<\/p>\n<ol>\n<li>\n<p>Advanced Segment in Google Analytics<\/p>\n<\/li>\n<li>\n<p>Event sent if form interacted with<\/p>\n<\/li>\n<li>\n<p>Event sent with the last field interacted with<\/p>\n<\/li>\n<li>\n<p>Event sent with full interaction history<\/p>\n<\/li>\n<\/ol>\n<p>Well, the first one can be done without Google Tag Manager at all. But the others require some setting up.<\/p>\n<p>The <em>technology<\/em>, if you will, is based on the beautiful combination of <code>beforeUnload<\/code>, a browser event that is dispatched when the user leaves or closes the web page, and the <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/analyticsjs\/field-reference#transport\">transport<\/a> field in Universal Analytics. With these in place, GA will receive an event that contains information about form interaction when the user leaves the form page. You can then use an Advanced Segment to only view interaction data for sessions where the form was not submitted.<\/p>\n<p>I\u2019ll even show you a simple way of sending the event only if the user didn\u2019t submit the form.<\/p>\n<p>Note that this guide is created around a very simple, basic form, which has been created according to <strong>B<\/strong>est <strong>P<\/strong>ractices; capital B, capital P. If you have some Ajax-postback-dynamic-validation-jQuery-horror-ultra-modern-form, this might not work for you, and you\u2019ll have to put your JavaScript skills to the test as you apply these lessons to the abomination you\u2019re cursed to work with.<\/p>\n<p>Don\u2019t say I didn\u2019t warn you!<\/p>\n<p>(<strong>UPDATE<\/strong>. My colleague, Lauri Piispanen, wrote a very, very nice upgrade to the Custom HTML Tag, and it\u2019s freely downloadable from <a href=\"https:\/\/github.com\/lauripiispanen\/auto-gtm-form-abandonment\">his GitHub repo<\/a>. It automatically tracks multiple forms on the page!)<\/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=\"advanced-segment-in-google-analytics\">Advanced Segment in Google Analytics<\/h2>\n<p>In Google Analytics, the simplest way to track form abandonment is to create an <strong>Advanced Segment<\/strong>, which includes Sessions where the form page was visited, but the session itself did not include a conversion for the form submission:<\/p>\n<div style=\"aspect-ratio: 1818 \/ 760;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/advanced-segment.jpg\" title=\"Advanced Segment for Form Abandonment\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"760\" width=\"1818\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/advanced-segment.jpg#ZgotmplZ\" alt=\"Advanced Segment for Form Abandonment\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>This is OK. It\u2019s not polished, as it doesn\u2019t really tell us anything about <em>why<\/em> the form was abandoned. Also, a simple page view of the form page is simply not a good way to extrapolate intent. But for all intents and purposes, this exposes possible flaws in a crucial funnel on your website.<\/p>\n<p>As you create the Events in the chapters that follow, you can substitute the <strong>Page<\/strong> rule in the segment condition with an Event rule that matches the Event you\u2019ve created.<\/p>\n<h2 id=\"the-base-custom-html-tag\">The base Custom HTML Tag<\/h2>\n<p>This Custom HTML Tag is what we\u2019ll use to setup the <code>beforeUnload<\/code> listener as well as the interaction handlers created incrementally in the following chapters.<\/p>\n<p>So, <code>beforeUnload<\/code> is a browser event that is dispatched when the page is unloaded from the browser. Most typical ways for a page to unload is if the user is redirected to some other page (via a link or form submission, for example), or if the user decides to close the browser. Naturally, if the user\u2019s computer crashes, no controlled <code>beforeUnload<\/code> event is dispatched.<\/p>\n<p>We want to use this browser event to invoke a <code>dataLayer.push()<\/code> when the user leaves the page. This <code>push()<\/code> will include a custom <code>event<\/code> key as well as values for the fields in the Event Tag we\u2019ll create in the next chapter.<\/p>\n<p>Create a Custom HTML Tag, give it some illustrious name, and set it to fire only on pages with forms. Here\u2019s the code we\u2019ll work on. Just copy-paste it into the Tag.<\/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> eventAction;\n    <span style=\"color:#0aa\">window<\/span>.addEventListener(<span style=\"color:#a50\">'beforeunload'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n        <span style=\"color:#a50\">'event'<\/span> : <span style=\"color:#a50\">'formAbandonment'<\/span>,\n        <span style=\"color:#a50\">'eventCategory'<\/span> : <span style=\"color:#a50\">'Form Abandonment'<\/span>,\n        <span style=\"color:#a50\">'eventAction'<\/span> : eventAction\n      });\n    });\n  \n    <span style=\"color:#aaa;font-style:italic\">\/\/ Add actual logic here...\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>That\u2019s pretty simple, right? All you do is attach a listener to the page, which waits for the <code>beforeunload<\/code> event. When that takes place, a <code>dataLayer.push()<\/code> is invoked, which is then used to fire a Google Analytics Event Tag with all your abandonment issues within. The whole thing is wrapped in an immediately-invoked function expression to protect the global namespace from being polluted with your variables.<\/p>\n<h2 id=\"the-event-tag\">The Event Tag<\/h2>\n<p>Before we go on, let\u2019s create the Event Tag itself. And before we do that, you\u2019ll need to create a Custom Event Trigger and two Data Layer Variables.<\/p>\n<p>The Custom Event Trigger looks like this:<\/p>\n<div style=\"aspect-ratio: 936 \/ 820;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/event-trigger.jpg\" title=\"Custom Event Trigger\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"820\" width=\"936\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/event-trigger.jpg#ZgotmplZ\" alt=\"Custom Event Trigger\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>And the two Data Layer Variables look like this:<\/p>\n<div style=\"aspect-ratio: 766 \/ 1032;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/dlv-eventcategory.jpg\" title=\"DLV - eventCategory\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1032\" width=\"766\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/dlv-eventcategory.jpg#ZgotmplZ\" alt=\"DLV - eventCategory\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<div style=\"aspect-ratio: 746 \/ 1024;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/dlv-eventaction.jpg\" title=\"DLV - eventAction\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1024\" width=\"746\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/dlv-eventaction.jpg#ZgotmplZ\" alt=\"DLV - eventAction\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>Next, onto the Event Tag itself. It\u2019s your basic affair, with a simple Event Category and Event Action. I\u2019ve set the <strong>Non-Interaction<\/strong> field to True, since this isn\u2019t really a user interaction but more like metadata about the page view, but you can do as you wish.<\/p>\n<p><strong>Remember to add your new Custom Event Trigger you just created to this Tag.<\/strong><\/p>\n<p>The Tag itself looks like this:<\/p>\n<div style=\"aspect-ratio: 602 \/ 1436;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/07\/event-tag.jpg\" title=\"GA Event Tag\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1436\" width=\"602\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/07\/event-tag.jpg#ZgotmplZ\" alt=\"GA Event Tag\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>You\u2019ll need one more thing that\u2019s not visible in the screenshot. Go to <strong>More Settings<\/strong> -&gt; <strong>Fields to Set<\/strong>, and add the following:<\/p>\n<p>Field Name: <strong>transport<\/strong><br \/>Value: <strong>beacon<\/strong><\/p>\n<p>This will utilize a beautiful feature of the Universal Analytics library, where any HTTP request that is initiated as the page is unloaded will be allowed to complete before the page or browser is run down. It doesn\u2019t have <a href=\"http:\/\/caniuse.com\/#feat=beacon\">stellar browser support<\/a>, which means that horrible browsers such as Internet Explorer might simply exit the page before the request to GA completes. But we can live with that.<\/p>\n<p>Now that we\u2019ve taken care of the foundations, we can get to the juicy stuff. Are you ready? I didn\u2019t hear you? ARE YOU READY?<\/p>\n<p>Sorry for that.<\/p>\n<h2 id=\"track-simple-interaction\">Track simple interaction<\/h2>\n<p>\u201cSimple interaction\u201d here translates to: <strong>the user changed the value of any form field<\/strong>. That\u2019s all we care about. It doesn\u2019t matter which field, and it doesn\u2019t matter how many form fields. We want to draw a line between two types of people: those who didn\u2019t interact with the form at all, and those who did.<\/p>\n<p>To make this work, you\u2019ll need to add <strong>another<\/strong> custom listener into the Custom HTML Tag. Here\u2019s what we\u2019ll go with in the Custom HTML Tag you\u2019ve already created:<\/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> eventAction;\n    <span style=\"color:#00a\">var<\/span> formSelector = <span style=\"color:#a50\">'form'<\/span>; <span style=\"color:#aaa;font-style:italic\">\/\/ Modify this CSS selector to match your form. Default is first form on the page.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#0aa\">window<\/span>.addEventListener(<span style=\"color:#a50\">'beforeunload'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      <span style=\"color:#00a\">if<\/span> (eventAction) {\n        <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n          <span style=\"color:#a50\">'event'<\/span> : <span style=\"color:#a50\">'formAbandonment'<\/span>,\n          <span style=\"color:#a50\">'eventCategory'<\/span> : <span style=\"color:#a50\">'Form Abandonment'<\/span>,\n          <span style=\"color:#a50\">'eventAction'<\/span> : eventAction\n        });\n      }\n    });\n  \n    <span style=\"color:#0aa\">document<\/span>.querySelector(formSelector).addEventListener(<span style=\"color:#a50\">'change'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      eventAction = <span style=\"color:#a50\">'True'<\/span>;\n    });\n  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>In the beginning, you define a <code>formSelector<\/code>. This is a basic CSS selector that you use to target a single form, e.g. \u2018<strong>#formId<\/strong>\u2019 or \u2018<strong>.formClass<\/strong>\u2019. If you choose a selector that can have potentially multiple hits on the page, this script will only listen to the <strong>first<\/strong> instance.<\/p>\n<p>In the end, we add a <code>change<\/code> listener to this particular form. If a <code>change<\/code> event is registered in any of the form fields, i.e. the form field value changes, then the <code>eventAction<\/code> variable is given a value \u2018true\u2019.<\/p>\n<p>Finally, the <code>dataLayer.push()<\/code> that sends the payload to <code>dataLayer<\/code> which triggers the Event Tag is set to execute only if the <code>eventAction<\/code> variable is set. Thus, you\u2019ll only report on potential form abandonments if the user has interacted with the form.<\/p>\n<p>The Event Tag will have Event Category <strong>Form Abandonment<\/strong> and Event Action <strong>True<\/strong>.<\/p>\n<p>To get the most out of this solution, you\u2019d create an Advanced Segment in Google Analytics, where you<\/p>\n<p>You need the \u201cgoal completions is 0\u201d because this Event will be dispatched when a form is submitted as well. In order to only send the Event when the user has interacted with the form but did not submit it, jump to chapter 7.<\/p>\n<p>Like I said, this is a very simple, rudimentary way of analyzing traffic that interacted but did not submit.<\/p>\n<h2 id=\"track-last-field-interacted-with\">Track last field interacted with<\/h2>\n<p>Let\u2019s improve the previous solution a little. Instead of just blindly looking at who interacted and who didn\u2019t, let\u2019s send the <strong>last field<\/strong> the user interacted with to GA. Maybe this will give us some clue about what made the user abandon the form.<\/p>\n<p>So, modify the Custom HTML Tag to look like this:<\/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> eventAction;\n    <span style=\"color:#00a\">var<\/span> formSelector = <span style=\"color:#a50\">'form'<\/span>; <span style=\"color:#aaa;font-style:italic\">\/\/ Modify this CSS selector to match your form. Default is first form on the page.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#00a\">var<\/span> attribute = <span style=\"color:#a50\">'name'<\/span>;\n    <span style=\"color:#0aa\">window<\/span>.addEventListener(<span style=\"color:#a50\">'beforeunload'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      <span style=\"color:#00a\">if<\/span> (eventAction) {\n        <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n          <span style=\"color:#a50\">'event'<\/span> : <span style=\"color:#a50\">'formAbandonment'<\/span>,\n          <span style=\"color:#a50\">'eventCategory'<\/span> : <span style=\"color:#a50\">'Form Abandonment'<\/span>,\n          <span style=\"color:#a50\">'eventAction'<\/span> : eventAction\n        });\n      }\n    });\n  \n    <span style=\"color:#0aa\">document<\/span>.querySelector(formSelector).addEventListener(<span style=\"color:#a50\">'change'<\/span>, <span style=\"color:#00a\">function<\/span>(e) {\n      eventAction = e[<span style=\"color:#a50\">'target'<\/span>].getAttribute(attribute);\n    });\n  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>We\u2019ve added a new variable, <code>attribute<\/code>. In this, you specify the attribute name that you want to collect to describe which form field was the last one that was interacted with. I would recommend against choosing <strong>value<\/strong> or anything that the user can add content to. This is to protect your GA account from inadvertently collecting personally identifiable information such as e-mail addresses and such.<\/p>\n<p>The other additions are the <code>e<\/code> parameter in the callback function of the \u2018change\u2019 listener, and the attribute value of the <code>e['target']<\/code> object as the value that <code>eventAction<\/code> retrieves. The <code>target<\/code> parameter of the event object contains the HTML element that was the target of the event action, which in this case would be the form field whose value changed.<\/p>\n<p>I would recommend you use the <code>name<\/code> attribute, since it\u2019s usually the most descriptive one (especially with well-formed forms).<\/p>\n<p>So, an input field like <code><input name=\"&quot;email&quot;\" type=\"&quot;text&quot;\"\/><\/code> would send \u2018email\u2019 as the Event Action of the Event Tag.<\/p>\n<p>Now, again, this would send an Event every time someone leaves the form page, so you\u2019ll get some false positives as well. Remember to apply the Advanced Segment, where you look for sessions with this event (using the Event Category filter in the segment settings), and sessions without any form submissions (using a goal completion filter or something similar).<\/p>\n<h2 id=\"get-full-interaction-history\">Get full interaction history<\/h2>\n<p>Here we\u2019ll extend the Event Action value that is sent to Google Analytics to include a complete \u201chistory\u201d of fields that were interacted with this. This is done as a trail that might look like this:<\/p>\n<p><strong>firstName &gt; lastName &gt; address &gt; creditCardNumber &gt; expirationDate &gt; creditCardNumber<\/strong><\/p>\n<p>As you can see, it will record multiple interactions as well. The history example above would indicate that the Credit Card Number field was the one that caused the user to disdainfully abandon your form.<\/p>\n<p>To make this work, here\u2019s the revamped version of the Custom HTML Tag:<\/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> formSelector = <span style=\"color:#a50\">'form'<\/span>; <span style=\"color:#aaa;font-style:italic\">\/\/ Modify this CSS selector to match your form. Default is first form on the page.\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>    <span style=\"color:#00a\">var<\/span> attribute = <span style=\"color:#a50\">'name'<\/span>;\n    <span style=\"color:#00a\">var<\/span> history = [];\n    <span style=\"color:#0aa\">window<\/span>.addEventListener(<span style=\"color:#a50\">'beforeunload'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      <span style=\"color:#00a\">if<\/span> (history.length) {\n        <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n          <span style=\"color:#a50\">'event'<\/span> : <span style=\"color:#a50\">'formAbandonment'<\/span>,\n          <span style=\"color:#a50\">'eventCategory'<\/span> : <span style=\"color:#a50\">'Form Abandonment'<\/span>,\n          <span style=\"color:#a50\">'eventAction'<\/span> : history.join(<span style=\"color:#a50\">' &gt; '<\/span>)\n        });\n      }\n    });\n  \n    <span style=\"color:#0aa\">document<\/span>.querySelector(formSelector).addEventListener(<span style=\"color:#a50\">'change'<\/span>, <span style=\"color:#00a\">function<\/span>(e) {\n      history.push(e[<span style=\"color:#a50\">'target'<\/span>].getAttribute(attribute));\n    });\n  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>Let\u2019s see. We\u2019ve removed the variable <code>eventAction<\/code>, and opted for a new Array named <code>history<\/code>. Instead of checking for whether the <code>eventAction<\/code> variable has a value, we now check if the <code>history<\/code> Array has any contents. If it does, we <code>join()<\/code> the <code>history<\/code> Array as a string delimited with whitespace-&gt;-whitespace. So, an Array that looks like <code>['firstName', 'lastName', 'phone']<\/code> becomes <code>'firstName &gt; lastName &gt; phone'<\/code>.<\/p>\n<p>Finally, in the <code>change<\/code> listener we use the <code>history.push()<\/code> method to insert the specified attribute value of the changed form field into the <code>history<\/code> Array.<\/p>\n<p>Thus, each time the user changes a value of a form field, the specified attribute (\u2018name\u2019 is again recommended) value will be pushed into the <code>history<\/code> Array, and this is how we get our neatly formatted interaction history to GA as the Event Action value of the hit.<\/p>\n<p>This is, as you might have guessed, a very simple way of mapping form abandonment. Nevertheless, it does give you some idea about which fields are interacted with and how much. In fact, you can easily convert this from a form abandonment survey into an engagement analysis. Using some simple data analysis, you can map the most common paths in your form.<\/p>\n<h2 id=\"only-send-event-when-a-form-isnt-submitted\">Only send event when a form isn\u2019t submitted<\/h2>\n<p>The major caveat with all the previous examples, apart from the browser support, is that the event is sent every time the page is unloaded and a field has changed, so for <strong>successful<\/strong> form submissions as well. This means you\u2019ll need to create an Advanced Segment in GA to make the most of your form abandonment analysis.<\/p>\n<p>However, you can tweak the Custom HTML Tag slightly to only send the form abandonment event when the page unloads for some other reason than a form submission. To do this, the revised Custom HTML Tag should look like this:<\/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> eventAction, i;\n\n    <span style=\"color:#00a\">var<\/span> checkSubmit = <span style=\"color:#00a\">function<\/span>() {\n      i = <span style=\"color:#0aa\">window<\/span>.dataLayer.length - <span style=\"color:#099\">1<\/span>;\n      <span style=\"color:#00a\">while<\/span> (i &gt; -<span style=\"color:#099\">1<\/span>) {\n        <span style=\"color:#00a\">if<\/span> (<span style=\"color:#0aa\">window<\/span>.dataLayer[i][<span style=\"color:#a50\">'event'<\/span>] === <span style=\"color:#a50\">'gtm.formSubmit'<\/span>) {\n          <span style=\"color:#00a\">return<\/span> <span style=\"color:#00a\">true<\/span>;\n        }\n        i--;\n      }\n    };\n\n    <span style=\"color:#0aa\">window<\/span>.addEventListener(<span style=\"color:#a50\">'beforeunload'<\/span>, <span style=\"color:#00a\">function<\/span>() {\n      <span style=\"color:#00a\">if<\/span> (!checkSubmit()) {\n        <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n          <span style=\"color:#a50\">'event'<\/span> : <span style=\"color:#a50\">'formAbandonment'<\/span>,\n          <span style=\"color:#a50\">'eventCategory'<\/span> : <span style=\"color:#a50\">'Form Abandonment'<\/span>,\n          <span style=\"color:#a50\">'eventAction'<\/span> : eventAction\n        });\n      }\n    });\n  \n    <span style=\"color:#aaa;font-style:italic\">\/\/ Add actual logic here...\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>  })();\n<span style=\"color:#1e90ff;font-weight:bold\">script<\/span>&gt;<\/code><\/pre>\n<\/div>\n<p>The first change is that you define a new counter variable <code>i<\/code>. Next, there\u2019s a new mini-function in town called <code>checkSubmit()<\/code>. This loops through <code>dataLayer<\/code>, starting from the end, and returns the Boolean value <code>true<\/code> if an \u2018event\u2019 key with the value \u2018gtm.formSubmit\u2019 is found. This would indicate that the unload was due to a form submission.<\/p>\n<p>Finally, the <code>window.dataLayer.push()<\/code> is wrapped in an <code>if<\/code> block, which is executed only if the <code>checkSubmit()<\/code> function does <strong>not<\/strong> return a truthy value. This is because we want to send the Event only if a form submission <em>didn\u2019t<\/em> cause the page unload.<\/p>\n<p>You might be wondering why not just check against the value of the <strong>{{Event}}<\/strong> key. Well, GTM has some internal logic running which prevents the value of a Data Layer Variable from being modified during the lifetime of a Tag. Thus, <strong>{{Event}}<\/strong> will always return <strong>gtm.js<\/strong> or whatever event name you\u2019re using to fire the Custom HTML Tag in the first place.<\/p>\n<p>If you already have the <code>if<\/code> block there to check for either <code>eventAction<\/code> or <code>history.length<\/code>, you can simply add the <strong>checkSubmit()<\/strong> check with Boolean logic:<\/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\">if<\/span> (eventAction &amp;&amp; !checkSubmit()) {\n  ...\n}\n\n<span style=\"color:#00a\">if<\/span> (history.length &amp;&amp; !checkSubmit()) {\n  ...\n}\n<\/code><\/pre>\n<\/div>\n<p>This solution might not work on single-page apps or web pages which have forms that do not redirect. In these cases, you\u2019ll need to make additional checks to see if the form that was submitted was the one you\u2019re actually tracking. It\u2019s relatively simple, but I won\u2019t explain it here as it\u2019s an edge case.<\/p>\n<p>With JavaScript and GTM, it\u2019s always a little bit of give-and-take, so you\u2019ll need to modify these solutions to fit whatever frameworks and setups you have running on your site. With a generic, Best Practices -infused HTML form, though, these setups should work beautifully.<\/p>\n<h2 id=\"summary\">Summary<\/h2>\n<p>Tracking form abandonment is an interesting way to see what types of interactions (or lack thereof) result in your forms not being submitted. Fixing this funnel can be key to opening up your website to exponential goal conversions.<\/p>\n<p>However, <em>abandonment<\/em> is very difficult to define, and you need to ask the correct business questions first before you can start looking for a solution. The four different methods outlined here serve a very simple hypothesis that correlates the fields of a form with the user\u2019s tendency to leave the form unfinished. This correlation might not work on many forms.<\/p>\n<p>Like I mention in the guide, it would be very simple to convert this from a form abandonment analysis to a form interaction analysis, where you inspect the \u201chistory\u201d of the filled fields to see if users are bouncing around the form and not following the chronology or layout that you have established.<\/p>\n<p>If none of this resonates with you, at least you\u2019ll have some cool new tricks up your sleeve with the <code>transport : beacon<\/code> field as well as the <code>beforeunload<\/code> browser event!<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Form abandonment isn\u2019t always easy to define. Most often, it refers to when someone starts to fill in an HTML form, but leaves the page without submitting it. As a definition, this works nicely. However, with multi-page forms it naturally refers only to the last page of the form. Also, especially with government institutions, forms [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":142799,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[31827,10122,1531,14495,1791,1018],"dealstore":[],"offerexpiration":[],"class_list":["post-142798","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-abandonment","tag-form","tag-google","tag-manager","tag-tag","tag-track"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Track Form Abandonment With Google Tag Manager - 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=142798\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Track Form Abandonment With Google Tag Manager - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"Form abandonment isn\u2019t always easy to define. Most often, it refers to when someone starts to fill in an HTML form, but leaves the page without submitting it. As a definition, this works nicely. However, with multi-page forms it naturally refers only to the last page of the form. Also, especially with government institutions, forms [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fivemor.com\/?p=142798\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-19T02:18:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1740\" \/>\n\t<meta property=\"og:image:height\" content=\"524\" \/>\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=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fivemor.com\/?p=142798#article\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\"},\"headline\":\"Track Form Abandonment With Google Tag Manager\",\"datePublished\":\"2025-03-19T02:18:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798\"},\"wordCount\":2533,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg\",\"keywords\":[\"Abandonment\",\"Form\",\"Google\",\"Manager\",\"TAG\",\"Track\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fivemor.com\/?p=142798#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fivemor.com\/?p=142798\",\"url\":\"https:\/\/fivemor.com\/?p=142798\",\"name\":\"Track Form Abandonment With Google Tag Manager - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798#primaryimage\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg\",\"datePublished\":\"2025-03-19T02:18:55+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fivemor.com\/?p=142798#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fivemor.com\/?p=142798\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/?p=142798#primaryimage\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg\",\"width\":1740,\"height\":524},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fivemor.com\/?p=142798#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/fivemor.com\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Track Form Abandonment With Google Tag Manager\"}]},{\"@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":"Track Form Abandonment With Google Tag Manager - 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=142798","og_locale":"en_US","og_type":"article","og_title":"Track Form Abandonment With Google Tag Manager - Som2ny Network","og_description":"Form abandonment isn\u2019t always easy to define. Most often, it refers to when someone starts to fill in an HTML form, but leaves the page without submitting it. As a definition, this works nicely. However, with multi-page forms it naturally refers only to the last page of the form. Also, especially with government institutions, forms [&hellip;]","og_url":"https:\/\/fivemor.com\/?p=142798","og_site_name":"Som2ny Network","article_published_time":"2025-03-19T02:18:55+00:00","og_image":[{"width":1740,"height":524,"url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg","type":"image\/jpeg"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fivemor.com\/?p=142798#article","isPartOf":{"@id":"https:\/\/fivemor.com\/?p=142798"},"author":{"name":"admin","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371"},"headline":"Track Form Abandonment With Google Tag Manager","datePublished":"2025-03-19T02:18:55+00:00","mainEntityOfPage":{"@id":"https:\/\/fivemor.com\/?p=142798"},"wordCount":2533,"commentCount":0,"publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"image":{"@id":"https:\/\/fivemor.com\/?p=142798#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg","keywords":["Abandonment","Form","Google","Manager","TAG","Track"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fivemor.com\/?p=142798#respond"]}]},{"@type":"WebPage","@id":"https:\/\/fivemor.com\/?p=142798","url":"https:\/\/fivemor.com\/?p=142798","name":"Track Form Abandonment With Google Tag Manager - Som2ny Network","isPartOf":{"@id":"https:\/\/fivemor.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/fivemor.com\/?p=142798#primaryimage"},"image":{"@id":"https:\/\/fivemor.com\/?p=142798#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg","datePublished":"2025-03-19T02:18:55+00:00","breadcrumb":{"@id":"https:\/\/fivemor.com\/?p=142798#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fivemor.com\/?p=142798"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/?p=142798#primaryimage","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-abandonment.jpg","width":1740,"height":524},{"@type":"BreadcrumbList","@id":"https:\/\/fivemor.com\/?p=142798#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fivemor.com\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Track Form Abandonment With Google Tag Manager"}]},{"@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\/142798","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=142798"}],"version-history":[{"count":0,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/142798\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/media\/142799"}],"wp:attachment":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=142798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=142798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=142798"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=142798"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=142798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}