How to Install the OpenAI Ads Pixel, Directly or Through GTM
By Ansh Khandelwal 10 min read
In brief
Install the OpenAI Ads pixel directly or through Google Tag Manager, then verify its base script, conversion calls, and click references.
Last verified: 12 September 2026 | Version: 1.0 | Next scheduled review: 12 October 2026
Two lines of work. Put the base snippet in the head of every page, then call oaiq("measure", ...) at the moment a conversion happens. The direct install and the GTM install differ only in who owns the ordering between those two things, which is also the only part that reliably breaks.
Below is the documented implementation, the parts OpenAI leaves to you, and the verification step most write-ups skip.
What the pixel is
The OpenAI Ads pixel is a JavaScript SDK loaded from bzrcdn.openai.com, exposing a single global command queue called oaiq. It does two jobs. It sends conversion events you name, and it captures OpenAI's click reference, oppref, from the landing page URL and stores it in a first-party cookie so that a conversion happening three pages later can still be joined back to the click.
OpenAI appends oppref to your destination URL on every ad click, in the form https://example.com/?oppref=gAAAAAb123. If your site strips query parameters on redirect, the pixel has nothing to store, and the conversion becomes unattributable inside Ads Manager even though the pixel fired correctly. Check your redirect chain before you check anything else.
Step one: create the pixel
In Ads Manager, the conversions tab issues a Pixel ID. The same object can be created through the Advertiser API:
curl -X POST "https://api.ads.openai.com/v1/conversions/pixels" \
-H "Authorization: Bearer $OPENAI_ADS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Acme website", "client_type": "web" }'
The response carries a source ID and a Pixel ID. Separately, you create an event setting, which is the object a conversion campaign actually optimises toward. It takes name, event_type, attribution_window_days and source_ids, and each event setting binds to exactly one source. That one-to-one binding matters later: if you run a second pixel for a second domain, the same conversion event needs its own event setting.
The direct install
OpenAI's documented base code, as published on the Measurement Pixel page, goes in the <head> of every page:
<script>
(function (w, d, s, u) {
if (w.oaiq) return;
var q = function () { q.q.push(arguments); };
q.q = [];
w.oaiq = q;
var js = d.createElement(s);
js.async = true;
js.src = u;
var f = d.getElementsByTagName(s)[0];
f.parentNode.insertBefore(js, f);
})(window, document, "script", "https://bzrcdn.openai.com/sdk/oaiq.min.js");
oaiq("init", { pixelId: "<YOUR-PIXEL-ID>" });
</script>
The stub queues calls before the SDK finishes loading, which is why a measure call placed after init is safe even on a slow connection. It is not safe before init.
If you run a consent banner, OpenAI documents a consent command that sets state around initialisation:
oaiq("consent", false);
oaiq("init", { pixelId: "<YOUR-PIXEL-ID>" });
// later, once the user has agreed
oaiq("consent", true);
Firing an event
The call takes a command, an event name, an event data object whose type must match the event's data shape, and an options object:
oaiq("measure", "lead_created", { type: "customer_action" }, { event_id: "lead_8842" });
The documented event names are page_viewed, contents_viewed, items_added, checkout_started, order_created, lead_created, registration_completed, appointment_scheduled, subscription_created, trial_started and custom. Two further names, app_installed and app_opened, exist for the Conversions API only and the pixel does not accept them.
Each name belongs to a data type. contents events take type, amount, currency and a contents array. customer_action events take type, amount and currency. plan_enrollment events add plan_id. A custom event requires custom_event_name in the options object.
For B2B, lead_created on the form success state and appointment_scheduled on the booking confirmation are the two that matter. Fire page_viewed on load if you want a delivery signal, but do not make it your conversion event setting, because a campaign optimising toward page views will buy you page views.
Page-load events versus click events
A page-load event is the reliable one. Put the measure call on the thank-you page or the confirmation state, where the server has already committed the record. A click event, fired on a button press before navigation, is faster but races the page unload and can be lost.
If you must fire on click, the pattern is to fire the event, then delay navigation briefly, then navigate. OpenAI does not document a callback or a beacon transport for oaiq, so the length of that delay is a guess you are making, not a number the platform gives you. Prefer the page-load version wherever a confirmation page exists.
Single-page applications need attention for the same reason. The base snippet initialises once on first load. Route changes fire no event by themselves, so a virtual thank-you route needs an explicit measure call in your router.
Dynamic order revenue
For revenue you pass amount and currency in the event data. OpenAI's published example sends "amount": 2599, "currency": "USD" for a single bundle, which reads as minor units, that is cents. Every other field in the documented examples is literal, so this is the one value worth confirming in your own account before you ship it, by sending a known order and reading back what Ads Manager reports.
The shape of the implementation, rather than a snippet you should paste:
- On the confirmation page, read the order total and currency from whatever object your platform already exposes, a dataLayer push on Shopify, the order object on WooCommerce, your own template variable otherwise.
- Convert to the unit your test confirmed.
- Pass the order ID as
event_id, not a random string. That ID is what deduplicates the browser event against the same event sent later from your server. - Fire
order_createdwithtype: "contents"and, if you have them, acontentsarray ofid,name,content_typeandquantity.
Point three is the one people skip and regret. Deduplication is keyed on Pixel ID, event name and event ID, and the first event received wins. A random event_id means the pixel event and the server event both count.
The GTM path
Everything above works inside Google Tag Manager with one structural condition: the base snippet must have run before any measure tag fires.
- Create a Custom HTML tag containing the base snippet, including the
initcall, and set it to fire on Initialisation or All Pages. Leavedocument.writesupport off. - Create a second Custom HTML tag per conversion event, containing only the
measurecall. - Use GTM's tag sequencing on each event tag, naming the base tag as the setup tag. Do not rely on trigger order or on both tags sharing an All Pages trigger. Order between two tags on the same trigger is not guaranteed in a way you should build measurement on.
- For revenue, read values from dataLayer variables rather than from the DOM. DOM scraping on a confirmation page breaks silently whenever the theme changes.
OpenAI's help documentation states the pixel can be deployed through a tag manager provided it loads reliably and does not block initialisation. That is the whole of the official GTM guidance. The sequencing requirement above is the implementation detail that follows from it, not something OpenAI writes down.
Verification, which is the step that gets skipped
There is a first-party way to check, and it is better than watching the network tab.
curl -X GET "https://api.ads.openai.com/v1/conversions/events?pid=<PIXEL-ID>" \
-H "Authorization: Bearer $OPENAI_ADS_API_KEY"
This returns up to 50 conversion events received from the pixel SDK in the previous 15 minutes. OpenAI labels it a testing tool and states plainly that it is not for attribution or reporting. Use it to answer three questions: did the event arrive, did it arrive under the event name your event setting expects, and did the amount arrive in the unit you intended.
Two further checks. Load a page with ?oppref=test appended and confirm the pixel still initialises and the parameter survives your redirects, a technique documented by third-party tracking write-ups rather than by OpenAI. And accept the reporting delay: OpenAI states that attributed conversions may take 24 to 48 hours to appear in Ads Manager, so an empty conversions column on day one is not evidence of a broken pixel.
One failure mode has no recovery. If your event setting names an event that your pixel never sends, or names it with a different string, reporting shows zero, and OpenAI states that historical data will not backfill once you correct the mismatch. Get the string right before you spend.
What we cannot tell you
- The exact unit for
amount. The documented example is consistent with minor units but OpenAI does not state the rule in words. Verify with a test order. - Whether
oaiquses a beacon or keepalive transport. Undocumented, which is why click-fired events cannot be given a safe delay figure. - The first-party cookie lifetime for the stored
oppref. Not published, so the effective ceiling on pixel-only attribution is unknown independent of your configured window. - Retry behaviour on a failed pixel request. Undocumented. Assume an event that fails in the browser is lost.
- Whether any of this is materially different for advertisers in the API beta versus the Ads Manager UI. No first-party comparison exists and we have no account of our own to test it in.
Quick answers
Where does the OpenAI Ads pixel go?
In the <head> of every page, not only the conversion page. The SDK needs to run on the landing page to capture and store the oppref click reference before the conversion happens later in the session.
What is the pixel's global function called?
oaiq. You initialise with oaiq("init", { pixelId: "..." }) and send events with oaiq("measure", eventName, eventData, options).
Can I install the OpenAI pixel through Google Tag Manager? Yes. Put the base snippet in a Custom HTML tag on Initialisation, put each event in its own tag, and use tag sequencing so the base tag is a setup tag for every event tag.
How do I check the pixel is working?
Call GET /v1/conversions/events?pid=<PIXEL-ID> on the Advertiser API. It returns up to 50 events from the last 15 minutes. It is a test tool and does not feed reporting.
Why are my conversions showing as zero?
Three usual causes: the event name in your event setting does not match the string the pixel sends, oppref is being stripped by a redirect, or you are inside the 24 to 48 hour reporting delay OpenAI documents.
Do I need the Conversions API as well as the pixel? Not to start. Send both only when you can share an event ID between them, since deduplication is keyed on Pixel ID, event name and event ID.
Sources
| Claim | Source | Tier |
|---|---|---|
Base snippet, oaiq global, SDK at bzrcdn.openai.com, init and consent commands |
OpenAI Developers, Measurement Pixel, 2026 | Confirmed, primary |
| Supported event names, data types and the pixel exclusion of app_installed and app_opened | OpenAI Developers, Supported Events, 2026 | Confirmed, primary |
measure argument order and the event_id, custom_event_name and opt_out options |
OpenAI Developers, Measurement Pixel, 2026 | Confirmed, primary |
| Pixel creation and event setting fields, including one source per event setting | OpenAI Developers, Conversion Setup API reference, 2026 | Confirmed, primary |
| Event stream returns up to 50 events from the last 15 minutes and is not for attribution | OpenAI Developers, Conversion Setup API reference, 2026 | Confirmed, primary |
oppref appended to the landing URL and stored in a first-party cookie |
OpenAI Help Center, Conversion Measurement, 2026 | Confirmed, primary |
| Deduplication keyed on Pixel ID, event name and event ID, first event wins | OpenAI Developers, Conversions API, 2026 | Confirmed, primary |
| 24 to 48 hour delay before attributed conversions appear; mismatched events do not backfill | OpenAI Help Center, Measure Results, 2026 | Confirmed, primary |
| Pixel may be deployed via a tag manager if it loads reliably | OpenAI Help Center, Measure Results, 2026 | Confirmed, primary |
| GTM tag sequencing requirement, SPA route handling, click-event race | Inference from the documented load order | Inference, ours |
Appending ?oppref=test as a verification technique |
ProAnalytics, OpenAI ads conversion tracking, 2026 | Reported, third party |
Related reading
- How to Measure ChatGPT Ads, and What You Cannot Measure Yet
- The OpenAI Conversions API, and When Server Side Beats the Pixel
- UTM Conventions for ChatGPT Ads That Survive Contact With a CRM
- Why ChatGPT Ads Traffic Lands in Referral in GA4
- ChatGPT Ads Troubleshooting
Changelog
12 September 2026, v1.0. First publication. Documents the published pixel snippet and event vocabulary, the GTM sequencing requirement, and the conversions event stream as the verification step.
Field kit
Tools
Site
OpenAI (primary)
Ansh works across GEO strategy, B2B research, and execution. At InPromptAds, he translates new AI advertising products into clear operating advice, tests, and measurement questions for marketing teams.