A lead arrives in the CRM. Name, email, company, message. What it does not say is how this person found you. Was it the LinkedIn campaign, the newsletter sponsorship, an organic blog post or a referral from a partner? Six months later the lead becomes a large customer and nobody can say which channel deserves the credit, or the budget.
This is one of the most common gaps in marketing measurement, and one of the most fixable. Analytics tools know where sessions came from, and the CRM knows which leads turned into revenue, but nothing joins them unless you deliberately capture source data on the form and carry it into the lead record.
This guide shows how to build that join: which fields to capture, a simple script for first-touch and last-touch data, hidden fields in common form tools, mapping into HubSpot, Salesforce and other CRMs, and the reporting and governance that keep the data trustworthy.
Where lead source data leaks out between the click and the CRM
Source data rarely disappears in one place. It drips away at several points, and you need to plug each of them:
- UTMs that never reach the form page. A visitor lands on a blog post with campaign parameters, browses three pages, then fills in the contact form. The URL of the form page no longer has the UTMs.
- Forms that do not ask for it. Most form builders send the fields a visitor sees. Unless someone adds hidden fields, source data is never part of the submission.
- Redirects that strip parameters. Some redirects, vanity URLs and link shorteners drop query strings, taking UTMs and click IDs with them.
- Cross-domain journeys. A booking or checkout on a different domain starts fresh unless parameters or linker values are passed across.
- Manual entry. A "How did you hear about us?" dropdown is useful, but people pick the first option, and sales reps overwrite fields.
- CRM fields that overwrite themselves. A "Lead source" field updated with every new form fill erases the first touch.
Self-inflicted analytics settings can make things worse. Google warns that telling Analytics to ignore referrers too broadly has a cost; applying it to every page:
“may lose valuable information regarding your traffic sources.”
— Google Analytics Help, [GA4] Identify unwanted referrals
The same principle applies to your own capture: throw nothing away at collection, and decide how to classify it later.
A source data model worth copying
Decide on the fields before touching any form. The model below works for most lead-generation businesses. Store each field twice, once as first touch (never overwritten) and once as last touch (overwritten on each new campaign visit).
| Field | Example value | Where it comes from | Why you need it |
|---|---|---|---|
| utm_source | URL parameter | Platform or publisher | |
| utm_medium | paid_social | URL parameter | Channel grouping |
| utm_campaign | 2026q4_cfo_guide | URL parameter | Campaign-level revenue |
| utm_content | carousel_v2 | URL parameter | Creative or placement |
| utm_term | fractional cfo | URL parameter | Keyword, where relevant |
| Click ID | gclid, gbraid, wbraid, msclkid, fbclid, li_fat_id | Added automatically by ad platforms | Offline conversion uploads |
| Landing page | /fractional-cfo-guide/ | Page path at entry | Content attribution |
| Referrer | https://www.google.com/ | Browser referrer at entry | Fallback when UTMs are missing |
| Touch timestamp | 2026-09-14T10:32Z | Script | Time to convert |
| Self-reported source | "Podcast" | Visible form field | Dark social, word of mouth |
The values you capture are only as consistent as the links you build. Google's own documentation stresses that Analytics treats them literally:
“Parameter values are case sensitive, e.g. utm_source=google is different from utm_source=Google.”
— Google Analytics Help, [GA4] URL builders: Collect campaign data with custom URLs
Your CRM may or may not be case sensitive, but your reports will be a mess either way. Agree lowercase values and a naming pattern first; our guide to UTM parameters has a template.
Capturing first touch and last touch with a small script
The simplest reliable approach stores source data in the browser when a visitor arrives, then writes it into hidden fields when they reach a form. Here is the logic, step by step:
- On every page load, read the URL parameters for UTMs and click IDs.
- If any are present, or if the referrer is an external site, treat the visit as a new touch.
- Save the touch as first touch only if nothing is stored yet. Always save it as last touch.
- Store the landing page and referrer with each touch.
- On pages with a form, read both stored touches and populate the matching hidden fields.
- If nothing is stored (storage blocked or consent declined), fill the hidden fields from the current URL and referrer as a fallback.
A minimal version of steps 1 to 4 looks like this:
// Runs on every page, after consent where required
(function () {
var p = new URLSearchParams(location.search);
var keys = ['utm_source','utm_medium','utm_campaign','utm_content','utm_term',
'gclid','gbraid','wbraid','msclkid','fbclid','li_fat_id'];
var touch = {};
keys.forEach(function (k) { if (p.get(k)) touch[k] = p.get(k); });
var hasCampaign = Object.keys(touch).length > 0;
var external = document.referrer && document.referrer.indexOf(location.hostname) === -1;
if (hasCampaign || external) {
touch.landing_page = location.pathname;
touch.referrer = document.referrer || '(direct)';
touch.ts = new Date().toISOString();
try {
if (!localStorage.getItem('ft')) localStorage.setItem('ft', JSON.stringify(touch));
localStorage.setItem('lt', JSON.stringify(touch));
} catch (e) {}
}
})();
Most teams deploy this through Google Tag Manager as a custom HTML tag, with a second tag that fills the hidden fields when a form is visible. If your site pushes events to a data layer, add the stored values there too, so analytics and the CRM read the same thing; our data layer guide explains the pattern. Visits with no UTMs and no external referrer (internal navigation, reloads) are deliberately ignored, so they do not overwrite real touches.
Hidden fields in the form tools you probably use
Almost every form tool supports hidden fields, but the mechanics differ. Name the fields identically across forms so one CRM mapping works for all of them.
| Form tool | How hidden fields are added | How they are filled | Watch out for |
|---|---|---|---|
| HubSpot forms | Add a contact property to the form and set it as hidden | Query string matching the property's internal name, or script | HubSpot's own source properties are calculated separately from yours |
| Gravity Forms, WPForms and similar WordPress plugins | Hidden field type with a parameter name | Dynamic population from query string, or script | Query string only works if UTMs are on the form page URL |
| Typeform, Jotform and other embedded forms | Hidden fields defined in the form | Passed through the embed URL | The embed must be built with the values, not just the parent page |
| Salesforce Web-to-Lead | Hidden input elements mapped to lead fields | Script | Field IDs, not labels, are used in the HTML |
| Custom forms | Hidden inputs | Script | Server code must save them, not just the visible fields |
| Ad platform lead forms | Not applicable (no website visit) | Platform passes campaign data via integration or webhook | Needs its own mapping into the CRM |
Platform lead forms deserve a note. Google Ads lead form assets, LinkedIn Lead Gen Forms and Meta lead ads collect contact details inside the ad, so there is no website visit to capture. Use the platform's CRM integration or a webhook, and set source fields from the campaign data the platform sends.
Test every form after setup: visit with a test URL such as ?utm_source=test&utm_medium=test&utm_campaign=hidden_field_check, browse two other pages, submit the form, and confirm the values arrive on the CRM record.
Mapping source fields into HubSpot, Salesforce and other CRMs
The CRM side is where most implementations go wrong, usually because a field gets overwritten or the values land on the wrong object.
HubSpot
HubSpot calculates its own original source and latest source properties from its tracking code. Keep them; they are useful. But create your own custom contact properties (for example ft_utm_source and lt_utm_source) for the exact values you capture, because HubSpot's categories are broader than your UTMs. Set first-touch properties so a workflow only fills them when empty, and copy key values to the deal when it is created so revenue reports can group deals by source.
Salesforce
Create custom fields on the Lead object for each source value, and map them to matching fields on Contact, Account or Opportunity in the lead conversion settings. Without that mapping, the data stays on the converted lead record and never reaches the opportunity that carries revenue. Many teams also set the standard Lead Source picklist from the captured medium through a flow, so legacy reports keep working.
Other CRMs
Pipedrive, Zoho, Dynamics and others all support custom fields. The rules are the same: separate first-touch and last-touch fields, protect first-touch fields from being overwritten, and carry source fields to whatever object holds revenue. For a wider view of how marketing uses CRM data, see our guide to CRM for marketing.
Click IDs: closing the loop with your ad platforms
UTMs tell you which campaign. Click IDs let the ad platform learn which clicks became customers. When you store the Google Ads GCLID (or GBRAID and WBRAID for some iOS traffic), the Microsoft MSCLKID or the Meta FBCLID on the lead, you can later upload qualified leads and closed deals back to each platform as offline conversions.
That matters because bidding algorithms optimise towards whatever you tell them is a conversion. If they only see form fills, they will find more form fills, including poor ones. If they see "sales-qualified lead" and "closed won" with values, they can find more of those. Our guide to offline conversion tracking covers uploads in detail, and enhanced conversions explains how hashed first-party data improves matching when click IDs are missing.
Two practical rules: keep the click ID exactly as received (do not lowercase or trim it), and record the timestamp of the click or form fill, because uploads need a conversion time and platforms only accept conversions within a limited window after the click.
Privacy rules and browser limits on stored source data
Source tracking is not exempt from privacy law or browser restrictions. Plan for both.
- Consent. In the UK and EU, storing campaign data in a cookie or local storage is usually non-essential and needs consent. Fire the capture script only after consent, and use the current-URL fallback when consent is declined. Our guide to marketing privacy laws covers the wider rules.
- Safari's storage limits. Safari's tracking prevention caps the lifetime of storage written by scripts, so a first touch stored weeks before the form fill may be gone. Expect some first touches to really be "the first touch Safari remembered".
- Click ID stripping. Apple's link tracking protection removes some known click identifiers from URLs in private browsing and in Mail and Messages. UTMs are not removed, which is one reason to use both.
- Data minimisation. Capture what you will use. Full referrer URLs can contain personal data in query strings; strip query strings from referrers before saving.
Example: what six months of captured source data showed
Example: a hypothetical B2B services firm, illustrative numbers.
Before capturing source data, the firm judged channels by form fills in GA4. Paid social looked like the winner because it produced the most leads at the lowest cost per lead. After six months of first-touch and last-touch capture, with source fields copied to deals, the revenue picture looked different:
| First-touch channel | Leads | Spend | Cost per lead | Closed revenue | Revenue per £1 spent |
|---|---|---|---|---|---|
| Paid social | 310 | £18,600 | £60 | £41,000 | £2.20 |
| Paid search | 140 | £16,800 | £120 | £96,000 | £5.71 |
| Newsletter sponsorships | 45 | £6,000 | £133 | £38,000 | £6.33 |
| Organic search | 190 | n/a | n/a | £121,000 | n/a |
Paid social leads were cheap but rarely closed. Paid search and the small newsletter test, judged on cost per lead, would have been cut; judged on revenue they were the best uses of budget. If you are testing sponsorships, our guide to newsletter sponsorships covers how to tag those links so this kind of report is possible. To turn revenue by source into a payback view, see CAC payback period.
The firm also found that 22% of leads had no first-touch data because consent was declined or storage had expired. That is normal. Report the unknown share openly instead of spreading it across channels.
Keeping lead source data clean after launch
Source capture decays without maintenance. A short routine keeps it healthy:
- Keep one shared UTM naming sheet with allowed sources and mediums, and reject anything else in a weekly report of new values.
- Lock first-touch fields so only the integration can write them; sales users get read-only access.
- Run a monthly check: the share of new leads with empty source fields, broken out by form. A sudden jump usually means a form was rebuilt without hidden fields.
- Re-test hidden fields after every website release, form edit or CMS update.
- Normalise values in the CRM with a simple mapping table (for example, "fb", "facebook.com" and "Facebook" all become "facebook").
- Reconcile with GA4 quarterly. Our GA4 audit checklist includes a lead reconciliation step that catches tracking faults on both sides.
Questions about capturing UTM data in forms and CRMs
Why not just use GA4 to see where leads came from?
GA4 reports sessions and key events in aggregate, and it is not designed to store personal data such as a lead's name or email. Your CRM knows which lead became a customer and for how much. Capturing source data on the lead record is the only reliable way to join the two.
Should I store first-touch or last-touch source?
Both. First touch tells you which channels create demand; last touch tells you what brought people back to convert. Storing both costs two extra sets of hidden fields and avoids arguments later about which model is right.
What happens if a visitor arrives without UTMs?
Fall back to the referrer. If there is a referrer from a search engine, record organic search; from another site, record referral; with no referrer, record direct. Store the raw referrer too so you can reclassify later.
Do I need consent to store UTM data in a cookie?
In the UK and EU, storing non-essential information on a device generally requires consent, and source tracking is usually treated as non-essential. Many sites only write the first-touch cookie after analytics consent, and fall back to capturing parameters from the current page URL at submission. Check with your privacy adviser.
How long should first-touch data be kept?
Long enough to cover your typical sales cycle from first visit to form fill, often 90 days to a year. Bear in mind that Safari limits cookies set by JavaScript, so some returning visitors will appear as new first touches whatever you set.
Can I add source data to leads that already exist?
Only partially. You can match historical leads to email campaigns, events or ad platform lead lists, but web source for past form fills is usually lost. Start capturing now and mark older records as 'unknown' rather than guessing.
Getting source data onto your next 100 leads
Start with one form and one CRM field set: add first-touch and last-touch hidden fields for source, medium, campaign and click ID, deploy the capture script, test with a tagged URL and check the record. Once the first form works, roll the same fields out to every form and map them to deals. In a quarter you will have revenue by source instead of opinions.
If you would like help connecting your ads, forms and CRM so you can see which marketing really produces revenue, our PPC management team sets up source capture and offline conversions as part of onboarding. Get a quote to discuss your setup.
Further reading on UTM data in CRM
- How to Estimate Competitor Website Traffic (and How Accurate It Is)
- GA4 Audit Checklist: Make Sure Your Data Can Be Trusted
- Bot Traffic in Analytics: How to Spot and Filter It
Sources for this guide to UTM data in your CRM
- Google Analytics Help: [GA4] URL builders: Collect campaign data with custom URLs
- Google Analytics Help: [GA4] Identify unwanted referrals
- Google Analytics Help: [GA4] Set up cross-domain measurement
- Google Ads Help: About lead form assets
- Semrush: UTM Tracking Codes in Google Analytics
- Semrush: CRM Marketing




