How Do You Track Which Ad a Lead Came From?
To track which ad a lead came from, tag each ad's destination URL with UTM parameters, keep those values when the visitor submits a form, and store them on the lead record. Then the lead itself shows the campaign and ad. Tools like Trakt remember the UTMs in the same browser and record each form submission with them.
- Tag your ad links with UTMs. Every ad that drives traffic to your site carries
utm_source,utm_medium,utm_campaign,utm_content, and optionallyutm_term. - Capture the UTMs at the form level. Hidden fields read the UTM values from the URL when the page loads and submit them silently with the form.
- Store the UTMs in the lead record. Map the hidden fields to custom CRM properties so the values stay with the contact through the funnel.
- Persist the UTMs across multi-page journeys. A first-party cookie keeps the values available when the form isn't on the page the visitor landed on.
The ad-to-lead chain, in four steps
A tagged ad URL is read by hidden form fields, CRM lead properties store the UTMs, and a first-party cookie carries them across pages.
If the CRM lead is missing its source, one of those links is broken, so the fastest fix is to find which one rather than rebuild everything.
Where Does the Ad Trail Break?
Each step has one common way of failing. Find the one that matches what you see in your CRM:
| Step | What goes wrong | What you see |
|---|---|---|
| 1. Tag ad links | Inconsistent UTM naming (LinkedIn, linkedin, li) | The same source split across several values |
| 2. Capture at the form | No hidden fields on the form, the step most teams skip | CRM leads with no source data |
| 3. Store in the CRM | UTM fields never created or mapped | Values submitted but missing on the lead record |
| 4. Persist across pages | The form is on a page with no UTMs in its URL | Blank source after a multi-page visit |
Why Ad Platform Pixels Don't Match Your CRM Leads
Ad platforms tell you how many clicks your ads got. They'll also report conversions, if you install their pixel and define a conversion event.
The problem with pixel-based conversion tracking is that it lives in the ad platform's system, uses the ad platform's attribution model, and counts in the ad platform's favor. It isn't the same thing as a lead in your CRM, it doesn't tell you whether that lead became a customer, and when you compare it to your CRM data the numbers almost never match.
UTM-based tracking works differently. You tag your ad URLs, capture the parameters at the form, and store them in the lead record, so the record itself says "I came from this campaign."
How to Track Form Submissions by Source, Step by Step
Step 1: Tag your ad links with UTMs
Every ad that drives traffic to your site should have UTM parameters on the destination URL. The five parameters:
utm_source: the platform (google, facebook, linkedin, tiktok)utm_medium: the channel type (cpc, paid-social, email)utm_campaign: the campaign name (q2-enterprise-retarget, product-launch-may)utm_content: the specific ad or creative (cta-demo, image-v2, carousel-a)utm_term: optional, useful for Google Ads keywords (project-management-software)
A well-tagged URL looks like this:
https://yoursite.com/demo?utm_source=linkedin&utm_medium=paid-social&utm_campaign=q2-enterprise-retarget&utm_content=cta-demo
Build your tagged URLs with the Trakt UTM Builder. It keeps your naming conventions consistent, and inconsistent UTM naming (utm_source=LinkedIn vs. linkedin vs. li vs. Linkedin) is one of the most common reasons attribution breaks.
Step 2: Capture UTMs at the form level
Once a visitor lands on your page with UTMs in the URL, those UTMs need to survive the form submission. That requires hidden fields on every form. The hidden fields read the UTM values from the URL when the page loads, then submit them silently alongside the form.
This is the step most teams skip, which is why their CRM leads don't have source data.
Step 3: Store UTMs in the lead record
Your form captures the UTMs. Now they need to land in the right place in your CRM:
- HubSpot: create custom contact properties for each UTM parameter and map the form hidden fields to those properties.
- Salesforce: create custom Lead fields (UTM Source, UTM Medium, and so on) and map them in your form integration or Zapier workflow.
- GoHighLevel: custom fields work the same way. Create them, then map the form fields.
Once the UTM values are in the lead record, they follow the contact through your funnel. When the lead becomes an opportunity, the UTM data is there, and when it closes, you can attribute that revenue.
Step 4: Persist UTMs across multi-page journeys
Here's a scenario that breaks Step 2: your ad sends someone to your homepage. They browse, read a blog post, move to your pricing page, then fill out the contact form. The UTMs were in the URL of the homepage, not the pricing page, so by the time they reach the form there are no UTM parameters left to read.
The fix is a first-party cookie. When a visitor first lands on your site with UTMs in the URL, store those values in a cookie. When any form on your site loads, check for the cookie and pre-populate the hidden fields from it, regardless of which page the form is on.
If you want each submission recorded with its ad source, pre-register for Trakt.
What You Can Answer Once It's Working
Once UTM data is flowing into your CRM, these are the questions you can answer directly from the lead record:
| Question | How to answer it |
|---|---|
| Which campaign generated the most leads this quarter? | Filter contacts by utm_campaign and count them. |
| Which ad creative drives the highest lead-to-close rate? | Filter closed-won deals by utm_content and compare conversion rates by creative variant. |
| Are our Google Ads generating pipeline, or just traffic? | Filter opportunities by utm_source=google and utm_medium=cpc. If the pipeline exists, it shows up. |
| Which channels should we cut? | Sort channels by closed revenue, not lead volume. Channels that drive low-quality leads look worse measured by close rate than by form fills. |
Why Ad Platform and CRM Attribution Never Fully Agree
Your ad platform's attribution and your CRM's attribution will not agree completely, and that's okay. Each ad platform counts conversions by its own rules, and none of those rules reflect what actually happened in your sales process.
CRM-level UTM attribution reflects the actual form submission with the actual campaign tag. It's more conservative, since it doesn't count view-through conversions, but it's also more accurate for understanding what is working. When leadership asks about ROI, the CRM number is the one that matters.
Tracking Ad Source Per Client for Agencies
If you manage paid campaigns for multiple clients, UTM hygiene matters even more. Every client's campaigns should have distinct, consistent UTM values that can't be confused with another client's.
Use a naming convention that includes a client code: utm_campaign=clienta-q2-retarget rather than just q2-retarget. Agree on the convention up front, so whoever builds the links that week uses the same one.
Why Manual UTM Capture Breaks in Practice (And How Trakt Closes the Gap)
The four steps above all work, and each one depends on someone doing the right thing every time. The weak points are predictable:
- Hidden fields get skipped. The setup lives on each form, so a new form or landing page can go live without it.
- Multi-page visits lose the UTMs. Without cookie logic on your site, the source is gone by the time the visitor reaches the form.
- Naming drifts. Different people tag the same source differently, and reports fragment.
How Trakt closes the gap
Trakt stores UTM values in a first-party cookie on first landing and injects them into hidden fields on any form page, even if the visitor has navigated away from the original landing page. Per-client UTM templates can be stored in Trakt's dashboard, so whoever builds the links uses the correct naming convention. It handles the capture and persistence, so leads reach your CRM with their ad source attached. See how Trakt tracks forms.
Manual UTM Capture vs. Trakt, By Requirement
| Requirement | Manual (DIY) | Trakt |
|---|---|---|
| Hidden fields on forms | Added to every form, per form platform | Injected into hidden fields on any form page |
| UTMs across multiple pages | Needs your own cookie and pre-fill logic | First-party cookie set on first landing |
| Naming consistency per client | A convention people have to remember | UTM templates stored per client in the dashboard |
| CRM property setup | Same either way: create the custom UTM fields and map them in HubSpot, Salesforce, or GoHighLevel | Same either way: create the custom UTM fields and map them in HubSpot, Salesforce, or GoHighLevel |
Frequently Asked Questions
How do I track which ad a lead came from?
Tag every ad's destination URL with UTM parameters, capture those parameters in hidden fields on your forms, and map the fields to custom properties in your CRM. The lead record then carries the campaign and ad that produced it. Use utm_content to identify the specific ad or creative.
Do I need a tracking pixel to see which ad drove a lead?
No. A pixel lives in the ad platform's system, uses its attribution model, and rarely matches the leads in your CRM. UTM-based tracking puts the source on the lead record itself, so you don't have to cross-reference ad platform dashboards.
How do I keep UTMs when a visitor browses several pages before filling out a form?
Store the UTM values in a first-party cookie when the visitor first lands on your site. When any form loads, check for the cookie and pre-populate the hidden fields from it, regardless of which page the form is on. Without that, the UTMs stay behind in the URL of the first page.
How do I track form submissions by source in HubSpot, Salesforce, or GoHighLevel?
Create a custom property or field for each UTM parameter, then map the form's hidden fields to them. In HubSpot these are custom contact properties, in Salesforce custom Lead fields, and in GoHighLevel custom fields. Once the values are stored, you can filter contacts and deals by source, campaign, or creative.
How do I track ad source when I run campaigns for multiple clients?
Use a UTM naming convention that includes a client code, such as utm_campaign=clienta-q2-retarget instead of q2-retarget, so one client's campaigns can't be confused with another's. Keep templates per client so everyone who builds links follows the same convention.

