On the 20th of September a researcher published a teardown of a cookie called __obi. The same day it hit the Hacker News front page, and the comments split into two camps. One was angry that OpenAI tracks ChatGPT users across the web. The other shrugged: Facebook and Google have done this for well over a decade.
Both are right, and both skip the part a developer can do something about.
The cookie only travels because a script from bzrcdn.openai.com loads on a shop's page. That script loads because someone pasted a snippet into a <head> tag. OpenAI's documentation tells you to put it "near the top of your <head>", on every page where you want to measure conversions.
That someone is a developer. Quite possibly you.
What the snippet does
The teardown on buchodi.com is careful work. It reproduces the mechanism on a real phone, checks it with two independent capture methods, and cross-references months of traffic across 936 advertiser pixels. The chain goes like this.
When you open ChatGPT, the client asks OpenAI's backend for a short-lived signed token. That token binds your account to a random identifier. The client then posts it to bzr.openai.com, OpenAI's ad collector, which answers with a cookie:
Set-Cookie: __obi=«redacted»; Domain=.openai.com; HttpOnly;
Max-Age=31536000; Path=/; SameSite=none; SecureOne year, and SameSite=none. That setting exists for one reason: so the browser sends the cookie along on requests from other sites. Every other OpenAI cookie the researcher checked was blocked on those requests. __obi was the only one configured to cross.
Then you visit a shop that advertises on ChatGPT. Its page loads OpenAI's measurement pixel, the browser attaches __obi to the request, and OpenAI receives an identifier tied to your ChatGPT account next to the page you are looking at. On the researcher's own phone, one __obi value went out from 12 commercial sites, including Chewy, Wayfair, Coursera and HelloFresh. It worked while logged out too: 196 of 932 decoded tokens carried an anonymous subject, stable per device for at least 27 days.
The case for the pixel is real
None of this is exotic. Meta has run the same structure for years: a logged-in account, a third-party cookie on the pixel, off-site conversions resolved to a profile. If you buy ads, you want to know which ones sold something. A conversion pixel is how the industry answers that, and OpenAI built the one its advertisers expected.
The researcher is also honest about the limits: the tests ran on Chrome for Android, and desktop Chrome was not tested. Safari blocks third-party cookies, and every iOS browser runs on the same WebKit engine, so iOS is not affected.
Nor does it fire every time. Only about one ChatGPT session in five produced a sync token at all. And the final step, OpenAI joining the event to an account on its servers, follows from the design but was not directly observed.
The mechanism itself is standard adtech. What is new is where the identity comes from. People tell a chatbot things they would never post on a social network, and the account that holds those conversations is now the key that ties together their shopping, their reading and their debt-advice searches.
The part the documentation leaves out
This is where it becomes a developer problem, and it starts with OpenAI's own measurement pixel documentation.
The docs never mention __obi. They list the cookies the pixel sets on your domain, __oppref and __obref, with their lifetimes. The cookie that identifies your visitor to OpenAI does not appear on the page you installed from.
The researcher gets there by another route. The cookie sits on a domain no advertiser script can read, and the teardown concludes: "They installed a conversion pixel and have no way to know their visitors are being resolved to a ChatGPT identity."
Consent is on until you turn it off. In the documentation's own words: "The Pixel initializes consent to true by default unless you set it to false or the Pixel finds a stored denial."
And turning it off comes too late. The documented way to wait for consent is oaiq("consent", false) before init, which stops the SDK from sending measurement events. It does nothing about the request that loads the SDK, and that request is the one the researcher caught carrying __obi. The browser attaches the cookie to the <script src> fetch before a single line of OpenAI's code runs, so loading the tag is enough.
I wanted to see that without a ChatGPT account in the loop, so I built two local pages and loaded them in a default Chromium 153 profile, which allows third-party cookies. The browser held a stand-in __obi cookie on .openai.com, and the OpenAI hostnames pointed at a local server, so nothing reached OpenAI.
Page one is the documented snippet with oaiq("consent", false) before init, and page two injects the same loader only after a click on an accept button, which the test never clicks. Condensed from the script's output:
page one GET /sdk/oaiq.min.js Cookie: __obi=local-test-value
page two (no requests to openai.com)The consent flag was set before the SDK even existed, and the cookie went out anyway. The only page that kept it home is the one that never loaded the script. Firefox and Safari, which partition or block third-party cookies, would not have sent it on either page.
Then there is automatic advanced matching, and here the researcher's traffic and OpenAI's docs part ways. The docs promise: "Raw customer information is not sent to OpenAI through automatic advanced matching." In the observed traffic, the SDK reads form fields and rendered page text, and wraps window.dataLayer.push to pick emails and phone numbers out of your tag manager. The feature was enabled on 638 of the 881 pixels whose setting was known.
Emails, phones and names are hashed with SHA-256 before they leave. Country, region, city and postal code go out in the clear. URLs are trimmed to origin plus path, and the paths that reached the collector included a medical condition, a debt-solutions funnel and a litigation intake form.
Your slugs are data. You chose them for search engines, and they now describe your visitors to an ad network.
What OpenAI calls it
OpenAI's cookie policy lists __obi under Analytics cookies, the only entry in that section, described as helping OpenAI "understand how our Services perform and are used". Marketing has its own consent choice. Every sync token the researcher decoded carried consent_decision: analytics_allowed, so a user who accepts analytics and refuses marketing still gets the cross-site identifier.
The researcher raised this with OpenAI's press and privacy addresses on the 14th of September. Support acknowledged the email and answered nothing.
What to actually do
If your site runs this pixel, or your marketing team asked you to add it recently, the fix is in your hands.
- Gate the script itself. Do not inject the loader until the visitor has consented. A consent flag inside a script that has already loaded protects nothing, because the disclosure happened on the load. That is page two from the test above.
- Switch off automatic advanced matching. It is a setting in OpenAI's Ads Manager. A script that scrapes your forms is a decision someone should make on purpose.
- Send conversions from your server. OpenAI offers a server-side Conversions API. A request from your backend carries exactly the fields you put in it, and none of your visitor's cookies.
- Read your CSP as an inventory. The docs ask you to add
bzrcdn.openai.comandbzr.openai.comto your Content Security Policy. Every host in that header is a third party that sees your visitors. If you cannot say why each one is there, find out.
The same habit applies to anything you paste into a page. A third-party snippet is a dependency you install without reading, and I have argued before that the unread dependency is where the MCP supply chain goes wrong. It is also the lesson from the coding agent that uploaded a whole repository: you only learn what a tool sends when you look at the wire.
This site runs no analytics at all, and I wrote that down as a decision. It costs me every number I might have liked to see. It also means I never have to find out from a Hacker News thread what my own <head> has been doing. If your data lives with a vendor anyway, taking back control of it starts with knowing where it goes.
The teardown's headline says OpenAI knows what you do on other websites. It found out because those websites told it. Somebody on each of those teams can make that stop.