
February 6, 2022
Enrich Form Submission Data with Google Tag Manager
Let’s say that you have a landing page with a signup form. All submissions are stored in the Customer Relationship Management system (CRM). This campaign has been running for a week, and you want to know who filled in the form and what information did they enter. But what about some additional data, e.g. where did this submission come from (what is the traffic source)?
You might say that the CRM you’re using has these additional tracking features. That’s nice, congratulations. But, from my experience, usually, businesses are using some basic form modules/plugins which have only one purpose – capture and store form submissions.
So you try to dig deeper, open Google Analytics, and check conversion reports. Even though you can see how many form submissions happened, you still cannot distinguish the traffic source of individual form submissions.
But that’s not an issue because in today’s blog post, I’ll show you how to enrich form submission data with additional data (not only traffic source). And we’ll do that by….. drumroll please ….. hiding some form fields and prefilling them with Google Tag Manager.
Why is it useful?
The answer’s pretty simple, you get more insights on the individual level because each form submission will have additional fields. As a result, you will be able to export them (I hope that your form module/plugin allows that) to Excel (or Google Sheets, or whatever) and slice the data from different angles.

So what’s the plan?
- First of all, you’ll need to create and then somehow hide several form fields. I prefer doing that in the form module itself. Why not GTM + Custom JavaScript? Because Google Tag Manager CAN be blocked by aggressive adblockers or other similar extensions. Imagine what would happen if a visitor comes to your landing page (with GTM blocked) and sees some strange form fields. The chances of successful submission are becoming much lower.
- Then we’ll train Google Tag Manager to fetch some data and enter it in those hidden form fields.
Keep in mind that your form builder/plugin/module must have the functionality to hide individual form fields. If you’re not sure if it’s possible, do a Google Search: [your form builder name] hidden fields.
In this blog post, I’ll be demonstrating a plugin called Formidable which enables me to hide certain form fields (here’s the solution).
If unfortunately, your form builder cannot hide fields, maybe you could ask a developer to do that. Just keep in mind that all hidden form fields must not be required. We do not want to block the form submission if, for some reason, those fields will not be prefilled.
Requirements for this technique to work
- Your form builder must have a feature to hide individual form fields (or you must have access to the developer who can hide them).
- Each hidden form field must contain an ID (it’s an HTML attribute).
- The form must not be in the iFrame. Do a right-click somewhere on the form. Do you see an option Reload frame? If yes, I’ve got some bad news. This blog post will not be useful for you.
Step #1. Create additional form fields
Here’s the case: you’re running an ad campaign that attracts traffic to a particular landing page containing a form. All links which refer to this landing page are tagged with UTM parameters, utm_medium, utm_source, utm_campaign.
It would be awesome to also catch those UTMs and pass with each form submission. How can you do this? Let’s find out.
In your form module, create additional 3 fields (for each UTM parameter). An example could look like this:
Remember, those three new fields must remain optional. Well, that was easy! Let’s proceed to step #2.
STEP #2. Prepare Variables
Now we need to teach Google Tag Manager to read the page URL and extract 3 variables: utm_medium, utm_source, utm_campaign.
Since those 3 parameters are visible in the URL, we can utilize a built-in GTM variable called URL variable. Go to your Google Tag Manager account > Choose the container > Variables > Hit New (under the user-defined variables) and create three variables with the following settings:
What did just happen now? We taught the GTM to read the URL of the current page, and if it contains utm_campaign, utm_medium or utm_source, they are turned into variables.
We’ll need those variables a bit later.
STEP #3. Prefill Those Form Fields
For this magic trick, I’ll be using a tiny JavaScript code snippet:
<script> (function() { var el = document.getElementById('some_id'); if (el) { el.value = 'some_value'; } })(); </script>
It scans the page and looks for the element with a particular ID (some_id), and once it’s found, the script changes its value to something that we define.
Let’s go back to the form and check those three newly created form fields. Right-click on the first field and hit Inspect.
Start looking for the “id” attribute. In my case, the id is field_ftdix.
I will add it to the aforementioned script.
<script> (function() { var el = document.getElementById('field_ftdix'); if (el) { el.value = 'some_value'; } })(); </script>
In our example, we’ll be working with three fields. Therefore, one of the possible solutions could be to update the code in order keep looking for 3 fields.
Pardon my limited JavaScript skills. This is probably not the most elegant code, but, on the other hand, it still does the job.
We should still remain in the same function but update it with two new variables and IF statements (for each additional field).
<script> (function() { var el = document.getElementById('field_ftdix'); if (el) { el.value = 'some_value'; } //we'll add some space here to add a variable and an IF statement })(); </script>
For the 2nd form field, we’ll use the variable el2 and add a condition that checks whether the field exists at all.
<script> (function() { var el = document.getElementById('field_ftdix'); if (el) { el.value = 'some_value'; } var el2 = document.getElementById('field_m6qwu'); if (el2) { el2.value = 'some_value'; } })(); </script>
And let’s do the same for the 3rd form field.
<script> (function() { var el = document.getElementById('field_ftdix'); if (el) { el.value = 'some_value'; } var el2 = document.getElementById('field_m6qwu'); if (el2) { el2.value = 'some_value'; } var el3 = document.getElementById('field_o8dcj'); if (el3) { el3.value = 'some_value'; } })(); </script>
To sum up what we’ve done so far: I had three form fields (of which IDs are field_ftdix, field_m6qwu, field_o8dcj). The script that we’ve created above will look for each of those form fields. If, say, the first form field exists, its value will be changed to some_value.
Now, onto the final step.
Remember those 3 URL variables which were created in Step #2? Let’s insert them into the script. Instead of some_value you should enter the names of all three URL variables (surrounded by double curly brackets {{}} ).
<script> (function() { var el = document.getElementById('field_ftdix'); if (el) { el.value = '{{URL - utm_medium}}'; } var el2 = document.getElementById('field_m6qwu'); if (el2) { el2.value = '{{URL - utm_source}}'; } var el3 = document.getElementById('field_o8dcj'); if (el3) { el3.value = '{{URL - utm_campaign}}'; } })(); </script>
STEP #4. Create a Custom HTML tag
Now that the script is ready, we need to implement it via Google Tag Manager. Go to Tags > Create > Custom HTML and paste that code. Also, assign a trigger with the following settings:
- Type: DOM Ready
- Rule: Page Path contains some-landing-page. The value of this rule should be changed according to the actual address of the landing page.
STEP #5. Test
Enable preview and debug mode in GTM, then go to the landing page and refresh the page. A large panel should appear at the bottom of the screen where you can see which tags fired, which didn’t, etc.
First of all, check whether the Custom HTML tag fires only on the particular landing page and not anywhere else. Next, go to the page with that form and see whether all three UTM-related fields are filled in. But before that, you need to fake UTM parameters by adding them to the address bar manually.
At the end of the page address, mywebsite.com/some-landing-page add a question mark and three UTM parameters connected with an ampersand (&). The final address to test could look like this mywebsite.com/some-landing-page?utm_medium=email&utm_source=newsletter&utm_campaign=february_newsletter.
Once the page (with those 3 UTM parameters in the address) is reloaded, form fields should be prefilled. Are some of those fields prefilled with undefined? There might be several reasons:
- You made a typo while faking parameters in the URL.
- You made a typo while inserting URL Variables in the form-prefilling script.
Let’s move on.
STEP #6. Hide those fields
For this step, there is no single effective solution because there is a ton of different forms and landing pages so you need you’ll need to do research on your own. In this blog post, I’m using a Formidable Forms plugin, and they enable me to hide form fields by adding a CSS class frm_hidden to all three fields.
In your case, the solution might be different: maybe there is a checkbox that does it, or maybe you will have to contact a developer if the form is custom-made. The list of possibilities could go on and on, but first, try to google.
Here’s an example of one field’s settings, but I also did the same thing with the other two.
Save the changes and proceed to the final step.
STEP #7. Final Check
Let’s test everything on a full scale:
- Add fake UTM parameters to the web address of the landing page with the form and hit enter (the page must be loaded with all 3 UTM parameters).
- After the form is loaded, those 3 new form fields should be invisible.
- Also, the Custom HTML tag (which prefills form fields) should be fired (you can check that in GTM Preview and Debug panel).
- Fill in all fields, and submit the form.
- Somewhere in your CRM, CMS, or whatever, check the data of the submission. It should contain 3 UTM parameters fetched from the address bar.
That’s it! Now, you’re officially taken your lead generation tracking to the next level. This should give you more insights from which traffic source each individual submission has been acquired.
Ideas for the future
But don’t limit yourself just to UTM parameters. There might be plenty of other data that you could prefill in the form. Here are several ideas:
- What if a visitor lands on page X and then goes to page Y, which contains the form? UTM parameters will be lost in the transition from the first page to the second. Well, you could parse UTM variables on the first page (just like I explained in this blog post) and then save them in 3 cookies. Here’s a guide how to set cookies with Google Tag Manager. When the visitor with those cookies visits the page with a form, GTM can read cookies (with the help of 1st party cookie variable) and insert their values in the form-prefilling script.
- Ask a developer to push some data about the visitor/user to the Data Layer, read that data with the help of the Data Layer Variable, store it in the cookie, and the use that data form-prefilling script. If you know JavaScript, you directly read the Data Layer and store information in the cookie. Since I’m not one of the JS magicians, I’m forced to take the longer route. Maybe your website contains a page with a pricing calculator where visitors can find out the potential price. Why not push the calculated result (price) to the Data Layer? You could later pass that price with the form submission, and it could give you a better perception of how important that prospect is.
- Track which affiliates drive the most conversions to your site. Usually, when affiliate traffic lands on your website, the URL contains a particular affiliate ID, say, mywebsite.com/?affiliateid=123456. By following the exact UTM-extraction technique (described in this blog post), you can also pass the affiliateid with the form submission.
Conclusion – How To Enrich Form Submission Data with GTM
After learning how to enrich form submission data, you now have a better opportunity to see the context of each form submission without requiring a visitor to fill in some additional fields.
Everyone should know that the more fields there are in the form, the fewer people will complete it. But now, with this technique, you are adding some useful and insightful data without giving the burden to the visitor.
The workflow of how to enrich form submission data goes like this:
- Create several additional form fields
- Prepare variables in Google Tag Manager (it’s up to you whether you’ll be using URL variables, Data Layer Variables, or something else).
- Prepare a form-prefilling script.
- Install that script via Google Tag Manager.
- Test.
- Hide those additional form fields (and make sure you left them as optional).
- Test again.

18 COMMENTS
Hi Julius. thanks a lot again, it's very well explained.
I did it just to practice and it's working well.
Congrats for the post !
Simon
Thanks Simon!
Julius,
I'm trying this on a website which doesn't have a particular landing page.
The form is on a "quote" page but the user is landing on that page at the very beginning.
I'm tracking gravity form submission with a custom event.
What I would like to do is to add the source and medium as you did, even if the user is coming from an other page.
So I read your post about cookies since I guess I will have to use it to track all my users.
Simple question, do I have to create a cookie for all sources ?
Thanks,
Simon
You can either create 3 cookies: utm_medium, utm_campaign, utm_source, or you can create one cookie which contains all 3 utm parameters. I'd choose the first option because it will be easier in the future to slice and dice the data.
Julius,
Why do you pre-populate the fields with dummy values and then change data.
document.getElementById("field_ftdix").value = "some_value";
document.getElementById("field_ftdix").value = "{{URL - utm_medium}}";
Why not insert the data you want immediately?
document.getElementById("field_ftdix").value = "{{URL - utm_medium}}";
If you need to pre-populate the field why not set a dummy value at the html level.
I'm wondering if there is a reason you have to do it.
Hey, just for demonstration purposes only because not everyone reading this guide will not that the variable can be inserted with {{ }} (there are a lot of beginners too), so I explain it gradually. First "some_value", then I use a {{variable}} instead.
I asked because I had troubles getting the form to update.
The Tag was firing before the DOM had loaded and throwing a javascript error.
Fixed it by...
window.onload = function(){
document.getElementById("input_22_31").value = {{sourceCookie}};
};
Thanks for the quick reply
Hmm, but that's a good point regarding the DOM not being loaded. It would be more robust to change the trigger from Pageview to DOM Ready. I'll update it for the future readers.
Hi Julius,
Thanks so much for putting this up online, I've implemented everything and it is working great except for when I have two forms on a page.
We have a newsletter form on every page toward the footer and so the hidden utm form fields are populated on the first form but never the newsletter.
I understand this is because the form id should be unique and so I have hacked my way around it by giving the newsletter hidden form fields the id "xyz_utm_campaign" / "xyz_utm_medium" etc and then added these to the utm_form_values like so;
document.getElementById("utm_campaign").value = "{{session_utm_campaign}}";
document.getElementById("utm_medium").value = "{{session_utm_medium}}";
document.getElementById("utm_source").value = "{{session_utm_source}}";
document.getElementById("xyz_utm_campaign").value = "{{session_utm_campaign}}";
document.getElementById("xyz_utm_medium").value = "{{session_utm_medium}}";
document.getElementById("xyz_utm_source").value = "{{session_utm_source}}";
Is this a reasonable way around solving the issue or is there a more elegant way?
Thanks in advance for your help
:)
Yes, definitely. The script inserts values only to the first appropriate fields it finds, so if you have more similar fields, you should either add a more complex script with a loop or you can implement the solution you mentioned above.
Hi Julius, thanks a lot, it's working well...on computer. I don't know why but it's not working on mobile. Do you know the reason ? (Same form obviously)
I am trying to set this up with our drupal forms and the fields do not have an id.
This is what the page source looks like
Can I use Name instead for ID?
I am finding that the JS is only working with the first line and any line after the first doesn't work. Any thoughts. Here is my code.
document.getElementById("input_4_6").value = "{{Client ID}}";
document.getElementById("input_1_7").value = "{{Client ID}}";
document.getElementById("input_6_9").value = "{{Client ID}}";
Are you sure you have entered ID's correctly and that they are present when this code is fired?
Hi Julius,
I am wondering if it can work for Google Adwords Paid Search. If I click on a Paid Ads, visiting the website and submit a form, do you get the UTM parameters from Adwords (source : google, support : cpc...)
Thank you.
You can apply this to those traffic sources of which data is visible in the URL. If your ads are tagged with UTMs (or some other parameters), you can use them.
Thanks Julius for this great tutorial.
I wonder if it would be possible to get medium/source data out of GA4 cookies and import them as in this tutorial to variabels to send them with hidden form fields to our crm?
This wil help with all traffic without utm codes in URLs to collect these data.
Also I assume this also would work the get the data from the Google ads Glid codes?
arch! Just adding this comment to confirm 'Notify me when new comments are added.'
In the UX of the form I should set that checkbox just below the other checkbox?