有效期一年的 __obi:OpenAI 跨站追踪的三层结构
2026/09/21 08:13
摘要:9/20 独立调查公开 OpenAI 广告追踪全链路:bzr.openai.com 发一年期 __obi cookie(SameSite=None、绑 ChatGPT 账号),广告主站点装官方测量 pixel 后回传页面与表单数据。官方把它归为 Analytics、pixel 默认 consent=true,拒绝 marketing 的用户照样被跨站追踪。文末给三个可自查的核对点。
9 月 20 日,独立研究者公开了 OpenAI 广告追踪的完整链路:936 个广告主 pixel、1,029 个 hostname,几个月流量里抓出来的。同一天,OpenAI 官方开发者文档里写着:测量 pixel 的 consent「initializes to true by default」。
两件事并排放,结论比「ChatGPT 有广告追踪」大一号。机制本身是标准 adtech,Meta 和 Google 跑了十年。史无前例的是它跑在一个对话产品上——用户把账单、病历、诉讼、债务问题打进对话框的地方。
四天前,OpenAI 刚官宣 Sponsored Agents 试点,广告从链接变成对话里的成交席位。四天后,对话外面的追踪机制被完整公开。独立的广告网络观测也在补这张图:带 ChatGPT 广告追踪器的站点数量正在翻倍。
文章落到一个能指着的东西:__obi 这条 cookie。它挂在 .openai.com 域下,SameSite=None,有效期一年,是 OpenAI 唯一配置成能跨站出门的标识符。它把你在广告主网站上的浏览行为,绑回你的 ChatGPT 账号。
绑回去的通道有三层:cookie 怎么建、pixel 怎么回传、consent 怎么分类。三层拆开,每层都有一个读者自己能核对的地方。拆之前记住一个数字:作者 9/14 向 OpenAI 提了两个问题,到文章发布,一个都没答。作者把复现方法写在文章里,两种独立抓包互证,承诺 OpenAI 回应后更新。
__obi 是唯一能跨站出门的 OpenAI cookie
第一层是 cookie 的出生。用户在 chatgpt.com 上,客户端生成 16 个随机字节,调 POST /backend-api/bazaar/obi/sync-token。登出用户走 /backend-anon/。后端返回一个 RS256 签名的 JWT:签发方 chatgpt-wadi,接收方 bzr.openai.com,用途 obi_sync,操作 set,token 有效期 60 秒。
JWT 里绑着 64 位的账号主体(sub)、22 位的标识符(obi),还有两行值得记住:consent_decision: analytics_allowed,consent_policy_version: user_granular_consent_v1。bzr 是 bazaar,OpenAI 内部对广告平台的称呼;wadi 是发 token 的服务。consent 的裁决被写进 token 里,由服务端决定,客户端只负责执行。
客户端把这个 token 跨站 POST 到 bzr.openai.com/v1/obi/sync。响应是一行 Set-Cookie:__obi=…; Domain=.openai.com; HttpOnly; Max-Age=31536000; SameSite=none; Secure。SameSite=none 是 cookie 能跨站发送的配置。Max-Age 是一年。JWT 里的 obi 和 cookie 里的值一模一样。
关键在对比。同一批广告主页面请求里,OpenAI 的其他 cookie 全被浏览器拦下。oai-did 和 oaicom-stable-id 是 SameSite=Lax,拦。会话 cookie 域不匹配,拦。只有 __obi 出门。
它是 OpenAI 标识符里唯一配置了 SameSite=None 的。这行配置就是为出门而写的。
为什么偏偏用 cookie?第三方 cookie 是广告归因的通用语言,Meta pixel、Google 转化代码都走这条路。OpenAI 把 SameSite 设成 None,等于明确要求浏览器跨站携带。链路的每一步都有先例,组合起来是第一次。
token 60 秒过期,cookie 一年有效。通行证一次一签,签证长期有效。服务端随时可以停发新 token,已经发出去的 cookie 要到明年才自然失效。一年是广告归因的常用窗口,也是这条链路的实际寿命。
登出也拦不住。932 个解码的 sync token 里,736 个带账号主体,196 个是匿名主体。匿名主体按设备稳定,至少持续 27 天。对 OpenAI 来说,匿名主体和账号主体一样稳定。换设备、清 cookie,才换身份。作者实测里,一个 __obi 值从 12 个商业站点发回 OpenAI,13 个 pixel ID,全部返回 202。覆盖 Chewy、Wayfair、ThriftBooks、Eventbrite、HelloFresh、Coursera、SeatGeek。202 是接受,不是报错——服务器收下 cookie 和事件,不带错误码。
这条 cookie 的扩张不平均。更广的流量里,30 个不同的 __obi 值有 12 个出现在多个广告主站点下,有一个出现在 10 个站点下。同一个标识符出现在 10 家站点,意味着十家广告主共享同一份浏览历史。约五分之一的会话才产生 sync token,ChatGPT 移动网页端干脆不 sync 直接放广告。它铺开的面积,取决于你用什么客户端、开几次会话。
广告主的 pixel 把页面数据连同身份送回 OpenAI
第二层是回传。广告主在自家站点装 OpenAI 的测量 pixel——官方 SDK,bzrcdn.openai.com/sdk/oaiq.min.js。零售商装它,跟装 Meta pixel、Google 追踪代码一样顺手。官方文档要求 pixelId,广告主在 Ads Manager 的 conversions 标签里创建。差别在细节:仅仅加载脚本这一下,浏览器就把 __obi 附在请求上发出去。SDK 有一条不带凭据的代码路径,没用——cookie 在 OpenAI 任何代码运行之前,就跟着 <script src> 出门了。对照组是 pixel-config 请求,不带 cookie 头。这一对照说明:cookie 是浏览器按 SameSite=None 的规则自动带的。SDK 拦不住,想不带都做不到。
回传的不只 cookie。SDK 从广告主页面抓身份,来源分四类:in 是广告主主动传的,fm、ht、js 是 SDK 从表单字段、渲染文本、tag-manager 总线里捡的。作者观测里,被抓取的身份 685 条,广告主主动传的 255 条。数据进 OpenAI 的方式,不是广告主给的,是 pixel 自己捡的。tag-manager bus 是最大的邮箱来源:SDK 替换 window.dataLayer.push,读 adobeDataLayer,还解析 gtm.js 的 l= 参数去定位改名后的 GTM 层。0.1.31 版还取过姓名和地理,8 月 27 日收窄到只剩邮箱和电话。
发送前,邮箱、电话、姓名做 SHA-256 哈希。官方文档要求先规范化再哈希:邮箱去空格、转小写。同一个邮箱两种写法,哈希出来是两个值,匹配会漏。国家、地区、城市、邮编明文发送。邮编是最常被抓的表单字段:100 个事件、28 个站点。URL 只留 origin 加路径,23,929 条观测里没有一条带 query string。但路径会保留。医疗状况、债务解决方案漏斗、诉讼 intake 表单,都在路径里出现过。路径里有医疗状况,说明健康类站点也在装 pixel。denylist 挡的是字段,挡不住路径。
自动匹配默认开。881 个已知设置的 pixel 里 638 个开着,所有被观测到的信贷和借贷广告主都开了。denylist 排除密码、一次性码、卡号、SSN、出生日期、病史、诊断、法庭字段。排除清单存在,说明设计者知道哪些数据不该碰——然后让 pixel 自己决定捡什么。
官方文档里还有一行容易被滑过去:consent 的接线是广告主的责任。文档写的是「如果需要同意才能追踪转化事件,用 pixel 的 consent 功能」。默认值由 OpenAI 定成 true,要不要改成 false,交给装 pixel 的商家决定。一个一年期跨站 cookie,默认开,改关的按钮在别人手里。浏览归因的窗口固定一天,点击归因窗口可配置,事件走 fetch 或 sendBeacon。
作者的证据链值得先说清楚。机制在他自己手机上复现,两种独立抓包方式互证,再拿几个月的历史流量对了一遍。观测窗口、设备、方法都写在文章里。这是单设备、Chrome Android 的观测,不是全平台普查。桌面 Chrome 没测,iOS 所有浏览器因为 WebKit 内核不在覆盖范围。数字是方向性的,链路是真的。作者还在局限里补了一句:202 只代表收集端收下了,服务端有没有 join 到账号,他没亲眼看到。链路设计上 join 是必然的,观测上没抓到最后一跳。
归为 Analytics 的 cookie 绕过了 marketing 拒绝
第三层是 consent 的分类,这一层最值得盯。OpenAI 把用户同意拆成两个独立开关:oai_consent_analytics 和 oai_consent_marketing。作者解码的每一个 sync token 都带 consent_decision: analytics_allowed。一个允许 analytics、拒绝 marketing 的用户,照样拿到这个跨站追踪 cookie。同意策略的版本号写在 token 里:user_granular_consent_v1,逐项同意,v1。
用户侧的设置界面里,这两个开关是独立选项。把 marketing 关掉,关掉的是广告定向那一类。跨站追踪走 analytics 的门,门没关。作者解码的 token 里,拒绝 marketing 的用户同样拿到 analytics_allowed。分类裁决在服务端,用户界面上看不见这一层。
OpenAI 的 cookie policy 把 __obi 列在 Analytics cookies 一节,有效期一年,出现在 chatgpt.com 和 openai.com 上。它是那一节唯一的条目。政策对 analytics cookies 的描述是:帮助 OpenAI 理解服务如何被使用。跨站发送、绑账号、一年有效的追踪标识符,归在「分析」名下。分类词是官方自己写的,改没改一眼可见。
pixel 文档把默认值写得更直白:consent 默认 true,除非主动设 false,或 pixel 找到已存的拒绝记录。广告主侧一个开关,用户侧两个开关,默认值都往开的方向偏。转换匹配还有一个 user 对象,把哈希后的邮箱、电话填进归因。哈希在传输前做,明文的地理字段没有哈希。
作者 9/14 把机制和两个问题发给 press@ 和 privacy@。问题一:为什么 __obi 归为 analytics。问题二:只给 analytics 同意、不给 marketing 的用户,是否仍会收到这条 cookie。回信来自 OpenAI Support,确认收到、内部 review。两个问题都没答。脚本加载即泄漏的发现,是提问之后才做出的——回信里不可能覆盖它。HN 评论区有人提醒,这套「分类决定放行」的粒度设计,正是欧盟 GDPR 逐项同意要防的东西——把追踪塞进用户最不会拒绝的那一类。
时间线值得排一遍。8 月 20 日,广告网络第一批客户上线。8 月 27 日,SDK 收窄身份抓取范围,姓名和地理不再取,只剩邮箱和电话。9 月 14 日,作者把问题发给 OpenAI。9 月 16 日,Sponsored Agents 官宣。9 月 20 日,机制公开。SDK 在公开前一个月主动收窄,说明身份抓取被内部评估过。收窄的是范围,不是机制。
标准 adtech 第一次跑在对话产品上
Meta 做过结构等价物:登录账号、pixel 上的第三方 cookie、站外转化归因到个人档案。Google 也做了十几年。HN 评论里有人指出,OpenAI 的广告团队里有前 Meta 员工。机制上没有任何新东西。新的是载体。
对话产品承载的知情预期不同。用户会把账单、病历、诉讼、债务问题打进对话框,这些不会写进 Facebook 状态。HN 这条帖子 534 分、299 条评论,最高赞的概括是:机制是标准 adtech,史无前例的是跑在 AI 对话产品上。付费订阅用户同样在链路里,有人评论:理想助手应该知道你做的事,但它应该在本地。
对用户来说,最别扭的地方在预期差。Facebook 的用户知道自己在看广告平台,行为本身是公开表演。ChatGPT 的对话框是私密语境,用户默认这里说的话只给机器听。广告追踪把这层默认掀了。
知情缺位在两头:用户不知道被追踪,广告主不知道在追踪谁。
对话产品还会往前走一步。9/16 的 Sponsored Agents 意味着,OpenAI 手里这份「浏览行为 + 对话内容」的画像,会接给替品牌成交的 agent。画像不再是展示广告的输入,是对话式成交的输入。作者的原话更短:人们告诉这些产品的东西,不会写进社交网络,而这些产品正在越来越多地替他们办事。
浏览器已经分好了阵营。Safari 的 ITP 挡全部第三方 cookie。Firefox 和 Brave 做 cookie 分区,chatgpt.com 的第三方 cookie jar 和第一方 jar 分开,账号关联不上。Chrome 和 Edge 不挡。MDN 的第三方 cookie 页面把各家机制列得清清楚楚。
社区侧的反应更直接:有人把 bzr.openai.com 加进 Hagezi 黑名单,DNS 解析直接返回 NXDOMAIN,请求到不了 OpenAI。这些限定词决定了「我被追踪了吗」的准确答案:看浏览器,看客户端。
广告主看不到这层。__obi 挂在 .openai.com 域下,广告主自己的脚本读不到。他们装了一个转化 pixel,不知道访客正在被解析成 ChatGPT 身份。作者观测的 2,860 个 __obref(广告主自己域上的 cookie)里,2,828 个只出现在单一广告主下。广告主之间互相看不见。OpenAI 全看得见。官方文档把两个域名写在 CSP 指引里:bzrcdn.openai.com 和 bzr.openai.com。想拦的人,域名是现成的。
独立数据在补这张图。bloomberry 维护的 ChatGPT Ads 客户名单显示,广告网络从 8 月 20 日起陆续上线,最早一批是房产、电信、医疗用品这类本地服务商。名单本身不是隐私证据,它证明的是另一件事:广告网络在扩张,追踪底座跟着铺开。研究员先看见底座,广告主后知后觉。9/16 的广告原则页承诺的是内容侧的事:敏感话题排除、未成年人保护。数据侧的政策描述,就是 analytics 那一行。
三个核对点都公开:cookie jar、policy、pixel 默认值
惊呼没有核对点。拆开有。第一处:浏览器开发者工具里搜 __obi。看 Domain 是不是 .openai.com,SameSite 是不是 None,Expires 是不是一年。再看页面请求里有没有 bzr.openai.com 和 bzrcdn.openai.com。这两个域名出现在哪些站点,你的账号就被带到哪些站点。Chrome 里搜 cookie,Firefox 里看分区情况,两步就能查完。
第二处:OpenAI cookie policy。看 __obi 在哪个分类。现在它和 analytics 放在一起,是该节唯一条目。哪天它挪进 marketing 或广告分类,就是官方承认这条链路性质的第一信号。改没改,刷新页面就能看见。
第三处:pixel 文档的 consent 默认值。现在写着默认 true。改成默认 false,或者要求广告主先取得用户同意再初始化,是第二个信号。两个信号都不需要等媒体,自己就能看见。广告主侧的知情也一样可查:装了 pixel 的站点,去 OpenAI Ads Manager 看自动匹配的开关——信贷和借贷广告主默认全开。
用户能做的,今天就能做三件。换带分区或 ITP 的浏览器,Safari、Firefox、Brave 都行。把 bzr.openai.com 和 bzrcdn.openai.com 加进 DNS 黑名单。或者接受现状,但知道现状是什么。关掉 marketing 开关没有用,这一条值得再说一遍:分类裁决在服务端,cookie 一年后才过期。广告主能做的只有一件:去 Ads Manager 关掉自动匹配,问 OpenAI 这笔数据到底怎么 join 的。这两个问题,作者 9/14 问过,OpenAI 没答。
这篇文章也没写两件事。第一,OpenAI 是否违法——欧洲监管和浏览器厂商会继续判断,本文只摆机制。第二,OpenAI 会拿这份画像做什么——Sponsored Agents 刚试点,广告主名单还在扩张,行为还没发生。可核的是链路本身,判断停在链路上。
本文的判断是:OpenAI 把 Meta 的广告追踪栈搬进了对话产品,「允许 analytics、拒绝 marketing」的边界拦不住它。什么新事实出现,这个判断作废:__obi 从 Analytics 分类挪走;pixel 默认 consent 改成 false;或者 OpenAI 公布一条能证明「收到 cookie 不 join 到账号」的技术说明。三者任一出现,按新事实重读。三者都不出现,按这三处盯——cookie jar 里的那行 SameSite=None,一年后才过期。