📗 This is the user manual for the Suite for ChatGPT Ads, the tool in the Ninja Scripts panel. Here you can search it, listen to it, highlight it and save it to favourites. It is updated with every release of the tool.
Without measurement, «maximise conversions» has nothing to maximise and cost per conversion is a decorative number. This is the part that takes the most work and the part that changes results the most.
The two keys, again
They aren't the same and they always get confused:
| Key | What for | Where it's created |
|---|---|---|
| Ads API | Reading the account and applying changes | Settings → API Keys |
| Conversions | Sending conversions from the server | Tools → Conversions → key icon 🔑 (top right, no label) |
The 🎯 Conversions screen carries a diagram pointing at exactly where that icon is, with a direct link to that screen in your account. You'll also need the pixel ID, which sits just under the data source name, on the Data Source tab. Don't go by how it starts: some begin with Fp… and some don't.
🚩 Sending isn't measuring: the actions must be created by hand
This is the most expensive thing to learn the hard way, and we learned it in our own account:
OpenAI does not create conversion actions for you. You can be sending events for days, get a
200 OKon every one, and still see zero in the report because no action exists with that event type. And there is no warning telling you.It happened to us: 46 events accepted over several days and not one conversion counted. The moment the action was created, 22 conversions appeared at once.
Actions are created under Tools → Conversions → Conversion Events → + Create. You need: the data source, the base event (a closed list: that's what matches what you send), a name (yours, it's only a label) and the attribution windows.
A trick to save time: Event Stream tells you in ten seconds whether it's «not arriving» or «arriving and nobody counting it».
The tool can't create those actions for you because OpenAI's API doesn't allow it. What it does do is show you, on the screen itself, the exact name you have to use for each one, with a copy button, and each one's real status based on what has already been sent: «already arrived (n)», «pending», «couldn't be sent» or «none yet».
One event per campaign
The most important rule in the whole measurement setup, and the one that messes up the most money when broken:
- Two actions describing the same fact add up: you'd count every conversion twice.
- Also attaching the stages (qualified, opportunity, sale) would make a single lead count four times.
One campaign, one event. The other actions keep being measured on their own in OpenAI's own report; what they must not be is attached to the campaign.
And since there's no value-based bidding on this platform, choosing which event the campaign counts is the only quality lever there is: if it counts the raw lead, «maximise conversions» chases volume; if it counts the qualified one, it chases quality. That said: qualified leads are always far fewer, and with low volume the campaign is left without a signal to learn from. The sensible minimum is 30 in 30 days, and 💡 Recommendations tells you when you reach it.
⚠️ Changing the event is not changing the objective, and it's worth not mixing them up. The event a campaign counts is changed in the ads manager (the tool can't: the API won't even list the events). The objective —clicks or conversions— can never be changed once the campaign exists: that's what 🧬 Clone is for, in section 14. If your campaign was created for clicks, attaching the qualified event to it will not make it bid for conversions.
🎯 Sending the Ninja Leads stages
If you have Ninja Leads (Lead Rating), the tool can send OpenAI the lead's four stages — raw, qualified, opportunity and sale with its amount — so the campaign learns from quality rather than volume.
How it works, every 30 minutes:
- The leads arriving from your site are read and matched against your Lead Rating sheet by the lead identifier.
- One event per lead and stage is sent, with a deterministic identifier: if it's re-sent, OpenAI deduplicates it.
- The raw lead goes with the lead's real date. Each stage goes with its milestone's date when your CRM sends it; if it doesn't, with the day the panel sees it ticked.
- The sale amount is sent in the currency you pick in the settings (EUR by default): check it if you don't invoice in euros.
- ✖ Bad stops the raw lead from being sent. Careful: if that same lead has a stage ticked (qualified, opportunity or sale), that stage is still sent — the bad-lead filter only applies to the raw one.
- There's a switch per stage and a Test button that validates without really sending anything.
- And a separate checkbox: «leads without the click identifier too». With it, those leads' hashed email is sent so OpenAI can try to match them by identity. It helps when you lose the identifier along the way, but it has two downsides: OpenAI may claim leads that never saw your ad (the figure inflates) and you're handing over one more piece of data, so your privacy policy has to cover it. It ships off.
Two platform limits worth knowing: an event older than 7 days is rejected (OpenAI's window), and what's been sent cannot be withdrawn — unlike Google Ads, there are no adjustments or retractions here.
💰 The 7 days apply to the stages too. If you tick the month's sales all at once at month end, the ones older than a week never get sent and the campaign never learns from them. Tick milestones as they happen: that's the difference between «maximise conversions» chasing quality or never finding out.
🩺 Why each lead is sent — or isn't
Below the send figures there's a block answering exactly that question, with figures taken from the database (not from the last pass). It exists because the most common case is the hardest to diagnose: a table of zeros that looks like «nobody came» when it's actually blocked.
If none of your leads can be sent, it says so at the top and in red, with the cause in plain words. The two causes of being blocked:
- Your site's tracking doesn't declare advertising consent: without it, neither the click identifier nor the email is stored, so there's nothing to attribute with. Fixed by updating the tracking on your site.
- The lead carries neither click identifier nor email: it didn't come from a ChatGPT ad, or its form never captured the email.
And the ones that were attempted but didn't make it are broken down by their real reason —expired past the 7 days, the source page was missing, conversions key rejected— instead of being a lone number.
🛡️ Visits · each ad's traffic quality
If you have Ninja Shield, this screen tells you how many of each ad's visits are people: measured visits against the clicks OpenAI counts, % bots, % with no interaction, duration and forms submitted.
It's the counterpart to cost per lead: a cheap ad with junk traffic stops looking cheap. Ads pointing at pages without the tracking are flagged as «not measured», with the reason, rather than showing up as zero.
This screen's thresholds (when a visit counts as a bot) are calibrated with Google Ads traffic and are provisional for ChatGPT: the ChatGPT app opens websites in its in-app browser, and that produces quick bounces that aren't robots. They'll be recalibrated with our own data.