I named the cookie the obvious thing. So had the script that was already there.
My attribution cookie collided with the one the site already had — and it overwrote it precisely on paid clicks. A postmortem on naming, namespacing, and being your own first suspect.
Last week I broke a client's paid attribution for four days. Nobody else could have caused it, and the fix took ten minutes once I understood it. The interesting part is the shape of the mistake, because it is one anybody working on a site they didn't build will make eventually.
The job was ordinary. An outdoor-living retailer runs search ads; the click lands on a category page; the enquiry form is two pages later. By the time somebody fills the form, the ad parameters are long gone from the URL. So you read them once on arrival, park them in a first-party cookie, and read them back into hidden fields at submit. Standard plumbing.
I published a tag-manager listener that did exactly that, and I gave the cookie the obvious name: the site's two-letter prefix, underscore, attr.
The site's own script had picked the same obvious name years earlier
And its version was much better than mine. Mine stored three keys. Theirs stored twelve — click IDs from two ad networks, all five UTM fields, the landing page, a timestamp, and, critically, a first-touch source that never gets overwritten.
Two scripts, one cookie name, same domain, same path. Under RFC 6265 that combination is not two cookies that happen to look alike — it is one cookie, and the last writer wins. There is no warning, no console error, nothing in the network tab. One script simply erases the other's work.
Now the part that made it genuinely nasty. My script only wrote when ad parameters were present in the URL. Which is to say: it wrote on paid clicks, and only on paid clicks.
The cookie whose entire job was to remember that someone arrived from an ad was being flattened at the exact moment someone arrived from an ad.
Organic visits sailed through untouched. Direct visits were fine. Every single ad click had its richer history replaced with my three thin keys, losing first touch, landing page and timestamp on the way. Three submissions in the overlap window show up as direct with no source — almost certainly mine.
The bit I nearly got wrong
The client's report was "leads are coming in as direct". My first instinct was the honourable one: check the independent systems. The analytics property and the shop's own source cookie were untouched by any of this, and both also said organic or direct. Two systems disagreeing with the ad platform.
That is a very satisfying finding, and it would have been a completely wrong one. I would have written up a discrepancy I had personally created four days earlier. It is the same trap as the ROAS that doubled without a single extra sale — when a number moves, the first suspect is not the platform. It is whatever you shipped.
So the rule I actually took from this: when a data anomaly starts on a Friday, look at what went live on that Friday before you look at anything else. Not because you're usually the cause, but because you're the cheapest hypothesis to eliminate.
The fix, and the proof
Renaming the cookie is trivial. Believing the rename took effect is the work. I gave mine a namespaced name in both tags, then re-read the container as actually delivered to the browser to confirm no bare name survived anywhere — because a find-and-replace that misses one of two tags leaves you with a bug that only fires on some pages.
Then a live proof run. Load a category page with a fabricated click ID and a set of campaign parameters. Navigate to the enquiry form with a completely clean URL — no parameters at all. Read the hidden fields.
Click ID present. Source and medium present. Landing page recorded as the category page. First touch dated correctly. Both cookies now sit side by side, the site's own one back to its full twelve keys. Cross-page persistence works — and had worked all along, right up until I stood on it.
That verification step matters more than the fix. Asserting that an element exists is not the same as asserting it works; I wrote a whole post about a button that was present, visible and zero pixels wide. Cookies are worse, because there is no rendered thing to look at at all.
Namespace what you write on other people's sites
The lesson is not "check for collisions", which is the kind of advice that sounds useful and changes nothing. It's more specific than that: the obvious name is obvious to everyone. That is exactly why it is already taken. The more natural your naming instinct, the more likely somebody with the same instinct got there first.
Read document.cookie on a live page before you write anything. Prefix your keys with something that identifies the system writing them, not the site receiving them. Treat a shared browser as the shared global namespace it is.
I diagnosed a nine-month tracking failure on another account without ever getting access to the tag manager. Then I broke a working setup on a site I had full access to, with one word. Access was never the constraint. Attention was.
Sources & further reading
External
RFC 6265 — cookies are identified by name, domain and path
RFC 6265bis — the current working revision of the cookie spec
MDN: Document.cookie
Google Ads: auto-tagging and the click ID parameter
Related posts
No login to the tag manager. The container told me everything anyway.
Our ROAS doubled. We hadn't sold a thing more.
The button was there. On a phone it was zero pixels wide.