Tracking UTM parameters in Salesforce Web-to-Lead Forms
UTM tracking usually looks simple on paper: add `utm_source`, `utm_medium`, `utm_campaign`, and you are done. Then the first Web-to-Lead submissions hit Salesforce and the values are missing, overwritten, or dumped into a Notes field nobody reports on.
The root issue is that Salesforce Web-to-Lead is intentionally minimal. It will accept only the fields you pass, it will not magically capture querystring parameters for you, and it has a few behaviors that surprise even experienced admins. Once you know those constraints, you can reliably persist UTMs into Lead fields and keep attribution intact from click to conversion.
Why UTMs get lost in standard Web-to-Lead setups
Web-to-Lead is a lightweight HTML form post into Salesforce. Salesforce provides a generator for the HTML and documents the feature as a straightforward way to create Lead records from your website via a form submission Salesforce’s Web-to-Lead setup guidance.
That simplicity is exactly why UTMs often disappear:
- UTMs live in the landing page URL, not the form post. If you do not explicitly move them into form fields, Salesforce never sees them.
- Hidden fields do not populate themselves. A hidden “ is just an empty container unless your page scripts fill it.
- Attribution often gets squeezed into a single “Lead Source” picklist. That helps sales routing, but it is not detailed campaign reporting.
A good mental model: Salesforce only receives what your browser sends in the POST body. UTMs are query parameters unless you copy them into that POST.
Decide where UTMs should live in Salesforce (before touching the form)
You have two common patterns:
Option 1: Create dedicated Lead fields for each UTM parameter
This gives clean reporting and keeps each UTM atomic:
- UTM Source
- UTM Medium
- UTM Campaign
- UTM Term
- UTM Content
Salesforce Leads are designed for early-stage prospect tracking and qualification, and the platform’s Lead workflow is built around capturing and updating information as prospects progress Trailhead’s overview of tracking prospects with Salesforce Leads. UTMs fit naturally into that “capture early, enrich later” approach.
Option 2: Map UTMs into existing fields (only if you must)
Some teams try to squeeze UTMs into:
- Lead Source (picklist)
- Description
- A single “Campaign” text field
This is workable in a pinch, but it tends to degrade reporting. Lead Source is usually a controlled vocabulary (Web, Partner, Referral, etc.). UTMs are granular and messy by design.
Add UTM fields to the Web-to-Lead form (the part Salesforce will actually accept)
Once you have Lead fields, you must include them in the HTML. Salesforce Web-to-Lead supports passing values for fields that exist on the Lead object, including hidden inputs, as long as you use the correct field name/id mapping.
A practical gotcha: you cannot rely on “standard hidden fields” magically existing for tracking. For example, “Default Lead Source” is not a special hidden input you can drop in without explicitly handling it. The behavior is discussed by practitioners working with Web-to-Lead and Lead Source defaults in this StackExchange thread about default Lead Source and hidden fields.
Capture UTMs from the landing page URL and write them into hidden inputs
This is where most implementations fail: the HTML has hidden fields, but nothing populates them.
A typical approach is:
- Read the current page URL querystring.
- Extract `utm_source`, `utm_medium`, `utm_campaign`, etc.
- Write those values into hidden inputs that Salesforce will receive on submit.
GA Connector’s implementation notes walk through this exact pattern for Web-to-Lead and show how to persist UTMs into Salesforce by combining hidden fields and client-side scripting in their step-by-step guide to tracking UTM parameters in Salesforce Web-to-Lead forms.
Two practical tips that save debugging time:
- URL decode values before storing them (spaces, plus signs, and encoded characters show up constantly).
- Persist UTMs beyond the first pageview if your lead form is not on the landing page (for example, store UTMs in a first-party cookie or `localStorage`, then populate the form later).
Preserve attribution across multi-step forms and internal redirects
If your flow is “Landing page -> Pricing -> Contact us,” UTMs may vanish by the time the visitor hits the form.
The fix is not Salesforce-specific. It is web plumbing:
- Store UTMs at session entry.
- Reapply them to the form at submission time.
Many teams also store:
- First touch UTMs (initial acquisition)
- Last touch UTMs (conversion session)
If you only store the last URL’s UTMs, you will misattribute leads that return via branded search or direct traffic before converting.
Don’t confuse “where the lead came from” with “how the lead was created”
A recurring Salesforce reporting confusion: people see “Web” and assume Web-to-Lead created it.
In Salesforce, you can distinguish how a Lead record was created using metadata fields. A commonly used method is checking the standard `CreatedById` and related audit information, as discussed by Salesforce practitioners troubleshooting how to tell whether a Lead was created via Web-to-Lead or API in this StackExchange explanation of differentiating Web-to-Lead vs API-created Leads.
This matters for UTMs because:
- UTMs should reflect marketing acquisition.
- “Created by Web-to-Lead” is an operational detail about ingestion.
Treat them separately in your data model.
Control picklists and field types so Salesforce doesn’t reject your UTM values
UTM values are usually freeform strings. If you try to push them into a restricted picklist, Salesforce can reject the value or ignore it depending on your configuration.
This shows up when teams decide to map `utm_source` into a Lead picklist field for normalization. You can do it, but you must ensure the inbound values match picklist options, or you need a translation layer (JavaScript mapping on the page, or downstream automation). The pitfalls and constraints of passing values into Lead picklists via Web-to-Lead are discussed by admins and developers in this StackExchange thread about Web-to-Lead and picklist values.
Practical recommendation:
- Store raw UTMs in text fields.
- If you need normalized dimensions, create separate normalized fields (or map later with automation).
Assign the right owner and related record fields without breaking tracking
UTM capture often ships alongside routing work: “Send paid social leads to SDR queue A.” Web-to-Lead can pass additional hidden fields, but some values cannot be dynamically discovered by Salesforce without extra logic.
Two common requirements:
Setting a default Lead owner
If you want Web-to-Lead submissions to land with a specific user or queue, you need to set it correctly in the form or via routing logic. Real-world constraints and approaches are discussed in this Web-to-Lead owner assignment thread about default owner behavior for Web-to-Lead.
Passing relationship fields (when you are doing Lead-to-Account associations)
Some orgs attempt to attach Leads to existing Accounts or set relationship fields via Web-to-Lead hidden inputs. That gets tricky quickly and can collide with attribution work if you start overloading hidden inputs. The limitations and considerations come up in this thread on using hidden form fields for Lead-to-Account relationships in Web-to-Lead.
The practical lesson: keep the form payload clean. UTMs, contact details, and a small set of routing inputs are fine. Anything more complex is usually better handled after capture.
Validate the data end-to-end (browser -> form post -> Salesforce Lead)
When UTMs “don’t work,” it is usually one of these:
- The page URL has UTMs, but your script never writes them into inputs.
- The inputs have values, but the `name` attributes do not match Salesforce’s expected field names.
- The field exists in Salesforce, but it is not on the Lead object (or you mapped the wrong field).
- The value violates field type constraints (picklist restriction, length, validation rules).
A simple, reliable testing workflow:
- Load your landing page with a full UTM string.
- Inspect the hidden inputs in the DOM and confirm they are populated.
- Submit a test lead.
- Open the created Lead and verify UTMs landed in the intended fields.
If you also need to debug “why did this lead route differently,” separate the concerns:
- UTMs (marketing attribution)
- Lead source defaulting rules
- Owner assignment rules
- Record creation method
That separation keeps you from “fixing” UTM tracking by hardcoding Lead Source or routing fields in ways that break reporting later.






