Ads and pixels
OpenAI Pixel
Configure the OpenAI Pixel
Copy the pixel ID from the conversions tab in OpenAI Ads Manager. Remove the
standalone OpenAI installation snippet, because the helper creates the oaiq
queue and initializes the pixel itself.
Register the scripts
Complete your framework quickstart first. Keep its Inth endpoint, policy, styles and consent UI. Remove the vendor's original script, SDK initializer or tag-manager entry, so the vendor loads only through c15t.
The vendor pages put the helper in src/consent-scripts.ts. If your framework
quickstart already has a scripts array, such as the one in c15t.config.ts
in the Next.js guide, add the helper to that array instead of creating a
second file.
The scripts export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
point for your framework below. These are edits to that provider, not a second
provider.
Add the configuration to scripts in c15t.config.ts, next to
next.config.ts:
Keep the rest of your config, such as mode and routePrefix, in the
same call. ConsentRoot reads the config in the browser, so the layout
keeps passing only state. App Router, Pages Router and static export all
read the same file. See
Next.js scripts and embeds.
Options
| Option | Default | Behavior |
|---|---|---|
pixelId | Required | Pixel ID passed to oaiq('init', ...). The helper trims it. Empty or whitespace-only values log an error and the script does not load. |
debug | false | Logs SDK activity, including queued and dropped events, to the browser console. |
user | None | User matching fields passed to init: email_sha256, phone_number_sha256, external_id_sha256, first_name_sha256, last_name_sha256, country, city, region and postal_code. |
scriptSrc | https://bzrcdn.openai.com/sdk/oaiq.min.js | SDK URL override. A blank value falls back to the default. |
c15t forwards user unchanged. Normalize and hash identifiers yourself as
OpenAI's
user data rules
describe. If user data arrives after initialization, call
window.oaiq('init', { pixelId, user }) again with the complete object.
Loading and revocation
openaiPixel uses the marketing category. Before marketing is allowed, c15t
defines no oaiq function and loads nothing from OpenAI. Measurement
permission alone does not load the pixel. When marketing becomes allowed, the
helper queues oaiq('consent', false), init and oaiq('consent', true),
then loads oaiq.min.js. The first call overrides the SDK's default consent of
true.
On revocation the helper keeps the SDK and calls oaiq('consent', false). If
the visitor allows marketing again before the page reloads, it calls
oaiq('consent', true) without reinitializing the pixel. OpenAI drops events
sent while consent is denied and does not replay them later. The SDK can still
send diagnostic pings while consent is denied.
Guard your own oaiq calls
The helper sends no page view or conversion, so every event comes from your
code. After revocation window.oaiq still exists, so its presence does not
mean marketing is allowed. Check the permission first, then that the queue
exists:
Pass the current marketing permission from your framework, for example
useConsent('marketing') in React. amount is an integer in the currency's
minor unit, so 2599 is $25.99. Reuse event_id on the server event to
deduplicate it.
@c15t/integrations/openai-pixel also exports openaiPixelEvent, a typed wrapper
around oaiq('measure', ...). It drops calls made before the queue exists and
does not check permission, so apply the same guard before calling it. A
custom event needs custom_event_name in its options. To send to one pixel
when you run several, call window.oaiq('measureSingle', pixelId, ...).
Verify the OpenAI Pixel
Set debug: true while you test. After you allow marketing, oaiq.min.js
loads from bzrcdn.openai.com. Trigger one guarded event and check that a
request to https://bzr.openai.com/v1/sdk/events succeeds and the event
appears in Event Stream in Ads Manager. An accepted request confirms delivery,
not attribution to a ChatGPT ad. Then revoke marketing. Until the page
reloads, calling trackOrder sends nothing. Turn off debug when you finish.
If your site sets a Content Security Policy, allow https://bzrcdn.openai.com
in script-src, both https://bzr.openai.com and https://bzrcdn.openai.com
in connect-src, and https://bzr.openai.com in img-src.
Test in a private window with an opt-in policy. Open DevTools Network, disable the cache and filter by the vendor's domain:
- Load the page. No request goes to the vendor before you choose.
- Click Reject, then reload. There is still no vendor request.
- Open Privacy settings and allow the helper's category. The vendor script loads without a page reload.
- Turn the category off again and save. c15t reloads the page, and the new page makes no vendor request.
c15t reloads on revocation because removing a script element does not stop
code that already ran. The vendor's listeners, timers and queued events stay
alive until the page unloads. If you set reloadOnConsentRevoked: false, stop
the vendor yourself. Register a callback-only script whose onConsentChange
calls the vendor's opt-out API, as shown in
custom integrations, and check the
permission before each of your own event calls. The reload does not delete
cookies the vendor already set; see
clear on revocation for your framework.
The helper sets vendor to its script ID, so once you declare that vendor a
visitor can turn it off inside an allowed category. See
vendor consent for your framework. The
consent verification guide covers navigation,
expiry and hosting checks.