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.

  1. Add hidden fields named utm_source, utm_medium, utm_campaign, utm_term and utm_content.
  2. Fill them from the URL query string.
  3. Save the values so they survive page changes.
  4. Map the fields into your CRM.
  5. 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 nameFills fromExample value
utm_source?utm_source=google
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_pagethe first page URL/pricing
referrerdocument.referrerthe 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:

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

  1. Open your site with a test URL such as ?utm_source=test&utm_medium=test&utm_campaign=hidden-field-check.
  2. Click to a second page.
  3. Submit the form.
  4. Check the entry in your form tool and in the CRM. All three values should be there.
  5. 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

RequirementHand-builtTrakt
Hidden fields on every formAdd and maintain each oneInjected automatically
Values across pagesYour own cookie scriptFirst-party cookie, 90 days
Click IDsExtra fieldsCaptured
Into the CRMMap each fieldSynced
ConsentYour banner rulesRespects Consent Mode v2, OneTrust, Cookiebot
Tagging your links consistentlySame either waySame 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.