pixellint

Vendor · engineers · marketers · PMs

Conversion linker, gclid, then the conversion tag

A conversion tag without the linker is how gclid dies on the landing page. Enhanced conversions without gclid still help, then fail in the ways hashed PII always can.

Linker on every page that can land

Conversion linker writes first-party cookies so gclid (and dclid) survive the hop to thank-you. Put it on all pages, including the landing host. Cross-domain checkout needs linker decoration on the actual navigation, including location.href in JavaScript. A plain linker on click of an a tag will not see that redirect. If you do not preserve log in Network, you only see the landing page; the missing gclid died two hops ago.

Consent Mode still matters: ad_storage, analytics_storage, ad_user_data, ad_personalization. Default denied, then update on choice. A linker that never ran because the CMP blocked storage is how enhanced conversions have nothing to join. A banner div that does not write those signals still fires the conversion tag if you wired it that way. Floodlight on the same page still wants a TC String. Consent Mode is not TCF.

Conversion tag: send_to, once

gtag event conversion with send_to the conversion id and label (AW-123456789/AbC-D_efG). Value and currency if it is a sale. Fire once. SPA thank-you is a dataLayer event, not a URL regex that also matches /checkout. Purchase does not belong on the landing page. The image pixel is a different shape: googleadservices.com (and googleads.g.doubleclick.net) /pagead/conversion/{conversion_id} with label on the query. View-through uses /pagead/viewthroughconversion/. Without label the hit lands on the account rather than a conversion action.

vendor/google-ads-conversion reads conversion_id from the path (numeric), expects label, and warns on guid (generated tag sends ON) and script (image fallback sends 0) when present and wrong. Pack page /packs/google-ads-conversion/. The loader is GTM or gtag; vendor/google-tag-manager checks id on gtm.js / gtag/js. The loader is not the conversion hit.

gtag("event", "conversion", {
  send_to: "AW-123456789/AbC-D_efGhIj",
  value: 19.99,
  currency: "USD",
  transaction_id: "T12345"
});
pixellint validate url @ads-conversion.txt --rulepack vendor/google-ads-conversion

gclid and enhanced conversions

gclid still matters. It is the strong click id. Enhanced conversions add hashed email or phone (SHA-256 of the normalized value: trim, lowercase email, then hash) so Google can match when cookies are thin. Tag or API, not two hashes of the same lead from two implementations. Test against Google's sample digests. Enhanced conversions do not make auto-tagging optional. Keep gclid.

userIdentifiers.hashedEmail on UploadClickConversions is the API twin; that is vendor/google-ads-click-conversions, a different pack (conversionDateTime with timezone offset, and one of gclid, gbraid, wbraid, or userIdentifiers). Do not debug a missing gclid by looking at a GA4 MP 204. Enhanced conversions without gclid still help, then fail in the ways hashed PII always can: wrong normalization, hashing twice, hashing IP. Do not hash gclid. Do not put raw email on the image pixel query.

Clock, hashing, other Google pipes

The browser conversion tag does not take Meta event_time. transaction_id is how Google Ads dedupes repeat fires of the same sale; send it, persist it. Offline click conversion uploads use conversionDateTime in yyyy-mm-dd hh:mm:ss plus a timezone offset, not Unix seconds. Copying CAPI event_time into that field fails the API pack.

GA4 Measurement Protocol is vendor/google-analytics: api_secret, exactly one of G- measurement_id or firebase_app_id, timestamp_micros at 16 digits. Browser collect is vendor/google-analytics-collect: /g/collect v=2 tid G- cid en (ecosystem_reference). Hash email and phone on the enhanced conversions recipe. Leave gclid, gbraid, wbraid plaintext. This is not Meta CAPI; do not send event_id unless you are on a product that names it. The conversion id lives in send_to and in the image path.

pixellint validate url "https://www.googleadservices.com/pagead/conversion/123456789/?label=AbC-D_efGhIj&guid=ON&script=0" --rulepack vendor/google-ads-conversion
pixellint validate url "https://www.googletagmanager.com/gtm.js?id=GTM-XXXX" --rulepack vendor/google-tag-manager

Independence and both pieces

Linker plus conversion tag is the two-piece browser setup. Enhanced conversions are the hashed PII overlay. CAPI-style redundancy here is the tag plus (optional) UploadClickConversions, not facebook.com/tr. Do not skip the linker because you hashed email. Do not skip gclid because you installed the linker on the thank-you page only. Staging conversion ids belong in the staging GTM environment. GTM preview is not the published container.

Pixellint is not affiliated with Google. Pack pages under /packs/google-ads-conversion/ and /packs/google-tag-manager/ are the contracts. This playbook is linker, send_to, enhanced conversions, gclid. pixellint validate url on the conversion pixel after a clean-browser publish, not only after preview.

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Nothing leaves the tab.