A common requirement in measurement plans set by Marketing or Product teams is the ability to track form abandonment. With many of the teams mentioned above stressing over bringing in more and more leads, the ability to analyze and address where and why users drop off is important.
While there some tools that can measure a form’s conversion rate (e.g. Hubspot’s built feature) and even analyze specific fields (e.g. Hotjar Form Analysis tool), measuring this in Google Analytics can come in handy for in-depth analysis.
The output of measurement described below is this table of events in Google Analytics that can be used to analyze the drop-off points of users.
Another classic use case of this data is creating Remarketing audience from these users that had expressed a clear interest in your product or service and only need that extra nudge. These can also serve as a great seed for and Lookalike audiences too.
Since this triggers a generic event, it can be used to create these audiences in any ad platform aside from Google Analytics/Ads, for example on Facebook Ads or Taboola.
Form abandonment tracking with Google Tag Manager
The simplest way I usually go about this is with Google Tag Manager (GTM). If you’re using GTM4WP, this is already baked in as an event (will appear in the Data Layer as gtm4wp.formElementEnter & gtm4wp.formElementLeave).
The method described below is based off of the Generic Event Tracking mechanism I’ve previously posted about. Using this generic tracking, adding additional event such as the form abandonment is a breeze.
Adding the Custom HTML tag
The first step to handling form abandonment is being able to identify to which point has a user gotten within a specific form. To achieve this we will use a simple jQuery script.
Important:
This assumes you already have jQuery active on your site (WordPress sites ship with it by default). If you don’t use jQuery, see the Vanilla JS solution below.
The purpose of this script is to capture a change in the value of a form field, and send the label of that field to GTM.
We will add this script as a Custom HTML tag in GTM. You can set the tag to trigger on any page or only on the pages where there are forms (e.g. only the Contact Us page).
<script>
jQuery("form input, form select, form textarea").change(function() {
dataLayer.push({
'event': 'form interaction',
'form_field': jQuery(this).attr('placeholder')
})
});
</script>
The output of this script will be an event sent to Google Analytics (using the Generic Event tag in GTM). The event’s name is ‘form interaction’ and the event’s parameter ‘form_field’ will record the field interacted with.
In the example above, the field will be identified by its placeholder text. You can extract the field’s label attribute by replacing the placeholder value with label.
jQuery(this).attr('label')
Elementor forms
In Elementor forms, this value is also referenced as name or id. You can also grab the field’s label or the form’s name with a minor alteration:
'form_field_label': jQuery(this).parents('div').children('label').text(),
'form_field_id': jQuery(this).parents('form').attr('name')
You can also check out my guide on Bulletproof Elementor form tracking with GTM.
Contact Form 7 forms
In CF7 forms, this value is also referenced as id. You can also grab the field’s label or the form’s ID with a minor alteration:
'form_field_label': jQuery(this).parents('label').text(),
'form_field_id': jQuery(this).parents('.wpcf7').attr('id')
You can also check out my guide on Bulletproof Contact Form 7 tracking with GTM.
Gravity forms
In Gravity forms, this value is also referenced as name or id. You can also grab the field’s label with a minor alteration:
'form_field_label': jQuery(this).parents('li').children('label').text(),
'form_field_id': jQuery(this).parents('.gform_wrapper').attr('id')
Hubspot forms
In Hubspot forms, this value is also referenced as name. You can also grab the field’s label with a minor alteration:
jQuery(this).parents('div').eq(1).children('label').text()
You can also check out my guide on Hubspot form tracking with (and w/o) Google Tag Manager.
Form abandonment tracking w/o Google Tag Manager
For those of you who don’t use GTM (shame on you!), there’s also a solution available. It utilizes the same jQuery and logic (see above for specific platforms) but triggers the event directly to Google Analytics via the gtag method.
Add this snippet to any page that has a form you want to track.
<script>
jQuery("form input, form select, form textarea").change(function() {
gtag('event', 'form interaction', {
'form_field': jQuery(this).attr('placeholder')
});
});
</script>
You can also create a similar tracker for Facebook pixel events by altering the script (both GA and FB events can sit under a single script):
<script>
jQuery("form input, form select, form textarea").change(function() {
fbq('track', 'ViewContent', {
content_name: jQuery(this).attr('placeholder')
});
});
</script>
Vanilla JavaScript (w/o jQuery)
in case your site doesn’t use jQuery, you can still use a simpler version of this solution. Since JS lacks some of the methods that are trivial in jQuery (without complex setup), we can only grab the immediate value of the field’s name/label.
If you’re using Google Tag Manager, simply use this snippet. You can change the value of form to capture a specific form by class or id (e.g. .class or #id). You can also change the value of the attribute you’re
<script>
document.querySelector('form').addEventListener('change', function(e) {
dataLayer.push({
'event': 'form interaction',
'form_field': e['target'].getAttribute('name')
});
});
</script>
If you’re not using Google Tag Manager, you can use this snippet to trigger the event into Google Analytics.
<script>
document.querySelector('form').addEventListener('change', function(e) {
gtag('event', 'form interaction', {
'form_field': e['target'].getAttribute('name')
});
});
</script>
Testing your selectors
If you want to test that you have the correct selectors, you can use this script. Simply paste it in your browser’s Console (click F-12 and navigate to the Console tab) and then interacting with any form on that page (the function resets on page navigation).
jQuery
jQuery("form input, form select, form textarea").change(function() {
alert('The field value is '+jQuery(this).attr('placeholder'))
});
Vanilla JavaScript
document.querySelector('form').addEventListener('change', function(e) {
alert('The field value is ' + e['target'].getAttribute('name'))
});
Caveats
While this approach is pretty simple, it does bring some challenges.
- This method doesn’t take into account the form’s ID. If you have one for per page, that’s no big deal (as GA events are tied to the page the user triggered them on). If you have multiple forms, e.g. a contact us form and newsletter footer , these can be difficult to analyze separately.
In that case my suggestion is simply to add the form’s ID to the Event Label field (requires additional code, see above). - Fields can be tracked multiple times – if a user edits a field multiple times, this will be recorded (not necessarily a bad thing)
- Browser autocomplete will trigger the fields impacted (again, not a bad thing)
5 Responses
Hello Elad,
You are really an Expert in your domain of analytics.
I was looking for something like this to track the analytics for form abandonment tracking.
Thanks a lot!!!
Hello Elad,
thanks for information
but, how to track this thing with GA4?
Hey Shona
This will work just the same, simply use the GA4 Event tag and use Event parameters to pass the values
Hello Elad,
Thank you for your post on this subject. I am trying to get this to work for a WordPress site using Contact Form 7.
I”ve implemented the code you provided into GTM.
When I debug in GM, I can see the event, eventCategory and the eventLabel. Unfortunately the eventAction is blank. This is what I see:
eventAction: ”,
The following code you supplied seems like it should work:
‘eventAction’: jQuery(this).parents(‘label’).text(),
When I look at the page source code this is the structure:
YOUR NAME
Any ideas?
It depends if this is the field’s label or id.
You can try instead this variation (for capturing the id instead of the label):
‘eventAction’: jQuery(this).parents(‘.wpcf7’).attr(‘id’)
let me know if this helps