Skip to main content

Conversion Uplift

How to Set Up ChatGPT Ads Conversion Tracking with Web and Server-Side GTM

Are you spending on ChatGPT Ads without knowing which leads or orders they produced? OpenAI’s Ads Manager gives you two ways to send it conversions: a browser pixel and a Conversions API. Use only the pixel and you lose conversions to ad blockers,  browser extensions and Apples tracking protection. Use both without matching them up and OpenAI counts every conversion twice, which makes your cost per lead look half what it really is.

This guide shows the full setup we tested end to end on our own site: the OpenAI Ads Pixel in web Google Tag Manager, the OpenAI Conversions API in server-side GTM (sGTM) hosted on Stape, and the Event ID that ties the two together so each conversion is counted once. It also covers the two problems that stopped our first attempt working, because you will probably hit at least one of them.

The video walks through every screen. The written steps below match it, so you can follow either. There’s also a free PDF checklist at the end of this post that covers every setting in order, with space to record the values you used. Jump to the download.

What we're building

We’re going to track a website lead in ChatGPT Ads using both:

  • the OpenAI Ads Pixel in web GTM
  • the OpenAI Conversions API in server GTM

We’re using the Stape templates for both.

Our website already pushes a generate_lead event into the data layer when somebody successfully submits the contact form. We’re going to use that as an example of how to turn it into OpenAI’s standard lead_created event.

Using the Pixel and the Conversions API together gives OpenAI two ways of receiving the conversion. The important part is giving both versions the same Event ID, so OpenAI knows they’re the same conversion rather than two separate leads.

If you’re an ecommerce site, the process is the same. Swap generate_lead for your purchase event and lead_created for OpenAI’s order_created, and read the ecommerce notes in each step.

Before you start: check the event you already have

Before setting anything up in OpenAI, establish what you’re going to track.

In our example, a successful form submission creates:

event: generate_lead
value: 1136
currency: GBP
lead_id: 1748
lead_type: contact
form_id: 18784
user_data.email_address: [email protected]

You don’t need these exact parameters. What matters is a reliable event that only fires when the conversion has actually happened.

For an ecommerce website, you’d normally start with existing ecommerce events such as purchase, add_to_cart or their equivalents.

Step 1: Set up OpenAI Ads Manager

Create the OpenAI Data Source

Set up a OpenAI Ads Manager account here: https://ads.openai.com/ or login if you already have account. To set up tracking, you will first need to add a logo and add payment details to the account. 

Once you have set up your account, go to the left-hand menu and select Tools then  Conversions and start on the Data Source tab.

Create a new Web Data Source. Call it something like Website Name Pixel Data Source. We called ours  Conversion Uplift Data Source.

Once it’s created, OpenAI gives you a Pixel ID. Copy it, because the same Pixel ID goes into both web GTM and server GTM.

Don't confuse the two OpenAI objects

A Data Source identifies the website or integration fo sending the data.

A Conversion Event defines the action you’re interested in, such as a lead or a purchase. That’s next.

Create the Conversion Event

Go to Tools then Conversions then Conversion Events and create a new conversion event.

For our contact form we used:

  • Display name: Lead Created
  • Event type: Standard
  • Standard event: lead_created

Associate it with the Web Data Source you just created.

For an ecommerce implementation, choose the standard event that describes the action you’re measuring. These include order_created, subscription_created and registration_completed.

 

For e-commerce sites, OpenAI recommend implementing five standard events, so the campaigns can see the whole journey and not only the final sale:

  1. page_viewed: a visitor lands on a page
  2. contents_viewed: a visitor views a product
  3. items_added: a product is added to the basket
  4. checkout_started: the visitor begins checkout
  5. order_created: the purchase completes

 

 Custom conversion events aren’t supported for that optimisation objective at the moment.

Create the Conversions API key

This turned out to be one of the most tricky parts of the implementation.

You need an API key for the server-side Conversions API request.

In Ads Manager go to Tools then Conversions, open Manage conversion keys and choose Create new key.

Give it a recognisable name such as GTM CAPI API. Copy the key when it’s generated and store it securely.

The key belongs in your server GTM container. Don’t expose it in web GTM or in website code. The Pixel ID isn’t a secret in the same way; the Conversions API key is. 

For this implementation, creating the key through Manage conversion keys proved to be the reliable route. There’s a longer explanation of why in the troubleshooting section below.

Step 2: Set up the OpenAI Pixel in web GTM

Install the Stape web GTM template

Open your web GTM container and go to Templates the Search Gallery.

Search for OpenAI Ads Pixel by Stape, accept and add the template.

Create a new tag using this template. We called ours OpenAI Conversion Tag.

Configure the web OpenAI Pixel

Enter the OpenAI Pixel ID from your Data Source. I prefer putting the ID into a GTM Constant variable rather than typing it into every tag.

For our lead event, configure:

  • Event Name Setup Method: Override
  • Event Type: Standard
  • Event Name: lead_created

Why Override?

Our website event is called generate_lead, but the OpenAI standard event we want to send is lead_created. So we’re explicitly mapping one to the other.

Stape also supports inheriting and mapping event names, which is useful for larger ecommerce implementations where you have several events to map.

Configure user data

Under User Identifiers Parameters, add:

Email Address → {{DLV - user_data.email_address}}

Our website already provides the email address inside user_data.email_address, so we’re reading that value with a Data Layer Variable.

Keep Enable Advanced Matching → ON.

Don’t add an email address as an ordinary GA4 custom event parameter just to make this work. Handle user data through the user-data functionality built for it.

Add the conversion value

Under Event Parameters, we added:

  • Amount (in the currency’s regular unit) → {{DLV - lead_value}}
  • Currency → {{DLV - lead_currency}}

Our example therefore sends:

Amount: 1136
Currency: GBP

The Stape server template converts the amount into the format the OpenAI API requires. In our successful outgoing request, £1,136 appeared as:

amount: 113600
currency: GBP

That’s expected. The API request represents the amount in the currency’s lowest unit, so pence rather than pounds.

Create the Event ID

This is the part that matters if you’re using both the browser Pixel and the server-side Conversions API.

Install Stape’s Unique Event ID variable template and create a variable from it. We called ours OpenAI Event ID.

In the OpenAI web tag, go to Server Side Tracking Settings → Event ID and select {{OpenAI Event ID}}.

The actual ID doesn’t matter. What matters is that the same ID reaches both OpenAI requests.

Pass the Event ID to server GTM

This was the missing step in our first implementation.

Generating the Event ID for the OpenAI web Pixel isn’t enough. Server GTM also needs to receive it.

We’re already sending our generate_lead event from web GTM to server GTM through GA4. So open the existing GA4 Event – generate_lead tag and add this Event Parameter:

event_id

with the value:

{{OpenAI Event ID}}

The flow is now:

generate_lead
      ↓
OpenAI Event ID
      ↓
 ┌───────────────┬────────────────┐
 ↓               ↓
OpenAI Pixel     GA4 generate_lead
 ↓               ↓
lead_created     event_id
                 ↓
             Server GTM

In our final test, the GA4 event and the OpenAI web Pixel both contained exactly the same Event ID.

Configure consent

In the web OpenAI tag, set Enable Google Consent Mode support → ON.

We also use the appropriate ad_storage consent state.

Your consent implementation depends on your CMP and your legal requirements, so don’t copy another website’s consent configuration.

Step 3: Set up the OpenAI Conversions API in server GTM

Add the server GTM template

Move into your server GTM container and add the Stape template OpenAI Ads Conversions API by Stape.

Create a tag called something like OpenAI CAPI Tag.

Configure the server OpenAI tag

For our lead implementation we used:

  • Event Name Setup Method: Standard
  • Event Name: lead_created
  • Pixel ID: the same Pixel ID used by the web tag
  • API Key: your Conversions API key
  • Action Source: Web
  • Validate Only: False
  • Use Optimistic Scenario: False while testing

Leaving Optimistic Scenario off during implementation means you can see whether OpenAI actually accepted the request, rather than the tag reporting success before the API has responded.

Configure the server Event ID

Create a server GTM Event Data variable with its Key Path set to:

event_id

We called ours Event Data – Event ID.

In the OpenAI CAPI tag, under Server Event Data Parameters, set:

Event ID → {{Event Data - Event ID}}

Keep Automap Server Event Data Parameters → ON.

For this hybrid Pixel and CAPI implementation we set Autogenerate an Event ID if none is found → OFF.

That’s deliberate. If the Event ID doesn’t arrive from web GTM, I would rather see the server tag fail during testing than have it create a different ID and lose the ability to deduplicate the browser and server events.

Configure server-side user data

Keep Automap User Data Parameters → ON.

Our incoming server GTM event contained user_data.email_address. The successful OpenAI request contained a SHA-256 hashed email rather than the plain address, which gives OpenAI another signal for matching the website conversion back to an eligible ad interaction.

Configure the server conversion value

Under Event Parameters add:

  • Amount (regular unit) → Server Event Data value
  • Currency → Server Event Data currency

Our incoming event contained:

value: 1136
currency: GBP

and the successful outgoing OpenAI request contained:

currency: GBP
amount: 113600

So don’t convert £1,136 to 113600 yourself when you’re using Stape’s regular unit field. The template handles that.

Configure the OpenAI click reference

The Stape server template supports OpenAI’s click reference and can manage the oppref value server-side.

For testing we used a dummy oppref in the landing-page URL, which let us confirm the value made it all the way into the server request.

A dummy value only proves the implementation works. It doesn’t create genuine OpenAI attribution. For that you need an eligible interaction with a real ChatGPT ad.

Set the server GTM trigger

Fire the CAPI tag on the server-side event that represents the genuine conversion. For us that’s generate_lead, which the server tag then maps to lead_created for OpenAI.

Don’t fire the CAPI tag on every GA4 request. It should only fire for the event you’re sending to OpenAI.

Step 4: Test the whole flow

Test the web Pixel

Start web GTM Preview and complete the contact form.

Open the generate_lead event and check the OpenAI tag. We verified:

Firing Status: Succeeded
Event Name: lead_created
Event Type: standard
Email: populated
Amount: 1136
Currency: GBP
Event ID: populated

Copy or note the Event ID, because you’re going to compare it with the server event.

Test server GTM

Open server GTM Preview at the same time and complete another test conversion.

Find the incoming generate_lead and inspect Event Data first. You should see:

event_name: generate_lead
event_id: [your event ID]
value: 1136
currency: GBP
user_data: ...

If event_id is missing here, don’t start changing the OpenAI CAPI tag. The problem is upstream. Check that your web GTM GA4 event is sending:

event_id → {{OpenAI Event ID}}

That was one of the main problems we found during this implementation.

Check deduplication

Compare the Event ID in the OpenAI web Pixel with the Event ID sent by the OpenAI CAPI tag. They must be identical for the same conversion.

Our final test produced the same ID all the way through:

OpenAI Web Pixel
        ↓
GA4 generate_lead
        ↓
Server GTM
        ↓
OpenAI CAPI

This is what allows OpenAI to recognise the browser and server events as the same conversion rather than counting two separate leads.

Check the outgoing OpenAI CAPI request

In server GTM Preview, open the outgoing request to OpenAI. Our successful request contained:

type: lead_created
action_source: web
event_id: [matching Event ID]
user:
    email_sha256
    ip_address
    user_agent
    obref
data:
    type: customer_action
    currency: GBP
    amount: 113600

Most importantly, the response was:

Status Code: 200

That proves OpenAI accepted the server-side event.

Check Ads Manager

Return to Ads Manager → Tools → Conversions and check the Data Source and Event Stream.

There’s an important distinction here. Event received means the implementation is sending data successfully. Attributed conversion means OpenAI has also connected that event with an eligible advertising interaction and the campaign’s configured conversion event.

Don’t assume an accepted test event will immediately appear as an attributed campaign conversion.

Troubleshooting: the Conversions API key problem we hit

This deserves its own section because the implementation looked correct but initially failed.

Our first outgoing request reached OpenAI but returned:

HTTP 401

with an error saying the key was missing the scope:

ads.third_party_events.write

At that point the payload was already correct. Event ID, hashed email, value and the other parameters were all reaching the OpenAI endpoint. The problem was the API key.

What fixed it

We went back to Ads Manager → Tools → Conversions, opened Manage conversion keys and created a new Conversion key there.

We replaced the previous key in server GTM without changing anything else. The next request returned:

HTTP 200

What I'd recommend

Create the CAPI credential through Tools → Conversions → Manage conversion keys → Create new key. That route makes it clear you’re creating a key specifically for conversion measurement.

OpenAI’s current documentation requires a Pixel ID and a Conversions API key for conversion measurement integrations. There are other API-key areas within the wider OpenAI interface, so I wouldn’t claim another route can never work. What we can say from our test is that for our direct Stape server GTM implementation, creating a fresh key from Manage conversion keys resolved the 401 missing-scope error immediately.

So if you get:

401
Missing scopes: ads.third_party_events.write

and the rest of the request looks correct, create a fresh key through Manage conversion keys before you start changing the GTM implementation. It could save you a lot of unnecessary debugging.

Step 5: Link the conversion to your campaign

Ads Manager’s setup checklist includes Link event to a campaign.

You don’t need to create a campaign to prove the Pixel and CAPI implementation works. But you do need to associate the conversion with your advertising if you want OpenAI to use it for campaign conversion measurement and optimisation.

For a conversion-optimised campaign, create a campaign with Objective → Conversions and select the standard conversion event you want the campaign to optimise towards. For our example that’s Lead Created.

Decide which conversion you want to optimise towards before launching the campaign.

Final checks before you publish GTM

I’d want all of these to pass before publishing either container:

That’s the configuration we successfully tested end to end. The same checks, plus every setting that feeds them, are in the PDF checklist at the bottom of this post.

Frequently asked questions

You can run the Pixel alone, but you’ll lose conversions to ad blockers, browser tracking protection and consent choices. The Conversions API sends the conversion from your server, so it isn’t affected by those. Running both, with a shared Event ID, gives OpenAI the most complete picture without double counting.

The OpenAI API represents amounts in the currency’s lowest unit, so pounds become pence. Stape’s template does the conversion for you when you use the “regular unit” amount field. Enter 1136, not 113600.

In Ads Manager go to Tools, then Conversions, then Manage conversion keys, and create a new key. In our testing, a key created elsewhere in the OpenAI interface returned a 401 “missing scopes: ads.third_party_events.write” error, and a fresh key from Manage conversion keys fixed it.

Almost always the web side. Check that your GA4 event tag in web GTM is sending an event_id parameter with the same Unique Event ID variable you gave the OpenAI Pixel tag. If that parameter isn’t there, server GTM has nothing to read.

Not for conversion-optimised campaigns at the moment. OpenAI requires a supported standard event such as lead_created, order_created, subscription_created or registration_completed for that objective.

Download the checklist

Every setting in this guide, in the order you need to make it, on six pages you can print or keep open in a second window. Each step has a tick box and a space to write the value you used (Pixel ID, variable names, trigger, sign-off date), so the person who audits the setup later can see exactly what was configured. It includes the troubleshooting table for the 401 missing-scope error and the missing Event ID.

No email address required.

Need this set up on your site?

I set this up on our own site first so I could see where it breaks. If you’d rather not spend an afternoon in two GTM containers and the OpenAI API, book a free tracking audit and I’ll tell you what your ChatGPT Ads tracking is doing today and what it would take to make it hold up.

Neal Cole, founder of Conversion Uplift

Neal Cole

Neal Cole is the founder of Conversion Uplift, a UK digital analytics consultancy, and wrote the official GA4 and GTM audit course for CXL. He works with marketing teams who spend real money on acquisition and want numbers they can stand behind.

Neal Cole

Neal Cole

Neal is the founder of Conversion Uplift and the author of the official GA4/GTM audit course for CXL. It's the course much of the industry trains on. He's spent over 20 years in digital analytics, including senior roles in online gaming and financial services, working out where businesses' numbers go wrong and what it costs them. His work now focuses on server-side tracking, GA4 and BigQuery: getting the data right, and being the person who's accountable for it when a decision depends on it.
Neal Cole

Neal Cole

Neal is the founder of Conversion Uplift and the author of the official GA4/GTM audit course for CXL. It's the course much of the industry trains on. He's spent over 20 years in digital analytics, including senior roles in online gaming and financial services, working out where businesses' numbers go wrong and what it costs them. His work now focuses on server-side tracking, GA4 and BigQuery: getting the data right, and being the person who's accountable for it when a decision depends on it.
Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Free audit checklist to

Fix GA4 Tracking Like a Professional

Acceptance
Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Free audit checklist to

Fix GA4 Tracking Like a Professional

Acceptance