Every offline conversion upload, every enhanced conversion for leads, every "which keyword closed this deal" report rides on one fragile URL parameter surviving the trip from ad click to CRM. When the gclid dies, Google Ads optimizes on guesses. And the leak is almost never where people first look.
What is the gclid and why does everything break without it?
The gclid (Google Click Identifier) is a unique ID Google appends to your landing page URL on every ad click when auto-tagging is on, and it's the key that ties a real-world outcome back to the exact click. Offline conversion uploads need it. CRM lead imports need it. And Google only accepts uploads within 90 days of the click, so persistence matters as much as capture. No gclid stored, no attribution. Binary.
Is auto-tagging actually turned on?
Check this first, it's a 30-second fix. In Google Ads: Admin, then Account settings, confirm Auto-tagging is enabled. If someone turned it off years ago "because the URLs looked ugly," every click since has arrived naked.
Two related traps:
- Manual UTM overrides. GA4 has a setting that lets manual tagging (UTM values) override auto-tagging. If an agency stacked utm_ parameters on final URLs and flipped that override, GA4 attribution shifts even while the gclid still rides the URL.
- Tracking templates. A misconfigured tracking template or final URL suffix can route clicks through a third-party tracker that rebuilds the URL and drops the gclid. Click one real ad and check the address bar on arrival.
- Ad click — Auto-tagging appends gclid to the URL
- Redirect chain — https, www and geo hops drop $args
- Landing page — replaceState scrubs the query string
- Lead form — No hidden field, so the CRM gets none
- Captured on landing — Persisted 90 days, written to records
Are redirects stripping your gclid?
Redirect chains are the number one silent killer I find in audits. Every hop is a chance for the query string to get dropped. The usual suspects:
- http to https upgrades that redirect to a hardcoded URL without parameters
- non-www to www (or the reverse) rewrites
- geo or language redirects (example.com to example.com/en/)
- vanity URLs, short links, and affiliate hops that rebuild the destination URL
Test it yourself in a terminal:
curl -sIL "https://example.com/landing?gclid=TEST123" | grep -i "^location"
The -I flag asks for headers only, -L follows redirects, and each location: line shows where you got bounced next. If gclid=TEST123 appears in the first location header but vanishes in the second, you've found the hop that's eating it. The fix is server config: make every redirect rule pass the query string through (in nginx that's appending $args, in Apache the QSA flag). Show your developer which hop drops it and they'll know what to do.
Can my own landing page or consent tool eat the parameter?
Yes. This layer is sneakier because the URL arrives intact and the parameter dies on the page. Four ways it happens:
Client-side URL rewrites. Some frameworks and "clean URL" plugins call history.replaceState on load and scrub query parameters for cosmetics or canonicalization. The gclid exists for a few hundred milliseconds, then it's gone.
Consent tools deferring scripts. Under Consent Mode v2, plenty of setups hold all tags until the visitor accepts. Fine. But if gclid capture lives inside a deferred tag and the visitor hits page two before accepting, the parameter's page is long gone when the script wakes up.
SPAs swallowing the landing URL. Single-page apps often boot, take over routing, and normalize the URL before your tag manager fires anything. Same race, different cause.
WAFs and security rules. Web application firewalls and bot-protection rules sometimes flag long parameterized URLs and serve a challenge page or a stripped redirect. If gclid clicks convert at zero while direct traffic is fine, check the WAF logs.
Why doesn't the gclid reach my CRM?
Because nobody wrote it there. The most common gap of all: the gclid survives to the page, then the lead form submits name, email, phone, and nothing else. The click ID has to travel inside the form as a hidden field, or your CRM records have no key for offline conversion uploads. Most form builders (Gravity Forms, HubSpot, Elementor, ClickFunnels, GoHighLevel) support hidden fields populated from a cookie or URL parameter. No gclid column in your CRM today? That's the smoking gun.
| Layer | What sits there |
|---|---|
| Inputs | gclid, wbraid and gbraid (iOS), fbclid, msclkid, ttclid |
| Capture, persist, write | Read the landing URL before rewrites, store 90 days first-party, stamp every record |
| Destinations | Hidden form fields, CRM contact properties, Google offline conversions, Enhanced conversions for leads, Meta CAPI |
What does a bulletproof click-ID setup look like?
Stop treating the gclid as URL decoration. Treat it as data you capture once and own. Three moves:
- Capture on first touch. A tiny first-party script (or better, a server-set cookie, more below) reads the landing URL the instant the page loads, before rewrites, before the SPA router, before anything else.
- Persist for 90 days. A first-party cookie on your own domain with a 90-day lifetime, matching Google's upload window, refreshed on every pageview.
- Write it into every record. Hidden form fields, CRM contact properties, order metadata. Every conversion record gets the click ID stamped at creation time.
Two extensions make this future-proof. wbraid and gbraid: on iOS traffic affected by Apple's App Tracking Transparency, Google often sends wbraid (web) or gbraid (web-to-app) instead of a gclid, so a script that only looks for gclid is blind on a big slice of mobile. Grab all three. And the same pattern covers msclkid (Microsoft Ads), fbclid (Meta), and ttclid (TikTok). One capture-persist-write pipeline handles every platform.
Do I need first-party server-side tracking for this?
If you want the fix to survive browser privacy changes, yes. Plain-language version for anyone new to the term: instead of relying only on JavaScript in the visitor's browser (which ad blockers kill and Safari restricts), you run a small tagging server on your own subdomain, like track.yourdomain.com. The browser makes one first-party call to it, and your server talks to Google Ads, GA4, and Meta from there.
For the gclid problem specifically, that changes four things. The cookie holding your click ID gets set server-side in an HTTP response, so Safari's ITP doesn't cap it at 7 days the way it does JavaScript-written cookies; your 90-day persistence actually holds. Ad blockers that eat gtag.js never get a shot at your capture, because the request goes to your own domain, not a blocklisted third party. The server becomes one source of truth: the same stored click ID feeds Google offline conversions, enhanced conversions for leads, and Meta CAPI with consistent values and proper deduplication, instead of three scripts racing on the page. And consent stays enforceable in one place, because the server forwards data per the visitor's consent state. Client-side capture is a patch. First-party server-side capture is the actual fix, and it's exactly what we build.
- Open ?gclid=TEST123 in incognito — Confirm the parameter is still in the address bar when the page finishes loading
- Trace the redirects — curl -sIL the ad URL and find the hop where gclid=TEST123 disappears
- Check the first-party cookie — DevTools, Application, Cookies: your cookie should hold TEST123 after load
- Browse two more pages — The stored value has to survive navigation, not just the landing page
- Submit a test lead — Check the form payload in the Network tab for the hidden click-ID field
- Open the CRM record — TEST123 in the click-ID field, then repeat on an iPhone to catch wbraid
How do I test the whole thing end to end?
- Open your landing URL with
?gclid=TEST123in a fresh incognito window. - Confirm the parameter is in the address bar on arrival. If not, run the curl test above.
- In DevTools, Application tab, Cookies, confirm your first-party cookie holds TEST123.
- Navigate to a second page, then a third. Cookie still there? Good.
- Submit a test lead and check the form payload in the Network tab for the hidden field.
- Open the record in your CRM. TEST123 should be in the click-ID field.
- Repeat on an iPhone with Safari and confirm a wbraid click gets captured too.
Fifteen minutes, and you know exactly which link in the chain is broken.
Frequently asked questions
Why is gclid not showing in my URL?
Either auto-tagging is disabled in your Google Ads account settings, or a redirect between the ad and your landing page is stripping the query string. Check the setting first, then trace the redirect chain with curl -sIL.
How long is a gclid valid for offline conversion uploads?
Google Ads accepts conversion uploads for up to 90 days after the click, which is why you persist the captured gclid in a first-party cookie for 90 days, not just the session.
What is wbraid and why am I seeing it instead of gclid?
wbraid is Google's privacy-preserving click identifier for iOS traffic affected by Apple's App Tracking Transparency (gbraid covers web-to-app). Capture and store it exactly like a gclid; Google accepts it for conversion uploads.
Can a consent banner block the gclid?
The banner doesn't touch the URL, but if your capture script is deferred until consent and the visitor navigates away first, the parameter is lost. Capture the landing URL at page load and gate the data-sharing, not the capture.
How do I pass gclid into my CRM?
Store it in a first-party cookie on landing, then populate a hidden field in every lead form from that cookie. Server-side setups can also stamp it onto the record via webhook or API.
Does the same fix work for fbclid and msclkid?
Yes. fbclid (Meta), msclkid (Microsoft Ads), and ttclid (TikTok) follow the identical capture-persist-write pattern, and the same redirect leaks kill them too.
- gclid
- click id
- attribution
- fix it

