How do you capture UTM parameters in a form?
To capture UTM parameters in a form, add a hidden field for each parameter, then fill those fields from the page URL, or from a cookie saved on the first visit, before the visitor submits. The values travel with the submission into your inbox, CRM or database, so every lead keeps its source.
- Add hidden fields named
utm_source,utm_medium,utm_campaign,utm_termandutm_content. - Fill them from the URL query string.
- Save the values so they survive page changes.
- Map the fields into your CRM.
- Submit a test lead and check it.
A tagged link reaches the landing page, the page reads the UTMs and saves them in a cookie, hidden fields are filled from it, and the submission carries the source into your CRM.
A hidden field is a form input the visitor can't see. It's submitted with the rest of the form, which makes it the standard place to carry tracking data.
Which hidden fields to add
| Hidden field name | Fills from | Example value |
|---|---|---|
utm_source | ?utm_source= | |
utm_medium | ?utm_medium= | cpc |
utm_campaign | ?utm_campaign= | spring-demo |
utm_term | ?utm_term= | crm software |
utm_content | ?utm_content= | headline-b |
gclid | ?gclid= | Google Ads click ID |
landing_page | the first page URL | /pricing |
referrer | document.referrer | the previous site |
Match the names exactly, in lowercase. Your CRM fields should use the same names, which makes mapping painless.
Step by step: add hidden UTM fields to a form
HTML forms
Add the inputs inside your form element:
<input type="hidden" name="utm_source">
<input type="hidden" name="utm_medium">
<input type="hidden" name="utm_campaign">
<input type="hidden" name="utm_term">
<input type="hidden" name="utm_content">
Then add this script before the closing body tag. It saves UTMs from the URL into a first-party cookie for 90 days, and fills any matching hidden field on every page:
(function () {
var keys = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "gclid"];
var params = new URLSearchParams(window.location.search);
var found = {};
keys.forEach(function (k) { if (params.get(k)) found[k] = params.get(k); });
if (Object.keys(found).length) {
document.cookie = "utm_store=" + encodeURIComponent(JSON.stringify(found)) +
"; max-age=" + 60 * 60 * 24 * 90 + "; path=/; SameSite=Lax";
}
var match = document.cookie.match(/(?:^|; )utm_store=([^;]*)/);
var stored = match ? JSON.parse(decodeURIComponent(match[1])) : {};
keys.forEach(function (k) {
document.querySelectorAll('input[name="' + k + '"]').forEach(function (el) {
if (stored[k]) el.value = stored[k];
});
});
})();
No-code form builders
Most builders support hidden fields that fill from the URL:
- Typeform: hidden fields, passed as URL parameters. See Typeform hidden fields.
- Tally: hidden fields read from the URL. See Tally hidden fields.
- WordPress plugins: most offer dynamic population. UTM tracking for popular form plugins lists them.
The catch with builders: they read the URL of the page the form sits on. If the visitor landed on a different page first, the UTMs are gone unless something carried them over.
Map the fields into your CRM
Create matching properties in your CRM (for example "UTM Source", "UTM Campaign"), then map each hidden field to its property in the form integration. Keep these fields read-only after creation so a later form fill doesn't overwrite the original source.
Once the manual steps work, you can skip maintaining them: pre-register for Trakt and the hidden fields are injected and filled on every form for you.
Persistence: why values disappear
The most common failure isn't the form. It's that the visitor clicked an ad, read three pages, then submitted, and the UTMs were only on the first URL. Saving them in a cookie or sessionStorage on arrival fixes it. A cookie survives across sessions. sessionStorage dies when the tab closes. Why UTM data gets lost on form submission walks through the other causes.
How to test it
- Open your site with a test URL such as
?utm_source=test&utm_medium=test&utm_campaign=hidden-field-check. - Click to a second page.
- Submit the form.
- Check the entry in your form tool and in the CRM. All three values should be there.
- Repeat in a private window and on a phone.
Why hand-built hidden fields break in practice (and how Trakt helps)
Every new form needs the fields again. Redesigns drop them. A builder update changes the parameter syntax. Consent banners block the script on some visits. And nobody notices until the report says Direct.
How Trakt closes the gap
Trakt injects the hidden UTM fields into your forms automatically and fills them, including forms added later. You can also build forms in Trakt. Each submission is stored with its source, the first touch is kept, visits are connected across devices, and the source and revenue sync into your CRM. New leads alert you by email and Slack.
Hand-built vs. Trakt, by requirement
| Requirement | Hand-built | Trakt |
|---|---|---|
| Hidden fields on every form | Add and maintain each one | Injected automatically |
| Values across pages | Your own cookie script | First-party cookie, 90 days |
| Click IDs | Extra fields | Captured |
| Into the CRM | Map each field | Synced |
| Consent | Your banner rules | Respects Consent Mode v2, OneTrust, Cookiebot |
| Tagging your links consistently | Same either way | Same either way |
FAQ
How do I capture UTM parameters in a form?
Add hidden fields named after each UTM parameter, then fill them with JavaScript from the URL or from a cookie saved on the visitor's first page. The values are submitted with the form and can be mapped to CRM fields.
What are hidden fields in a form?
Hidden fields are form inputs the visitor doesn't see. They're sent with the submission like any other field, which makes them the usual way to pass tracking data such as UTM parameters, click IDs and the landing page.
Why are my hidden UTM fields empty?
Usually because the UTMs were only on the first page and the form is on a later one. Store the values in a cookie on arrival and fill the fields from it. Also check that redirects keep the query string and that the field names match exactly.
Should I use a cookie or sessionStorage for UTM parameters?
Use a cookie if you want the source to survive a return visit days later. sessionStorage is simpler but clears when the tab closes. Either way, respect your consent banner.
Can I capture UTM parameters without coding?
Yes. Typeform, Tally and most WordPress form plugins support hidden fields that fill from the URL. Trakt goes further and adds and fills the hidden fields on your forms automatically.
Do I need to capture gclid as well as UTMs?
If you run Google Ads, yes. The gclid click ID identifies the exact ad click. Capture it in its own hidden field next to the UTMs.
What to do first
Open your highest-traffic form, add a test URL with utm_source=test, click to another page and submit. If the entry has no source, you've found the leak. Fix persistence first, then the fields.


