GoHighLevel Lead Source Tracking Guide
Most GHL accounts show leads as "direct" regardless of where they actually came from. Here is how native UTM attribution works and where it silently breaks.

GoHighLevel Lead Source Tracking Guide
The question that ends most attribution conversations badly is simple: "which campaign is actually working?" and the honest answer, on far too many GHL accounts, is that nobody actually knows. Leads come in, contacts get created, and the source field just says "direct" for nearly everything regardless of whether the lead came from a Google ad, an organic search, or a referral. Fixing this is not complicated, but it does require understanding exactly how GHL captures attribution and where that capture quietly breaks.
I set this up as one of the first things on any client account running paid traffic, because campaign spend without reliable attribution is spend nobody can actually optimize. This post covers how GHL's native UTM tracking works, where it breaks, and how to get consistent, usable source data on every contact.
Why Lead Source Tracking Matters
Without reliable attribution, ad spend decisions get made on gut feeling rather than actual performance data. A client spending several thousand dollars a month on Google Ads deserves to know whether those specific leads are converting, not just that leads are arriving from somewhere. Fixing attribution is usually the highest-leverage first step before optimizing anything else in a paid campaign.
Native GHL Source Fields
GHL has built-in URL parameter detection on every GHL-hosted funnel and website page. When a visitor lands with UTM parameters in the URL, GHL reads them, stores them in a session cookie, and on submission maps them into an Attribution panel on the contact record, capturing Session Source, Session Medium, and Session Campaign at both first touch (the very first interaction) and last touch (the interaction immediately before conversion). This native capture works out of the box for GHL-hosted pages with no additional setup required.
UTM Tracking
The five standard UTM parameters, source, medium, campaign, term, and content, need to be present in the URL a visitor actually clicks for any of this to work. GHL's attribution system also follows a defined hierarchy when multiple signals are present, prioritizing specific identifiers like Google or Microsoft click IDs before falling back to referring domain or defaulting to direct traffic if nothing else is detected. Keep UTM values consistent and case-sensitive across your campaigns, matching GHL's expected format, since inconsistent casing or naming between campaigns fragments what should be one clean source category into several different-looking ones in your reporting.
Forms and Landing Pages
For forms hosted directly on GHL funnel pages, enabling UTM Tracking under the form element's settings is what triggers GHL to pull the parameters from the page URL and map them automatically to the contact record on submission. This is the simplest and most reliable capture path, and worth confirming is actually turned on for every form rather than assuming it defaults to enabled.
Tracking Calls
Attribution for phone calls works differently from form-based attribution, since a call does not carry URL parameters the way a form submission does. Call tracking numbers, unique numbers assigned per campaign or channel, are the standard mechanism for attributing calls back to a specific source, letting you distinguish a call that came from a Google Ads landing page versus one that came from an organic listing, even though both eventually reach the same business.
Preserving Source Data
The single most common attribution failure I see is an external landing page, commonly WordPress, embedding a GHL form inside an iframe. The iframe does not automatically inherit the parent page's UTM parameters, so even though the visitor arrived with clean campaign data in the URL, the embedded form submits with nothing, and the resulting contact gets attributed to nothing more specific than direct traffic. If you are running campaigns into external landing pages with an embedded GHL form, the parent page needs to explicitly capture and pass UTM values into the iframe's form URL as hidden fields, rather than assuming the embed handles this automatically.
For leads arriving through a webhook from a source outside GHL entirely, the UTM values need to be mapped manually as part of the webhook payload into the corresponding custom fields, since there is no page URL for GHL to read parameters from in that case.
Reporting by Lead Source
Native UTM custom fields are useful for record-keeping but are not always filterable the way tags are inside Smart Lists. A workflow that fires on contact creation, reads the UTM attribution fields, and applies a corresponding source tag gives you clean, one-click segmentation for reporting without needing to build a filter against several individual UTM fields every time you want to check performance by source.
Common Attribution Mistakes
Assuming UTM tracking is on by default for every form. Check the form settings explicitly rather than assuming, particularly for forms built before this setting existed on the account or copied from an older template.
Embedding forms in an iframe without passing UTM parameters through. This is the single highest-impact fix available on most accounts running any external landing pages, since it silently erases attribution for an entire traffic channel without any visible error.
Inconsistent UTM naming across campaigns. A campaign tagged utm_source=Google and another tagged utm_source=google will show up as two separate sources in reporting rather than one, fragmenting data that should be aggregated together.
Not attributing calls separately from form leads. If your business gets meaningful call volume, tracking numbers matter as much as UTM parameters do for forms, and skipping this leaves an entire channel unattributed.
Once attribution is capturing reliably, it feeds directly into the routing logic covered in GoHighLevel Lead Routing, letting you route leads differently based on source, a paid lead going to a faster-response team versus an organic lead entering a standard nurture sequence.
Setting up clean, reliable attribution across your forms, funnels, and call tracking is exactly the kind of GoHighLevel work I take on for clients. If your reporting currently shows most leads as "direct" regardless of actual source, book a free 30-minute call and bring your current campaign setup, and we will get attribution fixed properly.
Frequently Asked Questions
How do I track lead sources in GoHighLevel?
GHL natively captures UTM parameters on GHL-hosted funnel pages, storing Session Source, Session Medium, and Session Campaign on the contact's Attribution panel at both first touch and last touch, provided UTM Tracking is enabled on the form.
Can GHL track UTM parameters?
Yes, natively for GHL-hosted pages once UTM Tracking is enabled on the form. For external landing pages embedding a GHL form in an iframe, or leads arriving through a webhook, UTM values need to be explicitly passed through rather than captured automatically.
Can GHL track leads from Facebook ads?
Yes, the same way as any other paid channel, through UTM parameters on the ad's destination URL captured by GHL's native attribution, provided the campaign links include properly formatted UTM parameters matching GHL's expected structure.
How do I see where my GHL leads came from?
Check the Attribution panel on an individual contact record for Session Source, Session Medium, and Session Campaign, or build a workflow that tags contacts by source on creation for easier filtering and reporting across your Smart Lists.
Can phone calls be attributed to lead sources?
Yes, using call tracking numbers assigned per campaign or channel, since calls do not carry URL parameters the way form submissions do. Without tracking numbers, calls typically show up as an undifferentiated source in your reporting.
Why is my GHL lead source missing?
Most commonly because the lead came through an iframe-embedded form on an external page that did not pass UTM parameters into the embed, or because UTM Tracking was never enabled on the specific form the lead submitted.
If you would rather have this fixed than fix it yourself, I take on GoHighLevel automation and tracking work through Upwork.

Want this built against your real numbers?
A 30-minute call to scope the workflow, agent, or automation you actually need.
Have a workflow that's burning hours every week?
Bring me one real bottleneck. I'll tell you whether it's worth automating, and what it would take.