Tracking & Attribution

Why Is gclid Missing on My Landing Pages?

gclid missing from your landing pages? The four real causes — auto-tagging off, redirects, browser stripping, iOS gbraid — and how to fix each.

Quick answer

gclid is missing from your landing page for one of four reasons: auto-tagging is off in Google Ads, a redirect dropped the query string before your page loaded, the browser stripped the parameter, or the click was an iOS click that carried gbraid or wbraid instead. Only the first is a setting you flip. The rest are plumbing. Check the first document request in DevTools with "Preserve log" on: if the click ID was never there, it is an account or browser problem; if it was there and vanished at a 30x hop, it is a redirect problem.

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

gclid is missing from your landing page URL for one of four reasons: auto-tagging is off in Google Ads, a redirect dropped the query string, the browser stripped the parameter, or the click was an iOS click that got gbraid or wbraid instead. Only the first is a setting. The other three are plumbing, and each has a different fix.

Work them in that order. Most people start by rewriting the tracking template, which is almost never it.

What is gclid, and what is supposed to put it there?

gclid — Google Click Identifier — is an opaque string Google Ads appends to your final URL when someone clicks your ad. Auto-tagging is the account-level setting that appends it. It is the only deterministic link between a specific ad click and everything that happens on your site afterwards.

It is not a UTM. UTMs are strings you write; gclid is issued by Google and only Google can decode it. That matters when it goes missing, because you can regenerate a UTM by hand and you cannot regenerate a click ID. If the distinction is still fuzzy, gclid vs fbclid vs UTM parameters covers what each one is for.

Why is gclid missing from my landing page URL?

Four causes account for nearly every case. They fail in different places — the ad account, your server, the browser, and the click itself — which is why one blanket “fix” rarely works.

Dark dashboard-style diagram of where a Google Ads click ID is lost: ad click, redirect chain, browser stripping, page rewrite, iframe, stored session

Is auto-tagging turned off in Google Ads?

Auto-tagging is a per-account checkbox. If it is off, Google Ads never appends the click ID and there is nothing to lose downstream. Turn it on and it applies to clicks from that point forward — it is not retroactive, so yesterday’s leads stay click-less forever.

The trap: a manager account can hold a different setting from the child account that owns the campaign. Check the one that owns the campaign.

Is a redirect dropping the query string?

This is the most common cause on real sites. A 301 or 302 that rebuilds the destination URL from a template — rather than passing the original query string through — discards ?gclid=… in the process. The usual suspects: http://https:// upgrades, www. → apex canonicalisation, trailing-slash normalisation, language or country redirects, a CMS “pretty URL” rule, a page-builder’s domain-level redirect, or a link shortener sitting in front of your landing page.

Chains of three hops are normal, and the parameter only has to be dropped once.

Is the browser stripping the parameter?

Several browsers now remove known click-tracking parameters from URLs before the page loads, in specific modes — strict tracking-protection settings and private browsing being the usual ones. Content blockers do the same with “remove URL parameter” rules. The effect is identical to a bad redirect: the request arrives without a click ID, and nothing in your stack ever sees one.

Was there ever a gclid, or was it gbraid or wbraid?

On iOS traffic where the user is not identifiable, Google issues gbraid or wbraid instead of gclid. Your landing page URL is not empty — it has a different parameter than the one your code is looking for. If your capture logic reads gclid and nothing else, that traffic looks untracked when it is fully tracked.

This is not a bug to fix, it is a parameter to add: capturing gbraid and wbraid covers storing them and using them for offline conversion import. If a big slice of your paid traffic is iOS, work through how to audit your iOS attribution gap first.

Did your own page erase it after loading?

The URL arrives intact and something on the page rewrites it. Single-page-app routers call history.replaceState on the first route resolution. Cookie banners reload the page. Consent tools bounce the visitor through a consent domain and back. The tell is an address bar that changes on its own a moment after load — and anything reading the URL after that point, including a tag that loads late, gets the rewritten version.

Did it die at an iframe or a subdomain boundary?

An embedded form is a separate document with its own URL. A Typeform, Jotform or GoHighLevel widget never sees your query string — it was loaded from the form platform’s domain with the form platform’s parameters. Same story when the form lives on a subdomain or a second domain and nothing forwards the click ID across.

How do you tell which cause you have?

Open DevTools, tick Preserve log in the Network tab, click your own ad, and read the first document request. That single step separates all four causes:

  1. Never there on the first request → auto-tagging, tracking template, or browser stripping. Retest in a clean profile to split the last one out.
  2. There, then gone after a 30x → redirect. Read each hop’s Location header; the hop whose Location has no ? is your culprit.
  3. Survives every hop but your tag has nothing → a page-side rewrite, or a tag that initialises too late. Log location.search from the first inline script and compare.
  4. gbraid or wbraid where you expected gclid → iOS traffic, working as designed.

Use a real click, not the final URL pasted into the address bar — pasting skips the redirect behaviour you are trying to observe.

What does a missing click ID actually cost you?

Three things, and they compound.

Offline conversion import into Google Ads is keyed on a click ID. With none, the lead that became a sale three weeks later cannot be sent back to the account, so Smart Bidding never learns which clicks were worth buying.

Your reports reclassify the traffic. A session with no click ID and no UTM falls back to referrer, which is a large part of why ad conversions show as Direct in tools that only look at the converting session.

And the journey breaks. Someone clicks on a phone at lunch and buys on a laptop that evening; with no click ID in a durable record from the first visit, there is nothing to stitch the two together — the problem covered in tracking leads across devices. Booking businesses feel it hardest, since the outcome lands in a calendar tool days later: tracking booked appointments to Google and Meta Ads is the same problem with a longer gap.

What can you fix yourself, without any vendor?

All of it is fixable, with honest limits on each.

Turn auto-tagging on. One checkbox, and it applies going forward only — it does not affect clicks that already happened.

Make every redirect query-preserving. In Apache, QSA on the rewrite rule. In Nginx, append $is_args$args to the target. In Cloudflare Rules, tick preserve query string. In a page builder, check whether the domain redirect is configurable at all — often it is not, and that is the limit: you cannot fix a redirect you do not own.

Read the click ID once, immediately, and store it yourself. Before a router or a consent banner can rewrite anything:

// First inline script on the page, not the last.
const params = new URLSearchParams(location.search);
for (const key of ['gclid', 'gbraid', 'wbraid', 'gad_source']) {
  const value = params.get(key);
  if (!value) continue;
  try { localStorage.setItem('pl_' + key, value); }
  catch (e) { /* private mode or blocked storage */ }
}

The limit: browser storage is the weak link. Script-written cookies are capped on Safari, localStorage gets cleared, and private windows may refuse the write. Reading early solves the page-rewrite case, not the storage-lifetime case.

Store all three click IDs, and store which one you got rather than normalising gclid, gbraid and wbraid into one column — they are not interchangeable across Google’s surfaces.

Forward the click ID across boundaries yourself. Append it to the iframe src, or postMessage it into the frame and have the embedded form read it. It works, and it is brittle — every form vendor exposes a different hook, and they change.

How does PartialLeads keep the click ID from going missing?

PartialLeads reads the click ID out of the landing URL on the session’s first capture payload and stores it server-side — not in a browser cookie that later gets capped or cleared. gclid, gbraid, wbraid and gad_source are all captured, alongside fbclid, msclkid, ttclid and epik, plus the landing page and referrer.

Server-side storage is what defeats the page-rewrite case: once the value is posted, it does not matter that a router rewrote the address bar a half-second later, or that a consent banner reloaded the page. For the iframe case, the tag listens for postMessage attribution from parent frames and broadcasts UTMs down into embedded frames, with document.referrer as the fallback — that is what keeps a GoHighLevel or Typeform embed from producing a source-less lead.

Return visits stay attached because the visitor ID is a server-set first-party cookie, not subject to the seven-day cap Safari applies to cookies written by JavaScript. And when a conversion session genuinely has no click ID, two mechanisms can still resolve it: the click ID is one of the six tiers in the identity cluster, so sessions sharing a gclid are unioned into one person; and visit-sibling inheritance lets a session with no attribution inherit strong attribution from a sibling session in the same visit — same client, IP and user agent within ±30 minutes, with a cellular-handoff tier that allows the IP to change for a phone moving from wifi to LTE mid-checkout. A production example: a Shopify purchase session that read “Direct” was flipped to Google Ads because the buyer’s earlier same-visit session carried the gclid.

Then the conversion goes back: matched purchases and qualified leads are exported for Google Ads offline conversions with the click ID plus hashed email and phone — E.164 normalisation with a geo fallback, Gmail dot and plus-address normalisation before hashing.

PartialLeads Leads list with journey ribbons above a Recovered Attribution card showing ad-click rescue and reclassified sessions

Where you see it working: the Leads list shows each lead’s source and journey as a row of touch badges, so a lead that arrived on a Google Ads click reads that way at list resolution. The Attribution report’s Recovered Attribution card itemises what a raw last-click view would have lost, by mechanism — iOS ad-click rescue, where a first touch is re-linked to a lost ad click, and sessions reclassified by session intelligence, typically the largest bucket and mostly traffic that would otherwise read as Direct.

The honest limits. If auto-tagging never ran, no vendor recovers the click ID — it was never issued. If a server-side redirect dropped the query string before your landing page was requested, the tag never sees it either, because the tag runs on the page the browser actually loaded; that one you fix on your server. And sibling inheritance is an inference from your own session data, not a join Google has confirmed.

What breaks The mechanism Where you see it in the dashboard
A router, consent banner or SPA rewrites the URL after load Click ID read on the session’s first capture payload, stored server-side Lead’s source and UTM columns
Form is an iframe with no query string postMessage attribution relay into the frame, plus referrer fallback Source label on the lead
Conversion session reads Direct although an earlier session had the gclid Visit-sibling inheritance, ±30 min, plus the cellular-handoff tier; server-set visitor cookie keeps return visits stitched Recovered Attribution → reclassified by session intelligence
iOS click issued gbraid or wbraid, not gclid All click IDs stored per session, each under its own key Recovered Attribution → iOS ad-click rescue
The lead never gets back into Google Ads Offline conversion export: click ID plus hashed email and phone Google Sheets dispatch, per-lead API column
A server-side redirect stripped it before your page loaded None — nothing captures what the browser never received Not applicable: this one is on your server

Frequently asked questions

QDoes turning on auto-tagging break my UTM parameters?
No. Auto-tagging appends gclid to the final URL; it does not remove or overwrite UTMs you have set. The two coexist in the same query string. The real risk is a landing page or redirect that rebuilds the URL and keeps only the parameters it recognises — that breaks both, and it was already broken before you touched auto-tagging.
QIs gclid the same thing as gbraid or wbraid?
No. They are separate click identifiers Google issues in different circumstances — gbraid and wbraid appear on iOS traffic where the user is not identifiable, in place of gclid. Capture all three and store which one you received. They are not interchangeable across every Google surface, so normalising them into a single column loses information you may need later.
QCan I recover a gclid after the fact?
Not the parameter itself. If it was never issued, or was stripped before your server saw the request, it does not exist anywhere you can reach. What you can recover is the attribution: if any session belonging to that person carried the click ID, session stitching can attach the conversion to it. That is an inference from your own data, not a value Google hands back.
QDo ad blockers and browsers remove gclid?
Some do, in specific modes. Strict tracking-protection settings, private browsing, and content blockers with URL-parameter rules can remove known click-tracking parameters before the page loads. Test the same ad click in a clean browser profile with default settings; if the click ID survives there and disappears in your everyday browser, that is your answer.
QShould I add ?gclid={gclid} manually in the final URL suffix?
Usually no. Auto-tagging already does it, and a manual copy can produce two conflicting values in one URL. It also does not help with your actual problem if a redirect is dropping the query string, because a manually added parameter is dropped by exactly the same rule. Fix the redirect first, then decide whether you still need it.
QHow long can I wait before uploading an offline conversion?
Google enforces a maximum click age for offline conversion import, and it has changed over time. Confirm the current window in Google's documentation before you design a backfill, rather than assuming the number you remember still holds. Either way, the practical rule is to upload continuously, not in monthly batches, so nothing ages out while it waits.
QDoes PartialLeads work if auto-tagging is off?
Partly, and it is worth being straight about it. Capture, identity stitching, purchase matching and lead qualification all work regardless. Click-ID-based offline import into Google Ads does not, because there is no click ID to send. Turn auto-tagging on first; nothing downstream can invent a parameter your ad account never generated.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.