UTM Parameters
Chapter 16 — Integrating UTM Tracking with CRM and Lead Management
Your CRM only earns revenue credit for marketing when UTMs survive the jump from first click to form to deal. This chapter shows how to capture UTM data on the site, write it into forms, model it in CRM with write-once vs refresh rules, and carry it into Campaigns and Opportunities for pipeline and revenue reporting.
This chapter stays focused on the mechanics: capture → populate → store → preserve → connect → report.
The Click-to-CRM Chain
The basic idea is that UTMs are preserved from the time a user clicks your link to the time they get safely stored in your CRM. This journey from click to CRM is vulnerable and very likely to leak. The process continues even after capturing in CRM because now you should be able to connect them to revenue and work on reporting outcomes.
Here is how you can tackle this “chain”. We’ll talk about various other considerations in preserving and/or sending UTM values subsequently.
- Capture on arrival: When someone clicks your link, we read the UTM tags in the URL and save them (like a luggage tag) so they don’t get lost when they browse more pages.
- Populate forms: When they fill a form, those saved UTM tags are quietly added into hidden fields so the form sends them to your systems.
- Store in CRM: Your CRM saves these tags in the right Lead/Contact fields. We set rules so random updates can’t overwrite them.
- Preserve history: The “first-touch” fields show how the person first found you and never change. The “last-touch” fields update only when they submit a new important form.
- Connect to revenue: We link the person to a Campaign and copy the UTM info to any new Opportunity, so you can see which click helped create potential revenue.
- Report outcomes: Because UTMs are on people and deals, you can report which tags created leads, opportunities, pipeline, and closed revenue.
Let’s discuss these in detail with clear steps on what you can do.
1. Capture on Arrival
Capture UTMs at first touch and persist beyond the session
Use one or more methods based on your stack. The goal: reliable values from first click to form submission—even if the user returns days later from another channel.
| Method | How it works | Pros | Watch-outs |
|---|---|---|---|
| Hidden form fields prefilled from URL | Form fields read utm_ values from the query string | Simple, no backend work | Only works if the visitor converts in the same page/session |
| First-party cookie or localStorage | JavaScript parses UTMs and stores them for later use | Captures first-touch for later conversions | Cookie expiry; cross-subdomain scope |
| Tag manager variables (e.g., GTM) | Variables capture UTMs and set cookies/dataLayer | Centralized logic across sites | Requires GTM governance |
| Server-side capture (edge/lambda) | Server reads UTMs and sets HttpOnly cookie | Robust, resilient to client-side issues | Needs engineering support |
Quick-start JavaScript (client-side cookie + hidden fields)
The code may have to change based on your CRM / form fields and cookie names you would prefer assigning.
<script>
(function(){
function getParam(n){return new URLSearchParams(location.search).get(n)||'';}
function setCookie(n,v,days){
var d=new Date();d.setTime(d.getTime()+days*24*60*60*1000);
document.cookie=n+"="+encodeURIComponent(v)+";path=/;SameSite=Lax;expires="+d.toUTCString();
}
function getCookie(n){
return (document.cookie.match('(^|;)\\s*'+n+'\\s*=\\s*([^;]+)')||0)[2]||'';
}
var keys=['utm_source','utm_medium','utm_campaign','utm_term','utm_content'];
var hasUTM=keys.some(function(k){return getParam(k);});
if(hasUTM){
keys.forEach(function(k){
var v=getParam(k);
if(v){
if(!getCookie('first_'+k)) setCookie('first_'+k, v, 180); // write-once
setCookie('last_'+k, v, 30); // always refresh
}
});
}
function fillInputs(){
keys.forEach(function(k){
var first=getCookie('first_'+k), last=getCookie('last_'+k);
var fi=document.querySelector('input[name="first_'+k+'"]'); if(fi) fi.value=first;
var li=document.querySelector('input[name="last_'+k+'"]'); if(li) li.value=last||first;
});
}
if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', fillInputs); else fillInputs();
})();
</script>
For single-page apps, also run the “fillInputs” function on route changes.
2. Populate Forms
Push UTM values through forms into automation tools
Consistent hidden fields make sure values reach your MA/CRM even when the query string is gone.
| Platform | How to capture | Field setup notes |
|---|---|---|
| HubSpot | Add hidden UTM fields in forms; HubSpot can also track Original/Latest Source | Create “First UTM *” and “Last UTM *” properties. Use workflows to set First only if empty. |
| Marketo | Marketo Forms hidden fields: “Get Value from URL Parameter” or from cookie/script | Map fields to Lead. Sync Program ↔ Salesforce Campaign for touch attachment. |
| Salesforce Web-to-Lead | Include hidden inputs; map to custom Lead fields | Map Lead → Contact on conversion. Lock “First” via Validation Rule or Flow. |
| Pardot (Account Engagement) | Hidden fields prefilled from query string | Sync to Salesforce Campaigns. Use custom fields for each UTM component. |
3. Store in CRM
Before you can store UTM values in your CRM, work on designing a CRM schema that preserves first and last touch.
Create a lean, durable schema so UTMs survive conversion and support revenue reporting. Although this will largely depend on your CRM, here are some hints.
| Object | Fields to add | Update rule | Purpose |
|---|---|---|---|
| Lead | First and Last UTM Source/Medium/Campaign/Term/Content; Landing Page URL; Form Name; Timestamps | First = write-once; Last = update on each qualifying form | Preserve first- and last-touch at lead creation |
| Contact | Same as Lead (mapped via conversion) | First = do not overwrite; Last = refresh on net-new conversions | Maintain lifecycle continuity |
| Opportunity/Deal | Primary Campaign Source or Deal Source fields | Set at deal creation; inherit from Contact/Lead or Campaign | Tie pipeline and revenue to campaigns |
| Campaign Member (optional) | UTM fields snapshot | Update on each new membership | Keep per-touch history without overwriting Lead/Contact |
utm_campaign, utm_medium, or utm_content values. Use dedicated UTM fields and write-once logic to keep precise, stable values.4. Preserve History
Keep first-touch write-once and last-touch refreshable
This one is quite tricky. There’re different ways to preserve history of UTMs. However, focusing on First and Last touch only can be quite rewarding. This split gives the marketing team “sourcing and in-quarter” performance without a full multi-touch build.
| Touch type | What to store | When to set | Who uses it |
|---|---|---|---|
| First-touch | The very first UTMs seen for the person | On first known session or first form submit | Marketing leadership (sourcing) |
| Last-touch (conversion) | UTMs at the moment of lead gen or key conversion | Every time a lead-qualifying form is submitted | Demand gen and ops |
utm_source=event) while last-touch for MQLs skews to retargeting (utm_medium=paid_social). Both get funding.5. Connect to Revenue
Carry UTMs into Campaigns and Opportunities for revenue attribution
Campaign alignment
- Create Campaigns that match your
utm_campaigntaxonomy. Add members on form submits or key engagements. - In Salesforce, set Opportunity Primary Campaign Source at creation (via Flow or Campaign Influence settings).
Deal association
- When a new Opportunity is created from a Contact, inherit the Contact’s First/Last UTM or the associated Campaign values.
- Lock the inherited values so the deal’s sourcing stays stable.
6. Report outcomes
Here is a reporting starter table with fields and groupings. Again, this might change based on your CRM and your specific setup
| Report need | Example CRM fields | Example filter/group |
|---|---|---|
| Leads by campaign | Lead.Last UTM Campaign | Group by campaign; filter Created Date = last 30 days |
| Opportunities by first-touch source | Opportunity.Primary Campaign Source or Contact.First UTM Source | Group by Source; Stage ≠Closed |
| Revenue by campaign | Closed Won Amount + Opportunity.Primary Campaign Source | Group by Campaign; sum Amount |
Other strategies that can help
Use native CRM/MA features and data pipes to reduce drift
- Salesforce: Custom fields, Lead mapping, Campaigns, Primary Campaign Source, and Flow for write-once/lock rules.
- HubSpot: Original/Latest Source for buckets plus custom UTM properties; workflows to set first/last.
- Marketo: Hidden form fields; Program ↔ Salesforce Campaign sync.
- Pardot: Form hidden fields; Campaign sync.
- Tag Manager: Centralize capture and cookie logic across properties.
- CDPs / Reverse ETL (Segment, Hightouch, Census): Standardize UTMs across tools and backfill CRM fields.
- Webhooks: Post form submissions with UTMs to MA/CRM in real time.
Make fast calls on scope, TTL, overwrite rules, and fields
- Pages to capture: All marketing pages with any form; include product signup pages.
- Cookie TTL: 90–180 days for long B2B cycles.
- Overwrite rules: First-touch = write-once; Last-touch = update on every new qualifying form.
- Fields to store: At minimum source, medium, campaign. Add term/content only if used in your programs.
Fix common breakpoints that drop UTM data
- Missing UTMs in CRM: Confirm hidden inputs exist and match CRM field API names. Check if the form library strips empty fields.
- First-touch getting overwritten: Add workflow/Flow condition “set only if empty.” Route new values to Last-touch.
- Subdomain issues: Set cookies for the parent domain (for example, .example.com) so data persists across app.example.com and www.example.com.
- SPA frameworks: Fire input population on route changes, not only on DOMContentLoaded.
Snapshot UTMs on Campaign Member to keep a per-touch history
Add custom UTM fields to Campaign Member and populate them each time someone becomes a member. This gives you:
- A durable, per-touch audit trail without overwriting Lead/Contact fields.
- The ability to analyze which
utm_medium+utm_campaigncombinations speed stage movement.
utm_medium=event) and “G2 retargeting” (utm_medium=paid_social) moved from Stage 2 to Stage 4 30% faster, which justified shifting budget to those touches.Five Step QA
Run a five-step QA to prove data flows end-to-end
| Step | Action | Expected result |
|---|---|---|
| 1 | Click a test URL with UTMs to a landing page | Cookies set for first_utm_* and last_utm_* |
| 2 | Submit a form with hidden fields | Form payload contains first_utm_* and last_utm_* |
| 3 | Verify CRM Lead/Contact | Fields populated; First-touch locked; Last-touch set |
| 4 | Convert to Opportunity | Opportunity inherits Campaign/Source at creation |
| 5 | Create report | Leads/Opportunities grouped by UTM fields refresh without export |
- Open a private browser window.
- Visit your test URL with UTMs (for example:
https://example.com/?utm_source=linkedin&utm_medium=paid_social&utm_campaign=q1-threat-report). - In DevTools > Console, run:
document.cookieto confirm first_utm_* and last_utm_* exist. - Submit a form that has hidden inputs named first_utm_source…last_utm_campaign. In the network tab, inspect the request payload and verify values were posted.
- Reload the page without UTMs and confirm the hidden inputs still populate from cookies.
Test your knowledge
Loading quiz questions...