Field Notes / AdTech
№ 016 · 2026
Build · Conversational AI · Conversion Measurement

Introducing the GTM Tag for OpenAI Ads.

ChatGPT Ads are live. The conversion pixel that ships with them is a hand-rolled SDK paste — a non-starter for any marketing team that runs its tag stack through Google Tag Manager. We built and open-sourced a GTM web custom template, Apache-2.0, that loads the OpenAI Ads Measurement Pixel, fires the eleven standard events, and deduplicates against the OpenAI Conversions API. Install it the way you install every other tag, and start moving budget on real data.

1,131 words5 minDemand SideMay 10, 2026Gad Benram

ChatGPT Ads went live, and an entire generation of conversion measurement showed up with it. A new pixel. New event names. A new attribution surface inside a chat product that didn't have ads twelve months ago. And — for now — the official install path is a copy-paste of a raw JavaScript SDK into the head of every page you want to track.

Nobody who runs a marketing stack at scale wants that. The whole point of Google Tag Manager — the reason it sits in front of analytics, ad pixels, CAPI relays, consent gates, and every other tag a modern site fires — is that you do not paste SDKs into your codebase one campaign at a time. You ship them as tags. You version them. You gate them on consent. You scope them to triggers. You let the growth team move without a code release.

So we built one. openai-gtm-pixel is open-source under Apache-2.0 and installs into any GTM container today.

Why the OpenAI Ads Pixel needs a Google Tag Manager template

OpenAI's Ads Measurement Pixel is a small, well-scoped client SDK — oaiq.min.js, served from bzrcdn.openai.com. You initialize it with a pixel ID. You call oaiq("measure", eventName, props, options) when a conversion happens. The contract is clean. The problem is not the SDK. The problem is the gap between the SDK and the place every working marketing team manages tags.

Closing that gap is what GTM community templates were invented for. A template is a sandboxed wrapper that turns a vendor SDK into a first-class GTM tag — permission-scoped script injection, declarative inputs in the GTM UI, no Custom HTML loophole, no untrusted JS pasted into a hundred sites by a hundred analysts. Meta has one. Google has one. TikTok has one. Until last week, OpenAI did not.

Paste the SDK

Raw <script> in every layout. Changes go through engineering. Consent gating is on you. Every event is hand-wired to a page-specific listener. The pixel ID lives in source.

Ship a tag

One template, two modes, declarative inputs. Consent integrations, versioning, triggers, and workspace permissions come for free from GTM. The growth team owns the rollout.

What the OpenAI Ads GTM tag does

One tag, two modes.

  • Initialization mode loads oaiq.min.js, calls oaiq("init", { pixelId }), and is wired to the All Pages — Page View trigger. One per site.
  • Event mode fires conversion events with standardized names, typed payloads, and an event_id for server-side deduplication. One per conversion.
11
standard event types out of the box — page_viewed, contents_viewed, items_added, checkout_started, order_created, lead_created, registration_completed, appointment_scheduled, subscription_created, trial_started, custom.
OpenAI Ads Measurement Pixel — standard event taxonomy

Payload fields cover the ecommerce shape every team already builds against: type, amount, currency, plan_id, and a contents[] array with id, name, content_type, quantity, amount, currency. From the GTM UI, an order conversion is six fields and a trigger:

1// dataLayer push at order completion
2window.dataLayer = window.dataLayer || [];
3window.dataLayer.push({
4 event: 'order_completed',
5 order_id: '8c4a1f', // → maps to event_id (CAPI dedupe key)
6 value: 129.00, // → amount
7 currency: 'USD', // → currency
8 contents: [ // → contents[]
9 { id: 'sku-42', name: 'Pro Plan', content_type: 'product',
10 quantity: 1, amount: 129.00, currency: 'USD' }
11 ]
12});

The template reads those values from GTM variables, hands them to oaiq("measure", "order_created", …), and the conversion shows up against the campaign that drove it.

How the OpenAI pixel and Conversions API work together

Two tags in GTM, one SDK in the browser, one Conversions API call on your server. All three carry the same event_id, and OpenAI Ads collapses them back into a single conversion at ingest.

Fig. 01 — Two tags, one SDK, one dedupe key browser path · GTM template fires the pixel · server path · your backend hits the Conversions API · OpenAI Ads dedupes on (pixelId, eventName, event_id) Browser GTM container Init tag oaiq("init", { pixelId }) trigger · All Pages — Page View tag sequencing Event tag oaiq("measure", "order_created", props, { event_id: "order_8c4a1f" }) trigger · order confirmation loads bzrcdn.openai.com/sdk/oaiq.min.js Your server order webhook on order paid order.id = "order_8c4a1f" amount · currency · contents · user_id Conversions API call POST /v1/ads/events { event_id: "order_8c4a1f", … } same id as the pixel · server-trusted survives ad blockers · ITP · consent declines OpenAI Ads · ingest dedupe key = (pixelId, eventName, event_id) → one conversion
Fig. 01 The pixel and the Conversions API are not redundancy — they're a quorum. The browser path is fast and granular; the server path survives the modern web. The same event_id on both lets OpenAI Ads collapse them into one conversion at ingest.

If this lands for you, star the repo on GitHub. Stars are the only signal we use to prioritize the next two things on the list: the CAPI companion (Cloudflare Workers + Node) and the Community Gallery submission. Issues and PRs welcome too.

Tag sequencing: firing the OpenAI Ads pixel reliably in GTM

The single failure mode you have to design out of a pixel template is the race between SDK load and event fire. If the event tag fires before oaiq.min.js is queued, you lose the conversion. Browsers do not retry it. Marketing dashboards just show a smaller number.

The template ships with GTM tag sequencing as the recommended pattern: on every Event tag, set "Fire a tag before this tag fires" to your Init tag. GTM guarantees the order. The SDK queues calls before it loads. Conversions land in the right window even when the event trigger beats the page view by a few milliseconds.

Server-side deduplication with the OpenAI Conversions API

Client-side pixels lose data — ad blockers, ITP, consent declines, broken pages, mobile webviews that drop third-party JS. The fix every mature ad platform has converged on is the same one OpenAI is using: fire the same conversion twice, once from the browser and once from your server, and let the platform dedupe on a shared key. Meta calls it CAPI. Google calls it Enhanced Conversions. OpenAI's Conversions API uses the tuple (pixelId, eventName, event_id).

The template surfaces event_id as a first-class field on every Event tag. Push the same value from your backend to the Conversions API and you get the union of browser-reachable and server-reachable conversions without double counting. That is the difference between bidding on attributable revenue and bidding on whatever happened to make it past the ad blocker.

Open-source roadmap: Community Gallery submission and a CAPI companion

The code is at github.com/TensorOpsAI/openai-gtm-pixel under the Apache-2.0 license. It is a single template.tpl file in GTM's sandboxed JS runtime, with a tests block that runs inside the GTM template editor. You can import it into any container today.

Three things are explicitly open. The template is unreviewed: before Community Gallery submission it needs final naming alignment with OpenAI and a real brand thumbnail. The CAPI side is out of scope here — that belongs in your server, not in GTM, and we will publish a companion reference for Cloudflare Workers and Node soon. And the event taxonomy follows OpenAI's standard names today; if they extend the spec, the template extends with it.

Conversational ads are not a 2027 problem. They are a 2026 budget line, and the teams that move first are the ones whose measurement is already wired through the same plumbing as everything else they spend on. Fork it, file issues, ship it into your container.

End.   Set in Fraunces & Newsreader.
№ 016 · 2026 · AdTech Lab