Your ChatGPT Ads conversions are about to be counted twice, and your paid traffic is about to be filed as organic in GA4. That is not a hypothesis, it is the default outcome when you plug in the ad platform without thinking about measurement. Since August 24, 2026, ChatGPT Ads has been open to 31 European markets including France, and self-serve access through Ads Manager is right behind it. So you need ChatGPT Ads conversion tracking this week, not in three months. This guide walks through the full practitioner setup in server-side GTM: the oaiq pixel on the browser side, the OpenAI Conversions API on the server side, the deduplication that breaks everything if you get it wrong, and the part nobody covers, cleanly separating paid from organic ChatGPT traffic in GA4.
What changed on August 24, 2026
OpenAI announced on August 18 that ChatGPT Ads would reach 31 European countries (Germany, France, Spain, Italy, Sweden, the Netherlands, Austria, among others). Three things to keep in mind before you spend a euro:
- Access first runs through the OpenAI Ads Solutions team, agencies, and technology partners. Self-serve through Ads Manager is slated for later in the summer, so September 2026.
- Ads only show on the Free and Go plans. Plus, Pro, and Enterprise stay ad-free. Your paid ChatGPT audience is, by construction, the free-tier audience.
- In Europe, targeting is contextual at launch. Ad selection relies on the current conversation topic, approximate location, device type, time of day, and language. Chat history and memory are not used.
That last point is not just one more compliance footnote: it changes how you have to think about measurement entirely, more on that at the end.
The OpenAI measurement stack in one mental image
OpenAI ships the exact same architecture as Meta or TikTok, two channels for the same event:
- The Measurement Pixel (
oaiq): a browser SDK that loads frombzrcdn.openai.com, initializes with your Pixel ID, and fires an event on every conversion throughoaiq("measure", ...). - The Conversions API (CAPI): a server-to-server endpoint (
https://bzr.openai.com/v1/events) that sends the same conversions from your backend. OpenAI states outright that it is a more reliable measurement source than the pixel alone.
Both speak the same language: the same standard event names and the same data shapes. If you have already deployed Meta CAPI, this is familiar ground; the logic behind Meta CAPI deduplication and Event Match Quality is identical here, only the field names change.
Here are the standard events supported as of this writing:
| Event | Data type | Use for |
|---|---|---|
page_viewed | contents | Viewing an important page |
contents_viewed | contents | Viewing a product, article, or content unit |
items_added | contents | Adding to cart |
checkout_started | contents | Starting checkout |
order_created | contents | Purchase completed |
lead_created | customer_action | Lead form submitted |
appointment_scheduled | customer_action | Meeting or demo booked |
registration_completed | customer_action | Registration finished |
subscription_created | plan_enrollment | Paid subscription started |
trial_started | plan_enrollment | Free trial started |
A detail that matters: monetary values are sent as integers in the currency’s minor unit (so 12999 for 129.99 EUR), and an amount always ships with a currency. This is a classic source of conversion values that end up wrong by a factor of 100.
Step 1: the pixel in web GTM
You could hardcode the OpenAI snippet in your <head>, but you may as well drive it cleanly from web GTM. The logic is simple: one loader tag that installs the SDK and the init, then one tag per event fired on your existing GA4 dataLayer events.
The official init snippet looks like this:
<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>
You create the Pixel ID in the Conversions tab of Ads Manager. Then, on each conversion, you map your dataLayer event to an oaiq("measure", ...) call. For a purchase:
oaiq("measure", "order_created", {
type: "contents",
amount: 12999,
currency: "EUR",
contents: [{ id: "SKU-123", quantity: 1, amount: 12999 }]
}, { event_id: "{{DLV - transaction_id}}" });
Remember that event_id: it is the value that drives deduplication. We get there in a second.
If you use a community template (Stape and others have published OpenAI templates for both web and server GTM), the principle is the same, they just wrap these calls.
Step 2: the OpenAI Conversions API in sGTM
On the server side, you replay the same event from your server-side GTM container. If you do not have a server container yet, start by migrating to server-side GTM, that is the prerequisite. For picking a host, my Stape vs Addingwell vs Taggrs comparison settles the question.
The CAPI call looks like this (sent only from your server, never the browser):
curl -X POST "https://bzr.openai.com/v1/events?pid=<PIXEL-ID>" \
-H "Authorization: Bearer <API-KEY>" \
-H "Content-Type: application/json" \
--data '{
"events": [{
"id": "order_12345",
"type": "order_created",
"timestamp_ms": 1773892800000,
"action_source": "web",
"source_url": "https://shop.example.com/confirmation",
"user": {
"obref": "<__obref_COOKIE_VALUE>",
"emails_sha256": ["<sha256>"],
"external_ids_sha256": ["<sha256>"]
},
"data": { "type": "contents" }
}]
}'
Three fields deserve your attention. action_source is web for on-site conversions. source_url is required for web events. And user.obref is the linchpin of attribution: it is the value of the first-party __obref cookie set on the browser side. You read it in the browser, send it to your server, and pass it back unchanged in user.obref. Never modify it. There is also an event-level identifier, oppref, to pass through untouched when OpenAI provides one.
For enrichment, hash identifiers with SHA-256 (email normalized to lowercase with whitespace stripped, and so on) and never send raw data. Again, this is the matching logic you already know if you have deployed Microsoft Ads Conversions API in server-side GTM.
Step 3: deduplication, the part that breaks everything
Here is the exact rule, the one that decides whether your measurement is right or wrong. OpenAI’s deduplication key is: Pixel ID + event_name + id. OpenAI keeps the first event it receives for a given key and ignores the rest.
Concretely, so the pixel and CAPI do not count the same purchase twice:
- Use the same Pixel ID on both sides.
- Send the same event name (
order_created=order_created). - Match the pixel’s
event_idand the CAPI’sid, exactly.
Web pixel (oaiq) | Conversions API | |
|---|---|---|
| Dedup identifier | event_id (in options) | id (event metadata) |
| Event name | 2nd argument of measure | type field |
| Pixel ID | init({ pixelId }) | pid URL parameter |
| Must match? | Yes, all three | Yes, all three |
My field advice: use your order number (transaction_id) as the id, not a randomly generated identifier. A random ID set client-side will not survive a reload of the confirmation page or a delayed server-side send, and you end up with two different id values for the same purchase, hence a duplicate. The order number, on the other hand, is stable, unique, and available on both sides. For events with no transaction (a lead, say), generate the ID once server-side and propagate it.
Step 4: separating paid from organic in GA4
This is the part nobody covers, and it is the most important. I have already shown that GA4’s “AI Assistant” channel misses a large share of AI sessions. The problem gets worse with ChatGPT Ads: your paid ChatGPT traffic will arrive with chatgpt.com as the referral, exactly like your organic ChatGPT traffic, and GA4 will pile it all into the same bucket. You will pay for clicks you cannot tell apart from your free visits.
The referral is not enough. The only reliable fix is a strict UTM tagging plan on every ChatGPT Ads placement, with at minimum:
utm_source=chatgpt.comutm_medium=cpc(orpaid_ai, as long as you stay consistent)utm_campaign=<campaign_name>
Then, in GA4, build a custom channel group that isolates “ChatGPT Ads” based on that source/medium pair, so it does not fall back into the organic “AI Assistant” channel. If this grouping mechanic is unfamiliar, GA4’s Source Group dimension explains how GA4 files your sources. And for the full picture of AI traffic (paid and organic alike), this is the direct follow-up to my guide on tracking ChatGPT, Gemini, and Claude traffic in GA4. If you sell online, tracking the sales ChatGPT triggers is covered in detail in agentic commerce: tracking ChatGPT sales in GA4.
What GDPR actually changes in Europe
At the European launch, ChatGPT Ads targeting is contextual: conversation topic, approximate location, device, time, language. No history, no memory. In practice, that means custom audiences and CRM uploads, which rely on cross-session data, are not your lever at launch.
The consequence is counterintuitive but decisive: the conversion signal you send back is very nearly the only optimization lever the algorithm has. On Meta, rich targeting can offset a mediocre signal. Here, it cannot. So the Conversions API is not an expert nicety, it is the performance condition for your campaigns. A clean, well-deduplicated CAPI weighs more on ChatGPT Ads than on any other ad platform.
Consent: no exemption available
Let us be clear on a point that is often misunderstood. The oaiq pixel and the __obref cookie set on your site serve an advertising purpose. In France as across the EU, that means consent is mandatory, with no exemption available. It does not matter that ChatGPT serves contextual ads on its side: on your site, you are doing advertising tracking, so you ask for consent.
The OpenAI pixel has a native consent control. You initialize it to false, and flip it to true only after the user agrees:
oaiq("consent", false);
oaiq("init", { pixelId: "<YOUR-PIXEL-ID>" });
// after the user grants advertising consent:
oaiq("consent", true);
Wire that signal to your CMP, exactly like your ad_storage in Consent Mode. On the server side, apply the same rule: only read and forward the __obref cookie if consent is granted. To line all of this up, see Consent Mode v2 in GA4 and Google Ads and, for the deadline that reshuffles the deck, the Digital Omnibus and its six-month rule.
Verify and debug
Before you let it run, two mandatory checks. In web GTM, the pixel’s debug: true option logs all SDK activity to the browser console; that is where you confirm oaiq("measure", ...) fires with the right event_id. In sGTM, the server container’s Preview mode shows you the outgoing CAPI request and its response. Send your first tests with validate_only: true in the CAPI payload: OpenAI validates the structure without recording the event, perfect for gaining confidence without polluting your data. Finally, check that events surface in the OpenAI dashboard, keeping in mind that some reporting delay is normal.
ChatGPT Ads: should you jump in now?
Honest box. ChatGPT Ads in Europe is new, contextual, and without query exclusions for now. Signals from the more mature U.S. market point to high CPCs on high-value intent, but CPMs often lower than classic Search. In other words: interesting on discovery and comparison intent, risky if you are chasing cheap volume.
My take: if you sell a product or service people compare before buying, test it, but only after you have laid down the measurement described here. Without a clean CAPI and without a paid/organic split in GA4, you will be flying blind on the exact channel where the conversion signal is the whole game. If you have neither a server container nor a tidy tagging plan, it is not premature to move, it is premature to spend.
The good news: the ad platform will keep changing, but the trio of pixel, CAPI, and deduplication will stay the foundation for at least a year. Lay it down cleanly once, and you will be ready the day self-serve truly opens the floodgates.