14-day free trial · no card
UTM tracking for forms

Skip the hidden fields. Capture UTMs the right way.

One script tag captures first-touch, last-touch, and full-session UTMs for every form on your site.

5-min install. No card required.
Works with
Gravity Forms Contact Form 7 HubSpot Jotform Typeform Webflow WordPress Squarespace
Why hidden UTM fields keep failing you

You shouldn’t need a developer to track a UTM.

Hidden-field UTM tracking is the duct tape of marketing analytics. It looks fine in a clean demo. In production, with real visitors clicking around your site, it breaks in five predictable ways.

  • UTMs vanish on the second page view. Query string only sticks to the landing page. Visitor browses to your pricing page before filling the form? UTMs gone.
  • Every form needs its own hidden fields. Add a new form? Add the fields. Rebuild the JS. Test it. Multiply by every page, every variant, every campaign.
  • The form-builder plugin "for UTM tracking" only handles one form tool. Use Gravity and HubSpot and a Typeform embed? Three plugins, three configurations, three things to break.
  • Visitor returns three days later. UTMs reset. First-touch attribution? Without persistent storage and your own code to manage it, you’re only capturing whatever’s in the URL right now.
  • The data still arrives in your CRM as "utm_source": "(none)". Because the hidden field was empty when the form fired. Now you have a CRM full of nulls and no way to backfill.

Lead Source handles all of it. auto-detect, persist, attach, submit. With one script tag and zero per-form work.

How it works

One script. Every UTM. Every form.

The script captures UTMs at first touch, preserves them across the entire session, then attaches them to every form submission. Server-side, at the moment of submit.

Step 01 · Install

Paste one script tag

Drop it into your site head or paste it into Google Tag Manager. Works on every CMS, every framework, every form tool. No backend integration.

<script src="…/ls.js" data-site="…"></script>
Step 02 · Capture & persist

UTMs travel with the visitor

First-touch UTMs stored. Last-touch updated on each new campaign click. The full UTM payload survives navigation, tab switches, and same-day return visits.

// captured: source · medium · campaign · term · content
Step 03 · Attach on submit

Every form fires fully attributed

On submit, the full UTM payload. First touch, last touch, journey. Is sent server-side to your inbox, dashboard, webhook, or CRM. No hidden fields. No matching by email later.

// arrives: first.utm_source = "google" · last = "linkedin"
Try the 5-minute install

5-min install. No card required.

Attribution model

First touch, last touch, and everything in between.

Pick the model that matches your reporting. Or use all three. Every lead arrives with the full timeline attached.

First touch

The campaign that found them

The UTMs from the visitor’s very first session on your site. Stored from day one. Doesn’t get overwritten by later campaign clicks.

first.utm_source google first.utm_medium cpc first.utm_campaign brand-terms first.seen_at 2026-04-22
Last touch

The campaign that closed them

The UTMs from the session in which they submitted. Updates on every new campaign click. Maps to "what worked right before they converted."

last.utm_source linkedin last.utm_medium cpc last.utm_campaign q2-retarget last.seen_at 2026-05-19
Full journey

Every campaign in between

The ordered sequence of every campaign click in the visitor’s history. Plug into multi-touch attribution. Or just look at what made the difference.

journey[0] google / brand journey[1] organic / blog journey[2] email / nurture journey[3] linkedin / retarget
Capture every UTM

14-day free trial · 5-min install. No card required.

Cross-session UTM persistence

UTMs don’t reset just because a visitor came back tomorrow.

Most "UTM tracking" tools only capture what’s in the URL right now. Lead Source remembers the campaign that first found a visitor. And every campaign click since. Even if the form submission is days, weeks, or a hundred page views away.

Day 1 · 9:14am First touch. Google Ads click
utm_source=google · utm_campaign=brand-terms
Day 3 Direct visit. Checked pricing
utm_source=(none). first-touch preserved
Day 7 Email campaign click
utm_source=email · utm_campaign=nurture-week-2
Day 12 · 4:42pm Last touch. LinkedIn retarget → form submit
first=google/brand · last=linkedin/retarget · journey=4 touches

Same lead. Three campaigns deserve credit. All three captured. Most tools would have shown this lead as "direct" or "(none)". Because the form fired on a session without a UTM in the URL.

We had a custom script our dev built two years ago to pass UTMs into Gravity Forms. Half the leads still came in as "direct." Swapped to Lead Source in an afternoon. first-touch and last-touch on every submission, no code on our end.

Jason Cole
Marketing Ops Lead · B2B SaaS
Compatibility

Works with every form tool. Without touching them.

No plugin per platform, no per-form hidden fields. The script attaches to forms automatically, whatever tool they were built with.

Gravity Forms WordPress Auto
Contact Form 7 WordPress Auto
HubSpot Embedded Auto
Jotform Embedded / iframe Auto
Typeform Embedded / popup Auto
Webflow Native Auto
Squarespace Native Auto
Wix Native Auto
Forminator WordPress Auto
Native HTML Any form tag Auto

If it’s a form on a web page, we attach to it. No per-form setup required.

Questions marketers ask first

The four things you’re probably thinking.

"We already use hidden fields. Why switch?"

Hidden fields work for the leads who fill in the form on their first session, on the landing page, without navigating anywhere else. In reality that’s a minority of your leads. Lead Source captures the rest. The visitors who come back later, the ones who browse before submitting, the ones who clicked an email before filling a form on a different page. And you stop maintaining per-form fields forever.

"How is this different from Google Analytics?"

GA4 sees the click, not the lead. It tells you sessions and conversions in aggregate, but never connects a specific UTM payload to a specific submitted form. Lead Source does that. first.utm_* and last.utm_* attached to the actual lead record, ready for your CRM or warehouse.

"Does the visitor have to be cookied for this to work?"

No cookies. No client-side storage. No fingerprinting. UTM persistence is handled server-side. Means the script sits outside ePrivacy/PECR storage-and-access scope entirely. No cookie banner required for our snippet, and the data still works.

"How do UTMs get into HubSpot / Salesforce / our CRM?"

However you want them. Direct webhook into HubSpot or Salesforce, Zapier, Make, native CRM integrations, or just email + dashboard. The full payload. first.utm_source, last.utm_campaign, the journey array. Is available on every lead record.

UTM tracking · for forms · done right

Stop building hidden fields. Start capturing UTMs.

One script tag, five minutes, every form on your site with every UTM and every visit captured. Free to start. No card required.

Start free
5-min install. No card required.