How Do You Track UTMs in Contact Form 7, Gravity Forms, and Typeform?
Each form tool tracks UTMs the same way in principle: hidden fields read the URL parameters and submit them with the form. Contact Form 7 needs a hidden-field plugin or code, Gravity Forms has dynamic population, and Typeform uses hidden fields in the form link. Tools like Trakt receive submissions from some of these tools by webhook.
- Contact Form 7: there is no native support for reading URL parameters, so add hidden fields and fill them with a plugin or a short script.
- Gravity Forms: add a Hidden field and set its default value to
{query:utm_source}(and the same for the other four parameters). - Typeform: add each UTM name under Connect, then Hidden fields, and make sure the UTMs are on the Typeform URL itself, which needs an extra script if the form is embedded.
The form UTM chain, in four steps
The UTM in the URL is read into a hidden field, submitted with the form, and mapped to a CRM property.
Each platform section below covers the same chain, so if a lead arrives untracked, find the link that broke and fix that one.
Platform Comparison at a Glance
| Contact Form 7 | Gravity Forms | Typeform | |
|---|---|---|---|
| Native UTM support | No (needs plugin or JS) | Yes (query shortcode) | Yes (hidden fields setting) |
| Best CRM integration path | Zapier | Native add-ons or Zapier | Native integrations or Zapier |
| Embedded form UTM issue | No | No | Yes, needs extra script |
| Multi-step form note | N/A | Add hidden fields on page 1 | N/A |
| Maintenance overhead | Medium | Low | Low |
How to Set Up UTM Tracking in Each Form Tool
Contact Form 7
Contact Form 7 is one of the most widely used WordPress form plugins, and one of the more annoying to set up UTM tracking on, because it doesn't natively support reading URL parameters into hidden fields.
Option 1: use a plugin (fastest). Install "Contact Form 7 UTM Tracker" or "CF7 Populate Fields" from the WordPress plugin directory. These plugins add a shortcode that reads URL parameters automatically. With CF7 Populate Fields installed, add this to your form's template:
[hidden utm_source default:query_post_meta]
[hidden utm_medium default:query_post_meta]
[hidden utm_campaign default:query_post_meta]
[hidden utm_content default:query_post_meta]
[hidden utm_term default:query_post_meta]
The plugin reads each field name as a query parameter from the URL and pre-fills the hidden field on page load. No additional JavaScript is required.
Option 2: JavaScript (no additional plugin). Add this to your theme's footer, or use a plugin like Code Snippets to add it without editing theme files:
document.addEventListener("DOMContentLoaded", function () {
const params = new URLSearchParams(window.location.search);
const utmFields = ["utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term"];
utmFields.forEach(function (key) {
const input = document.querySelector('input[name="' + key + '"]');
if (input && params.get(key)) {
input.value = params.get(key);
}
});
});
In your CF7 form template, add the hidden fields first:
[hidden utm_source]
[hidden utm_medium]
[hidden utm_campaign]
[hidden utm_content]
[hidden utm_term]
The JavaScript finds these fields and populates them from the URL on page load.
Connecting CF7 to your CRM: CF7 doesn't have native CRM integrations. You'll use either the CF7 to Zapier plugin or Flamingo (CF7's companion plugin for storing submissions) plus a Zapier workflow. In Zapier, when building the "Create Contact in [CRM]" action, you'll see the CF7 field names in the trigger data. Map each UTM field explicitly to the corresponding CRM property.
Test it: visit yoursite.com/contact-page?utm_source=test&utm_medium=test&utm_campaign=test, submit the form, then check Zapier's task history or your CRM for the test lead. Verify the UTM values populated.
Gravity Forms
Gravity Forms has better native support for UTM capture than CF7, but there are still configuration steps.
Using the built-in Hidden field. Gravity Forms has a "Hidden" field that can read from URL parameters:
- Add a new field to your form and choose Advanced Fields, then Hidden.
- Give it a field label (for example, "UTM Source"). This is internal only.
- Under Default Value, enter
{query:utm_source}.
The {query:parameter_name} syntax is Gravity Forms' built-in shortcode for reading URL parameters. Do this for each of the five UTM parameters.
CRM integration: Gravity Forms has official add-ons for HubSpot, Salesforce, and Mailchimp. In each add-on, a field mapping section lets you specify which form field maps to which CRM field. Map each hidden UTM field to the corresponding CRM property (custom contact properties in HubSpot, custom Lead fields in Salesforce). For GoHighLevel users, there is no official Gravity Forms add-on, so use Gravity Forms to Zapier to GoHighLevel, mapping the UTM fields in the Zap action.
The multi-step gotcha: if you're using Gravity Forms' multi-page feature (the form spans multiple pages), hidden fields only read URL parameters on the page they're placed on. Add your hidden UTM fields to the first page of the form. They'll be stored in form state and submitted when the final page is submitted.
Typeform
Typeform handles hidden fields differently from most form tools. They're configured at the form URL level, not inside the form builder.
Setting up the UTM hidden fields:
- Open your Typeform and go to Connect, then Hidden fields.
- Click "Add hidden field".
- Enter the field identifier
utm_source. - Repeat for
utm_medium,utm_campaign,utm_content, andutm_term.
Save the form. Now, when you share your Typeform link with UTM parameters appended (https://yourform.typeform.com/to/abc123?utm_source=linkedin), Typeform reads those parameters and attaches them to the response.
Viewing UTM data: in your Typeform results, each response shows the hidden field values alongside the answers. You can export results to CSV and the UTM columns will be included.
CRM integration: Typeform has native integrations with HubSpot and Salesforce. In the integration settings, a field mapper lets you map each UTM hidden field to the corresponding CRM property. For Zapier, Typeform passes hidden fields as part of the response payload in the Zap trigger, and they appear as separate fields in the Zap action mapper.
The Typeform gotcha: Typeform requires UTM parameters to be appended to the Typeform URL itself, not to a landing page URL that embeds the Typeform. If you're embedding a Typeform on your website, the visitor's URL (with UTMs) isn't the same as the Typeform URL. You'll need a custom embed script that reads UTMs from the page URL and appends them to the Typeform URL on the fly:
document.addEventListener("DOMContentLoaded", function () {
const params = new URLSearchParams(window.location.search);
const tfIframe = document.querySelector('iframe[src*="typeform.com"]');
if (tfIframe) {
const url = new URL(tfIframe.src);
["utm_source", "utm_medium", "utm_campaign", "utm_content", "utm_term"].forEach(function (key) {
if (params.get(key)) url.searchParams.set(key, params.get(key));
});
tfIframe.src = url.toString();
}
});
If you want submissions recorded with their source across your forms, pre-register for Trakt.
Why Per-Form Setup Breaks in Practice (And How Trakt Handles It)
Everything above works, and it also has a maintenance problem. Every method requires you to configure forms individually and maintain that configuration as forms change. Add a new landing page, forget the hidden fields, and those leads come in untracked.
How Trakt closes the gap
Trakt scans your site automatically and injects UTM hidden fields into every form it detects: Contact Form 7, Gravity Forms, Typeform embeds, and most other form tools. When a form changes or a new one is added, Trakt's injection updates.
Per-Form Setup vs. Trakt, By Requirement
| Requirement | Per-form setup (DIY) | Trakt |
|---|---|---|
| Hidden UTM fields | Configured form by form, in each tool's own way | Injected into every form it detects |
| New landing pages and forms | Easy to forget the hidden fields, and those leads arrive untracked | Covered as new forms are detected |
| Forms that change over time | The configuration has to be maintained by hand | The injection updates when a form changes |
| Testing the result | Same either way: submit a test form with UTMs and check the CRM record | Same either way: submit a test form with UTMs and check the CRM record |
Frequently Asked Questions
How do I track UTM parameters in Contact Form 7?
Contact Form 7 doesn't natively read URL parameters, so add hidden fields to the form template and fill them with either a plugin such as CF7 Populate Fields or a short JavaScript snippet that copies the UTMs from the URL into the fields on page load. Then map each field to a CRM property, usually through Zapier or Flamingo plus Zapier.
How do I track UTMs in Gravity Forms?
Add a Hidden field from Advanced Fields and set its Default Value to {query:utm_source}, using the matching parameter name for each of the five UTMs. Gravity Forms reads the URL parameter for you, and its official HubSpot, Salesforce, and Mailchimp add-ons let you map each hidden field to a CRM property.
Why aren't UTMs showing up in my embedded Typeform?
Typeform reads UTMs from the Typeform URL itself, not from the page that embeds it. A visitor landing on your site with UTMs in the page URL won't pass them to the embedded form on their own, so you need a small script that copies the UTMs from the page URL onto the Typeform iframe URL on load.
Do hidden UTM fields work on multi-page Gravity Forms?
Yes, with one rule: hidden fields only read URL parameters on the page they're placed on. Put the hidden UTM fields on the first page of the form, and the values are stored in form state and submitted when the final page is submitted.
How do I get UTM data from these forms into my CRM?
Map each hidden UTM field to the matching CRM property. Gravity Forms and Typeform have native integrations for some CRMs, such as HubSpot and Salesforce, while Contact Form 7 needs Zapier. Whichever path you use, test with a URL like ?utm_source=test&utm_medium=test&utm_campaign=test and confirm the values appear on the lead record.


