{"id":140578,"date":"2025-03-17T23:30:56","date_gmt":"2025-03-17T23:30:56","guid":{"rendered":"https:\/\/peraltafinancing.com\/analytics\/track-form-engagement-with-google-tag-manager\/"},"modified":"2025-03-17T23:30:56","modified_gmt":"2025-03-17T23:30:56","slug":"track-form-engagement-with-google-tag-manager","status":"publish","type":"post","link":"https:\/\/fivemor.com\/?p=140578","title":{"rendered":"Track Form Engagement With Google Tag Manager"},"content":{"rendered":"<p> <br \/>\n<\/p>\n<div>\n<p>(Updated 13 August 2017)<\/p>\n<p>A little over a year ago, in April 2014, I wrote the post \u201c<a href=\"https:\/\/www.simoahava.com\/analytics\/form-tracking-google-tag-manager\/\">Advanced Form Tracking In Google Tag Manager<\/a>\u201d, and it\u2019s been at the top of my best seller list ever since. Turns out that many people are rightfully passionate about making the web forms on their websites as fluid and intuitive as possible, since a web form is often the only thing that stands between a prospect and their transformation into clienthood.<\/p>\n<p>I thought it was time to update the article to be <a href=\"https:\/\/support.google.com\/tagmanager\/?hl=en#topic=3441530\">Google Tag Manager V2<\/a> compliant. It\u2019s not a major difference, but I have remodelled some of the JavaScript as well. Furthermore, I\u2019ve pulled together some new ideas explored in other articles, so now it\u2019s all conveniently packaged in this one big blog post.<\/p>\n<p>At the heart of this article is still the methodology of picking up values from form fields. Perhaps you want to send some selection the user made to Google Analytics with the purpose of segmenting the data, or perhaps you want to identify values which most often block a conversion. Whatever the case, remember this: Google Analytics is very harsh towards <strong>PII<\/strong> (personally identifiable information) collection, and you need to be very vigilant in sanitizing any values you\u2019re collecting. You don\u2019t want to send <em>anything<\/em> to Google Analytics that can be used to identify the person who filled the form. The most typical value is an <strong>email address<\/strong>, which you should categorically avoid recording.<\/p>\n<p>Without further ado, let\u2019s get rolling. First, the basics\u2026<\/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=\"1-form-tracking-in-google-tag-manager\">1. Form tracking in Google Tag Manager<\/h2>\n<p>In the new version (V2) of Google Tag Manager, form tracking is no longer isolated as its own \u201cForm Listener\u201d Tag type. Instead, <a href=\"https:\/\/www.simoahava.com\/analytics\/auto-event-tracking-gtm-2-0\/\">auto-event tracking<\/a> has shifted to handlers embedded in the Triggers you use to fire Tags.<\/p>\n<p>When you create a <strong>Form<\/strong> Trigger, it will activate on all pages where the <strong>Enable this trigger when\u2026<\/strong> setting is valid. Remember, you only see this setting if either \u201cWait For Tags\u201d or \u201cCheck Validation\u201d is checked in the Trigger settings.<\/p>\n<div style=\"aspect-ratio: 1768 \/ 870;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/09\/form-event-trigger.jpg\" title=\"Form Event Trigger\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"870\" width=\"1768\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/09\/form-event-trigger.jpg#ZgotmplZ\" alt=\"Form Event Trigger\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>If the Trigger is active on a page, it will actively listen for a form submission. The settings in the Trigger are:<\/p>\n<ol>\n<li>\n<p><strong>Wait For Tags<\/strong> &#8211; GTM will <em>pause<\/em> the form submission for as long as all the Tags that use the Trigger have fired or until the timeout (default 2000 milliseconds) expires.<\/p>\n<\/li>\n<li>\n<p><strong>Check Validation<\/strong> &#8211; If this is checked, GTM will not fire the Trigger if the default action of the form (submit and redirect) is prevented. If left unchecked, the Trigger will go off whenever a <code>submit<\/code> event is registered, whether or not the default action is prevented.<\/p>\n<\/li>\n<li>\n<p><strong>Enable this trigger when\u2026<\/strong> &#8211; As mentioned above, this condition is for establishing <strong>on which pages<\/strong> GTM should listen for form submissions. There\u2019s really no performance penalty in having the listener active on all pages, but there are cases where <strong>Wait For Tags<\/strong> interferes with other JavaScript on the page, so you might want to only have the listener enabled on pages you\u2019ve tested it on.<\/p>\n<\/li>\n<li>\n<p><strong>Fire this trigger when\u2026<\/strong> &#8211; If you select \u201cSome Forms\u201d as the <em>This trigger fires on<\/em> setting, these conditions that govern when the Trigger makes any attached Tags go off. If you have just one form on the website, using \u201cAll Forms\u201d here is justified. But if you want to specify you only want to fire the Tag when a form with <code>id=\"contactForm\"<\/code> should fire the Tag, you should add that as a condition here.<\/p>\n<\/li>\n<\/ol>\n<div style=\"aspect-ratio: 1748 \/ 788;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/09\/fire-on.jpg\" title=\"enable and fire trigger\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"788\" width=\"1748\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/09\/fire-on.jpg#ZgotmplZ\" alt=\"enable and fire trigger\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>If you don\u2019t see Variables like \u201cForm ID\u201d or \u201cForm Classes\u201d in the Variables drop-down menu, you will need to activate them, as they are <a href=\"https:\/\/www.simoahava.com\/analytics\/variable-guide-google-tag-manager\/\">Built-In Variables<\/a>, introduced in Google Tag Manager V2.<\/p>\n<p>However, there might be many reasons why a properly created Form Trigger doesn\u2019t work. So, read on\u2026<\/p>\n<h2 id=\"2-why-the-form-trigger-doesnt-always-work\">2. Why the Form Trigger doesn\u2019t always work<\/h2>\n<p>For the Form Trigger to work, the form must dispatch a <strong>valid form submit event<\/strong> which also <strong>bubbles all the way to the document node<\/strong>. To de-gobbledegookify this statement, it means that:<\/p>\n<ol>\n<li>\n<p>The form must dispatch a valid <code>submit<\/code> browser event<\/p>\n<\/li>\n<li>\n<p>This event must not be prevented from propagating to the <code>document<\/code> node<\/p>\n<\/li>\n<\/ol>\n<p>Those are the conditions. They seem simple enough, but you might be surprised how many forms out there violate either one.<\/p>\n<p>The first means simply that GTM listens for a standard <code>submit<\/code> browser event, which is most often dispatched when an <code>input<\/code> or <code>button<\/code> element is clicked, where element type is <code>submit<\/code>.<\/p>\n<div style=\"aspect-ratio: 1176 \/ 154;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/08\/valid-input-submit.jpg\" title=\"Valid input submit\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"154\" width=\"1176\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/08\/valid-input-submit.jpg#ZgotmplZ\" alt=\"Valid input submit\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<p>The second means that the <code>submit<\/code> must be allowed to climb all the way up to the <code>document<\/code> node, where GTM\u2019s listener is waiting for the event. You see, GTM uses something called <em>event delegation<\/em> to listen for form submissions. This is much more economical than adding a listener to all the forms on the page individually.<\/p>\n<p>The first condition is most commonly violated when the <code>submit<\/code> event is either cancelled (see below) or never dispatched in the first place. Many forms send their data with custom-built requests (e.g. jQuery\u2019s <a href=\"http:\/\/api.jquery.com\/jquery.ajax\/\">$.ajax<\/a> or the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/XMLHttpRequest\">XMLHttpRequest API<\/a>), and these prevent the <code>submit<\/code> event from working, since it\u2019s replaced with a custom dispatcher. Since the <code>submit<\/code> event is never dispatched, <strong>Google Tag Manager never records a form submission<\/strong>.<\/p>\n<p>The second condition is violated when event propagation is stopped with <code>return false;<\/code> in a jQuery handler. Another common way to prevent propagation is to use <code>stopPropagation()<\/code> instead of <code>preventDefault()<\/code> on the event object.<\/p>\n<p>I\u2019ve written about this phenomenon a number of times before:<\/p>\n<p>The best way to fix the issue, however, is to open a line of communication with your developers, and tell them that GTM requires a standard <code>submit<\/code> browser event to propagate all the way to the <code>document<\/code> node to work.<\/p>\n<p>If this can\u2019t be done, the next best thing is to ask the developer to implement a custom <code>dataLayer.push()<\/code> into the callback function which is invoked upon a successful submission. The piece of code could be something like:<\/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> onFormSuccess(event) {\n  <span style=\"color:#0aa\">window<\/span>.dataLayer = <span style=\"color:#0aa\">window<\/span>.dataLayer || [];\n  <span style=\"color:#0aa\">window<\/span>.dataLayer.push({\n    event: <span style=\"color:#a50\">'formSubmissionSuccess'<\/span>,\n    formId: <span style=\"color:#a50\">'contactForm'<\/span>\n  });\n  <span style=\"color:#aaa;font-style:italic\">\/\/ Rest of the success callback code\n<\/span><span style=\"color:#aaa;font-style:italic\"\/>}\n<\/code><\/pre>\n<\/div>\n<p>This would push <code>formSubmissionSuccess<\/code> into the <code>dataLayer<\/code> as the value of the <code>event<\/code> key. Then, you can create a Custom Event Trigger, which waits for an event named <code>formSubmissionSuccess<\/code>. Using this Trigger would then fire a Tag when the form is successfully submitted.<\/p>\n<p>There are other workarounds which involve e.g. polling the page until a thank you message is identified, or perhaps using a custom-built <a href=\"https:\/\/www.simoahava.com\/analytics\/google-tag-manager-dom-listener\/\">DOM Listener<\/a>. Unfortunately, all workarounds are far less robust than either fixing the form to respect GTM\u2019s Form Trigger requirements or the custom <code>dataLayer.push()<\/code> method described above.<\/p>\n<h2 id=\"3-built-in-variables\">3. Built-In Variables<\/h2>\n<p>Google Tag Manager introduces a number of <a href=\"https:\/\/www.simoahava.com\/analytics\/variable-guide-google-tag-manager\/\">Built-In Variables<\/a> you can use to simplify form tracking. Make sure all the \u201cForm\u201d Variables are checked before continuing.<\/p>\n<div style=\"aspect-ratio: 688 \/ 1032;\" class=\"figure nocaption\">\n<p>    <a href=\"https:\/\/www.simoahava.com\/images\/2015\/09\/form-built-in-variables.jpg\" title=\"Form built-in variables\"><\/p>\n<p>    <img decoding=\"async\" class=\"fig-img\" height=\"1032\" width=\"688\" loading=\"lazy\" src=\"https:\/\/www.simoahava.com\/images\/2015\/09\/form-built-in-variables.jpg#ZgotmplZ\" alt=\"Form built-in variables\"\/><\/p>\n<p>    <\/a><\/p>\n<\/div>\n<ul>\n<li>\n<p><strong>Form Element<\/strong> &#8211; returns an HTML Object which contains the form element that was submitted. You can use this Variable to dig deep into the object properties of the form itself.<\/p>\n<\/li>\n<li>\n<p><strong>Form Classes<\/strong> &#8211; returns a string of values in the <code>class<\/code> attribute of the form that was submitted.<\/p>\n<\/li>\n<li>\n<p><strong>Form ID<\/strong> &#8211; returns a string with the value stored in the <code>id<\/code> attribute of the form that was submitted.<\/p>\n<\/li>\n<li>\n<p><strong>Form Target<\/strong> &#8211; returns a string with the value stored in the <code>target<\/code> attribute of the form that was submitted.<\/p>\n<\/li>\n<li>\n<p><strong>Form URL<\/strong> &#8211; returns a string with the value stored in the <code>action<\/code> attribute of the form that was submitted.<\/p>\n<\/li>\n<li>\n<p><strong>Form Text<\/strong> &#8211; returns the entire <em>text<\/em> content of the form that was submitted (NOT very useful).<\/p>\n<\/li>\n<\/ul>\n<p>Many of the following solutions rely on these Built-In Variables.<\/p>\n<h2 id=\"4-note-about-scope\">4. Note about scope<\/h2>\n<p>All the Variables described below are <strong>Custom JavaScript Variables<\/strong>. They are all scoped, by default, to the form that was submitted with <code>{{Form Element}}.querySelector...<\/code>. If you want to access <em>any<\/em> form on the page, submitted or not, you need to use the following syntax:<\/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> form = <span style=\"color:#0aa\">document<\/span>.querySelector(<span style=\"color:#a50\">'#someform'<\/span>);\n<span style=\"color:#00a\">var<\/span> field = form.querySelector...\n<\/code><\/pre>\n<\/div>\n<p>Keep this in mind when applying the following solutions to your own measurement plan.<\/p>\n<h2 id=\"5-capture-field-value\">5. Capture field value<\/h2>\n<p>This is a simple Custom JavaScript Variable which captures the value user has input into a form field. Do note that items like checkboxes, radio buttons, and drop-down lists work a little differently, which is why they are covered in their own chapters.<\/p>\n<p><strong>Name<\/strong>: {{Field value}}<\/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\">var<\/span> field = {{Form Element}}.querySelector(<span style=\"color:#a50\">'#inputFieldId'<\/span>);\n  <span style=\"color:#00a\">return<\/span> field ? field.value : <span style=\"color:#00a\">undefined<\/span>;\n}\n<\/code><\/pre>\n<\/div>\n<p><strong>Description<\/strong>: This solution accesses the <code>value<\/code> attribute of the form field with ID <em>inputFieldId<\/em>, as long as its found within the form that was submitted. If no such field is found, then <em>undefined<\/em> is returned instead. Remember, do <strong>not<\/strong> collect personally identifiable information!<\/p>\n<h2 id=\"6-capture-selected-radio-button-value\">6. Capture selected radio button value<\/h2>\n<p>This solution is for capturing the value of the checked radio button. The default solution is for capturing just one radio button value, i.e. accessing just one group. See chapter 9 for an example of how to access multiple values from similar elements.<\/p>\n<p><strong>Name<\/strong>: {{Checked radio button}}<\/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\">var<\/span> radioName = <span style=\"color:#a50\">\"radioName\"<\/span>;\n  <span style=\"color:#00a\">var<\/span> checked = {{Form Element}}.querySelector(<span style=\"color:#a50\">'[name=\"'<\/span> + radioName + <span style=\"color:#a50\">'\"]:checked'<\/span>);\n  <span style=\"color:#00a\">return<\/span> checked ? checked.value : <span style=\"color:#00a\">undefined<\/span>;\n}\n<\/code><\/pre>\n<\/div>\n<p><strong>Description<\/strong>: Returns the value of the checked radio button in the group with the name <em>radioName<\/em>. This group must exist within the form that was submitted. If no checked button is found, <em>undefined<\/em> is returned.<\/p>\n<h2 id=\"7-capture-selected-checkbox-value\">7. Capture selected checkbox value<\/h2>\n<p>Returning the value of the selected checkbox within a group is done exactly the same way as how you\u2019d capture a radio button value. Both use the <code>checked<\/code> property to identify if an element is checked.<\/p>\n<p>So use the solution from the previous chapter to capture checkbox values as well. Just remember that it only returns the value of the <strong>first<\/strong> checkbox in a group that was selected. If the user can check multiple checkboxes (as is usually the case), you might want to check chapter 9 for tips on how to do this.<\/p>\n<h2 id=\"8-capture-selected-drop-down-list-item-value\">8. Capture selected drop-down list item value<\/h2>\n<p>To capture the selected item value in a drop-down list, checking for the <code>value<\/code> of the list itself will not work, as you\u2019d intuitively expect. Instead, you need to access the option in the list that was selected, and then capture its value.<\/p>\n<p><strong>Name<\/strong>: {{Selected list item}}<\/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\">var<\/span> selectList = {{Form Element}}.querySelector(<span style=\"color:#a50\">'#selectListId'<\/span>);\n  <span style=\"color:#00a\">return<\/span> selectList ? selectList.options[selectList.selectedIndex].value : <span style=\"color:#00a\">undefined<\/span>;\n}\n<\/code><\/pre>\n<\/div>\n<p><strong>Description<\/strong>: First, the script retrieves the drop-down list with ID <em>selectListId<\/em>. Next, it returns the value of the selected option in the list. If the list does not exist, the script returns <em>undefined<\/em>.<\/p>\n<h2 id=\"9-capture-multiple-values\">9. Capture multiple values<\/h2>\n<p>Sometimes you\u2019ll want to capture multiple values of some specified group. A prime example is the checkbox, where you can have multiple checked boxes in a single group. Here are some ideas for how to capture these values.<\/p>\n<p><strong>Return concatenated string of checked item values<\/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>() {\n  <span style=\"color:#00a\">var<\/span> groupName = <span style=\"color:#a50\">\"groupName\"<\/span>;\n  <span style=\"color:#00a\">var<\/span> elems = {{Form Element}}.querySelectorAll(<span style=\"color:#a50\">'[name=\"'<\/span> + groupName + <span style=\"color:#a50\">'\"]:checked'<\/span>);\n  <span style=\"color:#00a\">var<\/span> vals = [];\n  <span style=\"color:#00a\">var<\/span> i, len;\n  <span style=\"color:#00a\">for<\/span> (i = <span style=\"color:#099\">0<\/span>, len = elems.length; i return vals.length ? vals.join(<span style=\"color:#a50\">' '<\/span>) : <span style=\"color:#00a\">undefined<\/span>;\n} \n<\/code><\/pre>\n<\/div>\n<p><strong>Description<\/strong>: This returns a concatenated string of all the checked item values within the group with name <em>groupName<\/em>. An example would be e.g. \u201cbreakfast lunch\u201d, where the user chooses which meals they always eat out of \u201cbreakfast\u201d, \u201clunch\u201d, and \u201cdinner\u201d.<\/p>\n<p>To return just the plain Array, so that you can process it further in the Tag which calls this Variable, change the <code>return<\/code> statement to:<\/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\">return<\/span> vals.length ? vals : <span style=\"color:#00a\">undefined<\/span>;\n<\/code><\/pre>\n<\/div>\n<p>If you want to get the values in a multiple selection list, use the following script. It returns the results in a concatenated string again, but by following the tip in the previous paragraph you can return an Array instead.<\/p>\n<p><strong>Return selected values in a multiple selection list<\/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>() {\n  <span style=\"color:#00a\">var<\/span> selectList = {{Form Element}}.querySelector(<span style=\"color:#a50\">'#selectListId'<\/span>);\n  <span style=\"color:#00a\">var<\/span> options = selectList ? selectList.options : [];\n  <span style=\"color:#00a\">var<\/span> vals = [];\n  <span style=\"color:#00a\">var<\/span> i, len;\n  <span style=\"color:#00a\">for<\/span> (i = <span style=\"color:#099\">0<\/span>, len = options.length; i if (options[i].selected) {\n      vals.push(options[i].value);\n    }\n  }\n  <span style=\"color:#00a\">return<\/span> vals.length ? vals.join(<span style=\"color:#a50\">' '<\/span>) : <span style=\"color:#00a\">undefined<\/span>;\n}\n<\/code><\/pre>\n<\/div>\n<p><strong>Description<\/strong>: This returns a concatenated string of all the selected options in a multiple selection drop-down list, which has the ID <em>selectListId<\/em> and which is within the submitted form.<\/p>\n<h2 id=\"10-track-form-abandonment\">10. Track form abandonment<\/h2>\n<p>For ideas on how to track form abandonment, check out this article I wrote a short while ago:<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/track-form-abandonment-with-google-tag-manager\/\">Track Form Abandonment With Google Tag Manager<\/a><\/p>\n<p>Bounteous also has a <a href=\"https:\/\/www.bounteous.com\/insights\/2014\/11\/10\/form-tracking-google-tag-manager\/\">sweet guide<\/a> on how to achieve the same thing, albeit with a somewhat different approach.<\/p>\n<p>My colleague at <a href=\"https:\/\/www.reaktor.com\">Reaktor<\/a>, Lauri Piispanen, has also improved upon this solution, and you can check out his GitHub repo <a href=\"https:\/\/github.com\/lauripiispanen\/auto-gtm-form-abandonment\">here<\/a>.<\/p>\n<h2 id=\"11-track-form-field-timings\">11. Track form field timings<\/h2>\n<p>If you want to track how much time a user spends on your form, segmented by individual fields, check out the following article:<\/p>\n<p><a href=\"https:\/\/www.simoahava.com\/analytics\/form-field-timing-with-google-tag-manager\/\">Form Field Timing With Google Tag Manager<\/a><\/p>\n<p>It utilizes User Timings in Google Analytics to collect data on how much time users spend in the fields of your form by average.<\/p>\n<h2 id=\"12-one-form-element---multiple-forms-aspnet\">12. One form element &#8211; multiple forms (ASP.NET)<\/h2>\n<p>I decided not to dwell on this topic too much, since it\u2019s so hacky and unreliable. The issue is that on e.g. ASP.NET sites, a single master form control wraps the entire page, and individual forms are just groups of elements under this one control.<\/p>\n<p>The method I suggested in the <a href=\"https:\/\/www.simoahava.com\/analytics\/form-tracking-google-tag-manager\/\">previous guide<\/a> is still somewhat valid, however. The way it works is that:<\/p>\n<ol>\n<li>\n<p>Fire a Custom HTML Tag when the submit button of the form is clicked<\/p>\n<\/li>\n<li>\n<p>In this Custom HTML Tag, push the ID (or other relevant data) of the clicked element into the data layer<\/p>\n<\/li>\n<li>\n<p>Create a Form Submit Trigger which looks for this value in the data layer<\/p>\n<\/li>\n<\/ol>\n<p>This way the Form Submit Trigger should only fire when the form is submitted due to a click on the correct submit button.<\/p>\n<p>I\u2019ve noticed this doesn\u2019t always work due to race conditions or just the general fragility of the event chain. Nevertheless, it\u2019s something you might want to try if you can\u2019t get developers to assist you.<\/p>\n<p>If you <strong>do<\/strong> have an established line of communications with your developers, the solution is to ask them to create \/ edit the success callback of each form to push a custom <code>dataLayer<\/code> object when a form is submitted. This object should contain information about which form was submitted, and you can then create a Custom Event Trigger based on this information. Go back to chapter 2 for an example of such a push.<\/p>\n<h2 id=\"13-summary\">13. Summary<\/h2>\n<p>This guide is a bit leaner than the first edition (at least it feels like so). That\u2019s because the new Form Submit Trigger has made many things easier, and I\u2019ve also rewritten the JavaScript to utilise methods like <code>querySelector<\/code> and properties like <code>selectedIndex<\/code> to get the desired result with far less hassle.<\/p>\n<p>Once IE8 and older disappear entirely from the face of this earth (can\u2019t wait!), we can use even simpler language, with e.g. CSS3 pseudo-classes like <code>:checked<\/code>.<\/p>\n<p>Do you think something relevant is missing from this guide? Let me know. I\u2019m always happy to update this with new solutions. Don\u2019t forget to read the <a href=\"https:\/\/www.simoahava.com\/analytics\/form-tracking-google-tag-manager\/\">previous version<\/a> of the guide as well, and check the <strong>comments<\/strong> section, too! Lots of great questions and answers there.<\/p>\n<\/p><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>(Updated 13 August 2017) A little over a year ago, in April 2014, I wrote the post \u201cAdvanced Form Tracking In Google Tag Manager\u201d, and it\u2019s been at the top of my best seller list ever since. Turns out that many people are rightfully passionate about making the web forms on their websites as fluid [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":140579,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12033],"tags":[1748,10122,1531,14495,1791,1018],"dealstore":[],"offerexpiration":[],"class_list":["post-140578","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-analytics","tag-engagement","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 Engagement 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=140578\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Track Form Engagement With Google Tag Manager - Som2ny Network\" \/>\n<meta property=\"og:description\" content=\"(Updated 13 August 2017) A little over a year ago, in April 2014, I wrote the post \u201cAdvanced Form Tracking In Google Tag Manager\u201d, and it\u2019s been at the top of my best seller list ever since. Turns out that many people are rightfully passionate about making the web forms on their websites as fluid [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fivemor.com\/?p=140578\" \/>\n<meta property=\"og:site_name\" content=\"Som2ny Network\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-17T23:30:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1768\" \/>\n\t<meta property=\"og:image:height\" content=\"870\" \/>\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=140578#article\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371\"},\"headline\":\"Track Form Engagement With Google Tag Manager\",\"datePublished\":\"2025-03-17T23:30:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578\"},\"wordCount\":2387,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fivemor.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg\",\"keywords\":[\"Engagement\",\"Form\",\"Google\",\"Manager\",\"TAG\",\"Track\"],\"articleSection\":[\"Analytics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fivemor.com\/?p=140578#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fivemor.com\/?p=140578\",\"url\":\"https:\/\/fivemor.com\/?p=140578\",\"name\":\"Track Form Engagement With Google Tag Manager - Som2ny Network\",\"isPartOf\":{\"@id\":\"https:\/\/fivemor.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578#primaryimage\"},\"image\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578#primaryimage\"},\"thumbnailUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg\",\"datePublished\":\"2025-03-17T23:30:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fivemor.com\/?p=140578#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fivemor.com\/?p=140578\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/fivemor.com\/?p=140578#primaryimage\",\"url\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg\",\"contentUrl\":\"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg\",\"width\":1768,\"height\":870},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fivemor.com\/?p=140578#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/fivemor.com\/?bp_activities=1\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Track Form Engagement 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 Engagement 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=140578","og_locale":"en_US","og_type":"article","og_title":"Track Form Engagement With Google Tag Manager - Som2ny Network","og_description":"(Updated 13 August 2017) A little over a year ago, in April 2014, I wrote the post \u201cAdvanced Form Tracking In Google Tag Manager\u201d, and it\u2019s been at the top of my best seller list ever since. Turns out that many people are rightfully passionate about making the web forms on their websites as fluid [&hellip;]","og_url":"https:\/\/fivemor.com\/?p=140578","og_site_name":"Som2ny Network","article_published_time":"2025-03-17T23:30:56+00:00","og_image":[{"width":1768,"height":870,"url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.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=140578#article","isPartOf":{"@id":"https:\/\/fivemor.com\/?p=140578"},"author":{"name":"admin","@id":"https:\/\/fivemor.com\/#\/schema\/person\/b85e3c3dc0e1daea076524dc8810c371"},"headline":"Track Form Engagement With Google Tag Manager","datePublished":"2025-03-17T23:30:56+00:00","mainEntityOfPage":{"@id":"https:\/\/fivemor.com\/?p=140578"},"wordCount":2387,"commentCount":0,"publisher":{"@id":"https:\/\/fivemor.com\/#organization"},"image":{"@id":"https:\/\/fivemor.com\/?p=140578#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg","keywords":["Engagement","Form","Google","Manager","TAG","Track"],"articleSection":["Analytics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fivemor.com\/?p=140578#respond"]}]},{"@type":"WebPage","@id":"https:\/\/fivemor.com\/?p=140578","url":"https:\/\/fivemor.com\/?p=140578","name":"Track Form Engagement With Google Tag Manager - Som2ny Network","isPartOf":{"@id":"https:\/\/fivemor.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/fivemor.com\/?p=140578#primaryimage"},"image":{"@id":"https:\/\/fivemor.com\/?p=140578#primaryimage"},"thumbnailUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg","datePublished":"2025-03-17T23:30:56+00:00","breadcrumb":{"@id":"https:\/\/fivemor.com\/?p=140578#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fivemor.com\/?p=140578"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/fivemor.com\/?p=140578#primaryimage","url":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg","contentUrl":"https:\/\/fivemor.com\/wp-content\/uploads\/2025\/03\/form-event-trigger.jpg","width":1768,"height":870},{"@type":"BreadcrumbList","@id":"https:\/\/fivemor.com\/?p=140578#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fivemor.com\/?bp_activities=1"},{"@type":"ListItem","position":2,"name":"Track Form Engagement 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\/140578","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=140578"}],"version-history":[{"count":0,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/posts\/140578\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=\/wp\/v2\/media\/140579"}],"wp:attachment":[{"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=140578"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=140578"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=140578"},{"taxonomy":"dealstore","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdealstore&post=140578"},{"taxonomy":"offerexpiration","embeddable":true,"href":"https:\/\/fivemor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fofferexpiration&post=140578"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}