Tracking Form Completes With Google Tag Manager
24 Dec, 2021 Read Time: 12 Minutes
In the many years we have been setting up tracking for our clients, the standout and one of the most requested tasks has to be form submits or, as we like to call them, ‘completes’. This isn’t too surprising as the act of submitting a form represents a key conversion point for most organisations.
The concept of forms is fairly general, after all, everything from a user sign-up, sign-in, search submit, contact us or even a mailing list subscribe are still forms. The main difference is the complexity and steps required to complete.
To better understand the user's journey through a form, we generally recommend and provide an in-depth tracking plan, covering starts, steps, errors and field level interactions However, we always work backwards from the form complete to ensure the most important event is tracked.
This post will look at the various methods we have utilised for form complete tracking, calling out the benefits and limitations. Ideally, all forms should be tracked with dataLayer and roping in your developer team to help out - however, the reality is that this is not always possible and even when it is, the wait and effort might be too much. We would much rather get tracking up in the short term even if it's not perfect (accepting the limitations) in favour of waiting 6 months for the optimal solution.
Please note this post won’t go into full detail about each setup, rather a general guide. Most of the solutions will require you to have enabled the built-in variables in Google Tag Manager and knowledge of HTML/CSS/jS for implementation purposes.
Tracking Approaches
Thankyou/Complete Page URL
If you are lucky enough to have your form redirect to a complete / thank you page then you are already in business. The page URL should provide all the information you need and you can set up a Google Analytics destination goal.
If you would like an event or a trigger for other marketing tags, you should use the Page View trigger with the Page URL variable using RegEx (ignore case) as the match case. This allows for the broadest matching from the hostname, page path or query string.
Submit Button Click
This is one of the simplest methods to implement, however it is not a true form complete, rather the intention to complete the form. This is because validation issues and/or failures will overreport the true number of successful submissions.
The Submit Button Click is quick to set up, work for most forms and will not require code updates to the website.
The challenge with this setup is identifying the button that is clicked. You will need to use the Click - All Elements trigger.
These are the variables you may need to use:
- Click ID (use equals or regex)
- Click Classes (use contains or regex)
- Click Text (use contains or regex)
- Click Element (use matches CSS selector)
The click element will provide you the most flexibility, however it does require a good understanding of HTML and CSS to configure correctly. Most forms will have the submit button as an “input” field and you may have luck with the following CSS selectors. Otherwise using the other variables (i.e. Click ID or Click Text) will be easier if they are available.
input[type="submit"]
button[type="submit"]
Form Submission Trigger
In theory and name, this seems like the most logical choice, however many have been disappointed with this trigger - finding out that it simply did not work.
In order for this to work as intended, the event dispatched from the form submit must “bubble” up to the browsers document level for Google Tag Manager to receive it. The reality is most forms built these days will either prevent the event from firing or cancel it along the way. This is likely due to contemporary website development and the use of JavaScript libraries for form functionality e.g. validation etc.
The only way you will know is to set up the trigger and see if you get a result, if nothing happens (e.g. tags don’t fire or can’t see the gtm.formSubmit events in the dataLayer/preview mode ) it's very likely this option won’t work for any of your forms.
If you can get the trigger to work, you can match on the following:
- Form ID (use equals or regex)
- Form Classes (use contains or regex)
- Form URL (use contains or regex)
- Form Element (use matches CSS selector)
It must be cautioned here that unless you really know what you are doing, do not use the Wait for Tags or Check Validation options. While these may improve the accuracy of the tracking - I consider the risk of interrupting or interfering with the form functionality too great. You may find it works today, however sometime in the future when the website changes it may have unintended consequences.
Success Message Visibility
Back in 2017, Google Tag Manager released a new trigger type - the Element Visibility trigger. This enabled the targeting of HTML elements when they become visible within the user's browser. For example, let's say you had a call to action button buried in an article halfway down the page. You had already applied click tracking to the button. Your benchmark would be page views vs clicks. There is a chance that the user never saw the button despite the firing of a pageview event. Therefore this would likely be underreporting the effectiveness of the button.
Using the visibility trigger you could fire an event when the button becomes visible on the user's screen, you could then use the visible event vs button click to get a true picture of its performance.
For form tracking, this opened up a new possibility, track the form complete when a thank you message is displayed. This is a great improvement from the submit button method and fills the gap for forms that on submission don’t reload the page.
The best way to set up this trigger is to submit the form and inspect the displayed thankyou message You want to find a holder/wrapped e.g. the div/span/p tag that ideally has a class or better yet a unique id.
The trigger will let you match on either ID or CSS Selector, so again you are going to need to know a bit about HTML/CSS to configure this correctly.
For the other settings:
- When to fire: Every time an element appears on screen/Once per page
- Advanced>Minimum Percent Visible: <10 e.g. 5
- Advanced>Observe DOM Changes: Checked
- This trigger fires on: Some Visibility Events
For this trigger you will want to limit it to the actual form pages It is possible that this trigger can have page performance issues if not configured correctly.
jQuery Ajax Success
If your website is using jQuery and your forms use Ajax request functionality, then this custom JavaScript listener will potentially be able to pick up the network responses. The custom javascript is deployed via a Google Tag Manager in a Custom HTML Tag.
You can read up on the jQuery ajax success function here: https://api.jquery.com/ajaxSuccess/
This tag attempts to pick up ajax requests and convert the response into dataLayer pushes. You can use this to create a trigger for your form complete - should the response be successful.
By listening to the server's response and validating for a success flag, we can determine that the form was successfully completed. Once again these forms are not likely to reload the page and the ajax request will be the underlying service that then displays any thankyou messages/responses on-page.
It is important to note that Ajax requests are not limited to forms, they can be used for pulling in content, refining filters and many other websites services. Therefore you really should build in some URL limitations (use the “settings.url”) in the custom script. Otherwise, you might find your dataLayer being populated with many irrelevant pushes and lead to performance issues.
The Custom HTML Tag will need to be triggered on a DOM Ready Page view, targeted to the form pages.
Then you will need to set up a custom event trigger and dataLayer variables to use in your form complete trigger and tags.
Custom HTML Tag
DOM Ready Trigger for Custom HTML Tag
Custom Trigger for ajax dataLayer push (use this for your tracking tags)
Custom HTML Tag Code
<!-- CHTML - dataLayer - jQuery - Ajax - Success - Data Runs Deep - 2020 --> <script> (function($){ try { if( typeof $ != 'undefined') { $(document).ajaxSuccess(function(event, request, settings) { try { if(typeof settings.url !== 'undefined') { if(dataLayer !== 'undefined') { var targetUrl = settings.url; if(targetUrl) { var response = request.responseJSON; if(!response) { response = request.responseText; } var set = settings.data; if(set && typeof set === 'string' && set.indexOf('{"') >= 0) { set = $.parseJSON(set); } dataLayer.push({ 'event': 'custom.request.success', 'type' : 'ajax', 'request' : { 'url' : settings.url, 'data' : set, 'response' : response } }); } } } } catch (err) {if({{Debug Mode}}) console.log(err);} }); } } catch (err) {if({{Debug Mode}}) console.log(err);} })(jQuery); </script>
dataLayer via custom html and jQuery
Like the ajax success listener, if your website is using jQuery you can take advantage of the form submit function to attempt to pick up the users submission. This is more flexible than the inbuilt submission listener as it does not require the event to bubble up to the document level, instead you can target the form directly with jQuery.
You can read up on the jQuery submit function here: https://api.jquery.com/submit/
The Custom HTML Tag will use jQuery to target a specific form and trigger a dataLayer push on the forms submit event. Like the button click approach, this is the user's intent to submit, it may still overcount the true completes due to validation etc.
Once you have set up the Custom HTML tag you will need to create a custom event trigger and dataLayer variables to use in your form complete tags.
DOM Ready Trigger for Custom HTML Tag
Custom Trigger for jQuery submit dataLayer push (use this for your tracking tags)
Custom HTML Tag Code
<!-- CHTML - dataLayer - jQuery - Form - Submit - Data Runs Deep - 2020 --> <script> (function($){ try { if( typeof $ != 'undefined') { $("#myFormId").submit(function(event) { try { dataLayer.push({ "event" : "custom.form.submit", "category" : "form", "title" : formTitle, "label" : "submit", "data" : undefined }); } catch (err) {if({{Debug Mode}}) console.log(err);} }); } } catch (err) {if({{Debug Mode}}) console.log(err);} })(jQuery); </script>
dataLayer via website updates
Now we finally come to the ideal, ultimate and recommended approach for form tracking, the dataLayer push. This method will use the dataLayer to track the targeted forms.
If you are not familiar with the dataLayer then check out the “cooking up a dataLayer post”.
https://datarunsdeep.com.au/blog/cooking-datalayer-measurecamp-melbourne-2020
The dataLayer approach will take out the majority of complexity required in Google Tag Manager. Furthermore, it will provide a scalable and consistent approach to tracking forms across the website. The template below can be used for all forms, just ask your developers to swap out the “formTitle” as required. With this setup, you can make one trigger and one Google Analytics event tag to track all your forms!
It will require effort and buy-in from your development team - sometimes it's just not possible to get the resources for this, hence us detailing all the methods above. However if you can make this a priority no other method will compare, especially if you want to expand beyond just the form complete.
Once this has been added to your forms, you will need to set up a custom event trigger for the dataLayer event and configure your dataLayer variables for use in triggers and tags.
Custom Trigger for dataLayer push (use this for your tracking tags)
Google Analytics Event for dataLayer push
dataLayer JavaScript
/* Data Runs Deep - 2020 */
dataLayer.push({
"event" : "custom.form.complete",
"category" : "form",
"title" : formTitle,
"label" : "complete",
"data" : dataValue // undefined
});
Final thoughts
Like all types of tracking, there is never a one-size-fits-all. The challenge is working out what will be best for your team, how the website can facilitate the tracking and the resources you have available to meet the objectives of your organisation.
This post has provided a tool belt of methods to choose from and you will need to test to see what works. I strongly recommend trying other methods available should one fail. Have no doubt that the dataLayer is the best approach in the long term, however getting the tracking out sooner and therefore being able to act on the data is more important.
The methods above are not perfect and require a broad range of knowledge to implement correctly - I wish we could provide copy/paste solutions that work out of the box - however that's simply not how form tracking works, each website is unique and requires customisation.
All the examples have been added to a GTM Container and exported as a JSON import (click here), this can be imported into a test GTM container to allow you to get a feel for each of the configurations. They won’t work without modification however should provide a strong starting point to help you get those forms tracked!
So, there we have it. How to track from completes with Google Tag Manager. If you're new to GTM, or want to up your data analysis game, check out our Google Tag Manager training course.
This post first appeared on the Data Runs Deep blog. Data Runs Deep joined the Jellyfish global family in 2020 and the knowledge-sharing continues under the Jellyfish banner in Australia and around the world.











