ChatGPT Ads Tracking: How to Set It Up Properly
Henry Purchase
Co-Founder

Most people running ChatGPT Ads right now have broken tracking and do not know it.
I have watched it happen dozens of times inside our community. Someone launches a campaign, the dashboard shows conversions pouring in, they get excited, they scale spend. Then they check their actual sales and the numbers do not match. The campaign was never working. The tracking was lying to them.
The reason is a bug in the code OpenAI hands you during setup. Copy and paste it the obvious way and every single page view on your site gets counted as a conversion. Your reporting inflates by 100x. Your bids move toward the wrong actions. You scale a loser thinking it is a winner.
This guide fixes that. By the end you will have ChatGPT Ads tracking set up the right way: the pixel, the conversion events, and the Conversions API for when you want server-side accuracy. I will show you the exact bug to avoid and the exact code to use instead.
What you actually need to track ChatGPT Ads
ChatGPT Ads tracking has three layers. You do not need all three on day one, but you should understand what each does:
- The base pixel — a JavaScript SDK called
oaiqthat goes on every page and identifies visitors who came from a ChatGPT ad - Conversion events — specific actions (a lead, a purchase, a booking) that you tell the platform to count
- The Conversions API — server-side event tracking that recovers conversions the browser pixel misses
The pixel alone gets you started. The Conversions API is what you add when you are spending real money and need accurate data. OpenAI's own documentation says to run both. We will cover all three.
Why tracking matters more on ChatGPT than anywhere else
A quick reality check on why this is worth getting right.
The ChatGPT Ads dashboard reports impressions, clicks, spend, and CTR out of the box. What it does not show you without tracking is whether any of those clicks turned into money. ChatGPT's native reporting is the weakest part of the platform. There is no built-in way to see which ad drove which sale unless you wire up conversion tracking yourself.
On Google or Meta you can lean on years of benchmarks and a mature attribution ecosystem. On ChatGPT Ads, none of that exists yet. The channel is three months old. There are no reliable category benchmarks. The only way to know if your campaign works is to measure it directly. That makes tracking the difference between scaling a winner and burning money on a loser.
OpenAI knows this. They shipped the conversion pixel on 5 May 2026, the same day they opened the Ads Manager to all US advertisers, and updated their privacy policy on 30 April 2026 to enable it for general availability. The measurement layer is live. Most people just are not setting it up correctly.
Step 1: Generate your data source (the pixel)
Inside the Ads Manager, go to Conversions > Create > Data source. Name it something obvious like "Main website." Pick Web. Click create.
OpenAI generates a block of code and shows you a Copy button. This is the moment most people break their tracking.
The code block has two parts. The top half is the base pixel. The bottom half is a sample conversion event called registration_completed.
If you click Copy and paste the whole block into the <head> of every page on your site, here is what happens: the base pixel works fine, but the registration_completed event also fires on every page. Every time anyone loads any page on your site, OpenAI counts a completed registration. Your conversion numbers become fiction.
The fix
Copy only the top half — the base pixel. That is the part that loads the SDK and initialises it with your Pixel ID. It looks like this:
<script src="https://bzrcdn.openai.com/sdk/oaiq.min.js"></script>
<script>
oaiq('init', { pid: '<YOUR-PIXEL-ID>' });
</script>
That goes in the <head> of every page on your site. Nothing else. Leave the registration_completed event behind. We will add conversion events the right way in the next step.
When this pixel loads on a page someone reached by clicking a ChatGPT ad, it reads an identifier called oppref from the URL, stores it in a first-party cookie called __oppref with a 30-day lifetime, and uses that to attribute later conversions back to the ad that drove the click. Because it is a first-party cookie set on your domain (not OpenAI's), it survives the browser tracking restrictions that have hollowed out third-party cookies. That is genuinely good engineering on OpenAI's part. The default-code bug is the only real trap.
Step 2: Set up your conversion events
Now you tell the platform what counts as a conversion.
Head to OpenAI's developer documentation and open Supported events. There are 10 standard events:
| Event name | What it tracks | Best for |
|---|---|---|
| lead_created | A lead form submission | Lead gen, agencies, B2B |
| appointment_scheduled | A booked call or appointment | Service businesses, consultants |
| order_created | A completed purchase | E-commerce |
| checkout_started | Checkout initiated | E-commerce funnel tracking |
| items_added | Add to cart | E-commerce funnel tracking |
| contents_viewed | A product or content view | Top-of-funnel signals |
| page_viewed | A page load | General traffic |
| registration_completed | An account signup | SaaS, memberships |
| subscription_created | A paid subscription started | SaaS, subscriptions |
| trial_started | A free trial started | SaaS |
Plus custom events if none of the standard ones fit.
Pick the event that matches your real conversion goal. If you run lead gen, that is lead_created. If you sell consulting calls, that is appointment_scheduled. If you run e-commerce, that is order_created with the value passed through.
Place the event code on the right page only
This is the other half of the fix. The base pixel goes on every page. The conversion event goes only on the page that loads after someone converts.
For lead gen, that is your thank-you page or booking-confirmed page. Not the homepage. Not the form page. The page someone sees after they submit.
The event code looks like this for a lead:
<script>
oaiq('measure', 'lead_created', {
type: 'customer_action'
}, {
event_id: 'lead_<unique-id>'
});
</script>
For an e-commerce order with a value:
<script>
oaiq('measure', 'order_created', {
type: 'contents',
amount: 2599,
currency: 'USD'
}, {
event_id: 'order_12345'
});
</script>
The amount is in the smallest currency unit, so 2599 means $25.99. The event_id is what lets you deduplicate later if you also send the same event server-side.
If you are not comfortable editing the snippet for your specific conversion, do what I do: copy OpenAI's three documentation pages (data source, supported events, conversion events) into Claude or ChatGPT and ask it to write the exact code for your event and your platform. It will give you something that works.
Register the event inside the Ads Manager
The final piece. Go to Conversions > Conversion events > Create. Name it (e.g. "Form submitted"). Select the base event (lead_created). Select the data source you made in Step 1. Click create.
This step is what tells the platform "when this event fires on the website, count it as a conversion in my campaign." Skip it and your pixel fires into the void. The event reaches OpenAI but never gets attributed to anything.
Step 3: Add UTM parameters so you can read the data in GA4
ChatGPT Ads pass UTM parameters through to your landing page. Use them, because without them all your ChatGPT traffic gets lumped in with other paid or referral traffic in Google Analytics and you cannot isolate performance.
Every ad destination URL should carry:
utm_source=chatgpt
utm_medium=cpc
utm_campaign=[your campaign name]
utm_content=[your ad variant]
This gives you a second, independent read on performance. The ChatGPT dashboard tells you what OpenAI attributes. GA4 with UTMs tells you what landed on your site. When those two numbers roughly agree, you can trust your tracking. When they diverge wildly, something is broken and you found it before you scaled.
A dedicated ChatGPT Ads UTM Generator is on the Focal roadmap. Until it ships, any standard UTM builder works as long as you follow the convention above. Keep it consistent across every ad or your reporting fragments.
Step 4: Add the Conversions API when you are ready to scale
The browser pixel is enough to start. But browser pixels lose data. Ad blockers, browser tracking prevention, consent declines, broken pages, and mobile webviews all drop a percentage of your conversions. On some audiences you lose 20-30% of your real conversions to these gaps.
The fix is the same one Meta and Google converged on: fire the same conversion twice, once from the browser and once from your server, and let the platform deduplicate. Meta calls it CAPI. Google calls it Enhanced Conversions. OpenAI calls it the Conversions API.
Here is what a server-side event looks like:
curl -X POST "https://bzr.openai.com/v1/events?pid=<PIXEL-ID>" \
-H "Authorization: Bearer <API-KEY>" \
-H "Content-Type: application/json" \
--data '{
"validate_only": false,
"events": [{
"id": "order_12345",
"type": "order_created",
"timestamp_ms": 1773892800000,
"oppref": "oppref_abc",
"source_url": "https://shop.example.com/checkout/confirmation",
"action_source": "web",
"data": {
"type": "contents",
"amount": 2599,
"currency": "USD"
}
}]
}'
The critical detail for deduplication: the server event's id must match the browser pixel's event_id for the same conversion. OpenAI deduplicates on the tuple of Pixel ID, event name, and event ID. Get those three matching and the platform counts one conversion instead of two, even though you sent it from two places.
One gotcha the docs flag: unlike the browser pixel, the Conversions API does not capture oppref for you. You have to capture that value yourself when the user lands (from the URL or the __oppref cookie the pixel set) and pass it with your server event. Without oppref, the server event cannot be attributed to a specific ad click.
The GTM shortcut
If you do not want to hand-code this, there are Google Tag Manager templates that handle both the pixel and the Conversions API. Stape, TensorOps, and others have shipped open-source GTM templates that load the SDK, fire standard events, and manage the server-side deduplication for you.
One thing to watch with GTM: the pixel init has to run before any event tag fires. If an event tag fires before oaiq.min.js has loaded, you lose the conversion silently. Use GTM's "Fire a tag before this tag fires" sequencing to guarantee the init tag runs first. This is the single most common GTM setup failure.
How to verify your tracking is actually working
Setting up tracking is not the same as tracking working. Check these four things before you trust a single number:
Check the cookie. After clicking one of your own ChatGPT ads (or simulating the landing with an oppref parameter in the URL), open your browser dev tools and look for a __oppref cookie on your domain. If it is there, the pixel is capturing attribution.
Check the network request. In dev tools, watch for a POST request to bzr.openai.com when you trigger a conversion. If the request fires, the event is reaching OpenAI. If it does not, your init tag did not run or your Pixel ID is wrong.
Check the dashboard, but wait. There is a 7-hour lag between an event firing and it appearing in the Ads Manager. Do not conclude tracking is broken because nothing shows up immediately.
Cross-check with GA4. Your UTM-tagged ChatGPT traffic in GA4 should roughly match the clicks in your ChatGPT dashboard. Big divergence means something is off.
The most common failures
From watching people set this up, these are the failures that come up again and again:
- Pixel ID typo. A wrong Pixel ID does not throw an error. Events just go nowhere. Double-check it against the Ads Manager.
- Event fires before init. Classic GTM race condition. Use tag sequencing.
- Default code pasted everywhere. The bug we opened with. Every page view counts as a conversion.
- Conversion event never registered in the Ads Manager. The pixel fires but the platform does not know to count it.
- Consent declined but pixel still fires. In GDPR and CCPA jurisdictions, wrap the init in a consent check or you have a compliance problem.
Why this is the hardest part of ChatGPT Ads (and the biggest opportunity)
Here is the honest take. ChatGPT Ads tracking is more involved than it should be for a beta platform. The default code has a bug. The Conversions API needs developer time. The reporting is thin. Most operators will set it up wrong or skip it entirely.
That is exactly why getting it right is an advantage. The advertisers who measure properly will know which campaigns to scale while everyone else is guessing. In a channel with no benchmarks, accurate measurement is the entire game.
This is also the problem we are building Focal to solve. Once your tracking is wired up, the next bottleneck is reading the data, because the ChatGPT dashboard makes it hard to see what is working across multiple campaigns and clients. Focal connects to your ChatGPT Ads through MCP so you can ask "which of my campaigns are actually converting and where am I wasting spend" from inside Claude or ChatGPT, and get a structured answer instead of exporting CSVs and squinting at them. Join the waitlist here.
Quick-start checklist
If you want the short version:
- Generate your data source in Conversions > Create > Data source
- Copy only the base pixel (top half) into the <head> of every page
- Pick your conversion event from the 10 standard events
- Place the event code only on your post-conversion page
- Register the conversion event in Conversions > Conversion events > Create
- Add UTM parameters to every ad URL
- Add the Conversions API when you are spending enough to care about the 20-30% the browser pixel misses
- Verify with the cookie, the network request, and a GA4 cross-check before trusting any numbers
Frequently asked questions
What is the ChatGPT Ads pixel called?
The browser SDK is called oaiq (currently version 0.1.3). It loads from https://bzrcdn.openai.com/sdk/oaiq.min.js and reports events back to OpenAI's measurement endpoint at bzr.openai.com.
Why is my ChatGPT Ads conversion count too high?
Almost always the default-code bug. OpenAI's setup code includes a sample registration_completed event below the base pixel. If you pasted the whole block on every page, every page view is being counted as a conversion. Remove the event code from the base pixel and place conversion events only on post-conversion pages.
Do I need the Conversions API or is the pixel enough?
The pixel is enough to start. Add the Conversions API when you are spending enough that the 20-30% of conversions the browser pixel loses to ad blockers and tracking prevention actually matters. OpenAI recommends running both for accuracy.
How does ChatGPT Ads attribution work without third-party cookies?
OpenAI uses a first-party cookie called __oppref, set on your own domain with a 30-day lifetime. Because it is first-party, it is not subject to the third-party cookie restrictions that have weakened other attribution methods. The oppref value links a conversion back to the specific ad click that drove it.
How do I track ChatGPT Ads in Google Analytics?
Add UTM parameters to every ad destination URL using utm_source=chatgpt&utm_medium=cpc. This isolates ChatGPT Ads traffic in GA4 so you can cross-check it against the ChatGPT dashboard's own numbers.
Can I use Google Tag Manager for ChatGPT Ads tracking?
Yes. Stape, TensorOps, and AI-Advisors have shipped GTM templates that handle the pixel and the Conversions API. The main thing to watch is tag sequencing: the pixel init has to run before any event tag, or events fire before the SDK loads and the conversions are lost.
How long until conversions show in the dashboard?
About 7 hours. There is a lag between an event firing and it appearing in the Ads Manager, so do not assume your tracking is broken if nothing shows up immediately.
My question is not listed here.
Ask in the FutureProof community or email support@tryfocal.com. Tracking questions get answered fastest there because people are setting this up in real time.