Skip to Content
OpenAI CAPI

OpenAI CAPI Conversion Tracking with Google Tag Manager

OpenAI CAPI: measure your ChatGPT Ads campaigns reliably

The OpenAI pixel alone is not enough

OpenAI offers two ways to measure conversions from your advertising campaigns in ChatGPT: the OpenAI pixel, a script loaded in the browser, and the Conversions API (CAPI), a server-to-server communication. As with other advertising platforms, the pixel is exposed to ad blockers, browser restrictions such as Safari’s, and the limited lifetime of cookies set from the browser. OpenAI itself states that the Conversions API is a more reliable measurement source than the pixel alone and recommends using it whenever possible.

OpenAI Conversions API + OpenAI pixel, and deduplication:

The OpenAI pixel and the Conversions API do not collect data the same way. The pixel collects data directly in the browser, while the Conversions API sends events from your server, without depending on the visitor’s browser. Both methods can be used in parallel to maximize the volume of measured events.

Dual implementation of the OpenAI pixel and OpenAI CAPI

When both sources are active, OpenAI must deduplicate events received twice. To do so, the same event identifier must be sent through each method: the event_id parameter on the pixel side and the id field on the API side. OpenAI keeps the first event received for a given key (Pixel ID, event name and event identifier) and ignores duplicates. If an event is missed by the pixel but delivered by the server, OpenAI records it, so the collection is exhaustive.

OpenAI-side deduplication of an event sent by both the pixel and OpenAI CAPI, using the event ID

Addingwell OpenAI CAPI tag: one server-side tag, cookies that last

The Addingwell OpenAI CAPI tag reads the GA4 events received by your server container, converts them into the format expected by OpenAI and sends them to the Conversions API. It handles for you:

  • the automatic mapping between GA4 events and OpenAI standard events (purchase becomes order_created, page_view becomes page_viewed, and so on);
  • the normalization and hashing of user data (email, phone, first name, last name, external ID) following OpenAI’s rules;
  • the capture of the oppref click identifier present in the landing URL after a ChatGPT ad click, and its transmission with every event;
  • the extended lifetime of cookies: the oppref (click) and obref (browser) identifiers are rewritten server-side into the FPOPPREF and FPOBREF cookies for 365 days. If no obref exists yet, the tag generates one in the same format as the pixel, which enables server-side measurement even without the pixel. The pixel sets them in JavaScript for 30 and 365 days, but Safari caps these cookies at 7 days.

Unlike our Meta CAPI tag, the OpenAI CAPI tag does not trigger the pixel from the server. If you want to keep the OpenAI pixel in parallel, follow the OpenAI pixel setup section to handle deduplication.

Configuring the Addingwell OpenAI CAPI tag

Import the tag into GTM Server

Click here  to download the OpenAI Conversions API tag, then click the download icon to get the file.

Downloading the Addingwell OpenAI CAPI tag

Next, go to the Templates section of your server container, and under Tag templates, click New.

Create a new tag for Addingwell OpenAI CAPI

Then click the three-dot menu in the top right and select Import.

Import the Addingwell OpenAI CAPI tag

Select the template.tpl file you just downloaded, then click Save.

Save the Addingwell OpenAI CAPI tag

Configure the tag

Create a new tag in Google Tag Manager Server-Side and select the newly imported OpenAI CAPI tag. Two pieces of information are required to configure the tag:

Both are available in the Conversions tab of your OpenAI Ads Manager account. Once you have retrieved the key and the Pixel ID, configure the OpenAI CAPI tag.

Configuring the OpenAI CAPI tag

Event Name Setup Method

Setup methodDescription
Inherit from clientInstructs the tag to map GA4 events received from the client-side container to OpenAI standard events. Any GA4 event not listed in the mapping table is sent to OpenAI as a custom event.
OverrideMap GA4 events yourself to what should be sent to OpenAI. Choose to send either a standard event or a custom event.

Conversions API Key

Enter the API key generated in the Conversions tab of OpenAI Ads Manager.

Pixel ID

Enter the Pixel ID retrieved in the Conversions tab of OpenAI Ads Manager. Use the same identifier as your OpenAI pixel in the browser: deduplication depends on it.

Action Source

Tells OpenAI where the conversion occurred. Keep the default web value for events coming from your website. The other values (offline, physical_store, phone_call, email, other, mobile_app) are reserved for conversions that do not originate from the browser.

Validate only

Set this field to true only to test sending events to OpenAI: OpenAI then validates the event structure without recording it.

It is not recommended to keep Validate only set to true in the OpenAI Conversions API tag in production, as no conversion would be counted. Remember to set it back to false before publishing your server container.

Opt Out

Keep the default false value. Set it to true to exclude the event from user-level personalization at OpenAI. This field accepts a variable, for example to reflect a consent choice.

Override sections (optional)

The collapsed sections at the bottom of the tag let you adjust the data sent, without changing your web container:

SectionPurpose
Server Event Data OverrideForce the timestamp, the source URL or the oppref click identifier.
User Data OverrideProvide or replace user data (email, phone, first name, last name, city, postal code, country, external ID, IP address, user agent). Plain values are normalized and hashed by the tag; values already hashed with SHA-256 are forwarded as-is.
Event ID DeduplicationForce the event identifier sent to OpenAI. By default, the tag uses the GA4 event_id parameter, otherwise it generates a unique identifier.
Custom Data OverrideForce the amount (amount, in the currency’s minor unit), the currency, the plan_id, or add custom fields.
Items Data OverrideChoose which fields of the GA4 items array are used to build the contents sent to OpenAI.

Trigger the tag

Finally, trigger the OpenAI CAPI tag on the relevant GA4 events using the tag mapping table.

For example, for an e-commerce site, the following events are generally used:

Event name
page_view
view_item
add_to_cart
begin_checkout
purchase

For a lead generation or subscription site: generate_lead, sign_up, subscribe, start_trial.

This list of events is of course not exhaustive and depends on your situation.

For optimal organization, create a Lookup Table variable configured as follows:

Configuring a lookup table in Google Tag Manager Server-Side

In the OpenAI CAPI tag, create a custom trigger checking that events come from GA4 (Client Name = GA4) and that the previously configured Lookup Table returns true.

Configuring a custom trigger in Google Tag Manager Server-Side

Depending on the country in which your website operates and the regulations in force regarding data collection (GDPR in Europe, CCPA in California, Law 25 in Quebec, etc.), it is imperative to configure the tag trigger based on user consent. Ensure that the tag is triggered only when the appropriate consent has been obtained, in accordance with applicable legal requirements. The tag notably forwards the oppref and obref identifiers read from cookies: OpenAI asks you to stop sending them if the user withdraws consent.

OpenAI pixel setup (optional)

The OpenAI pixel remains useful to capture the oppref and obref identifiers in the browser and complement server-side measurement. OpenAI does not provide a tag template in the GTM gallery: the pixel is installed through Custom HTML tags in your GTM Web container. If deduplicating events between the pixel and OpenAI CAPI seems complex, don’t worry, this section explains everything.

In this section, we assume that your GA4 events are already sent to your server container. What remains is installing the pixel and handling deduplication with the event identifier (Event ID).

What the pixel does in the browser

The oaiq.min.js script exposes a global oaiq function that accepts the init and measure commands, as well as measureSingle to target a specific pixel when several are initialized. On load, the pixel:

ActionDetail
Captures the ad clickReads the oppref URL parameter and stores it in the __oppref cookie (30 days).
Creates a browser referenceGenerates a UUID and stores it in the __obref cookie (365 days).
Batches eventsQueues events and sends them in batches to bzr.openai.com, including when the page is closed.

The __oppref and __obref cookies are set in JavaScript: on Safari, their actual lifetime is capped at 7 days. This is precisely why the Addingwell server-side tag rewrites them into FPOPPREF and FPOBREF for 365 days.

Create the Event Id variable

In your GTM Web container, create a new variable then click Discover more variable types in the Community Template Gallery. Select the Event Id variable from mbaersch, then click Add to workspace.

Event Id variable from mbaersch

This variable generates a unique identifier per event, which we will pass to both the OpenAI pixel and GA4.

Install the OpenAI pixel

Create a Custom HTML tag triggered on all pages (Initialization - All Pages), with the initialization code provided by OpenAI. Replace <YOUR-PIXEL-ID> with your Pixel ID.

<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>
Custom HTML tag initializing the OpenAI pixel

To debug, add debug: true to the object passed to init: the pixel then logs every queued event and every send to the browser console, prefixed with [oaiq]. Events rejected for a format error are reported with a validation failed; event dropped warning.

The pixel applies no condition on its own: as soon as the initialization tag runs, it sets its cookies and sends events. It is therefore up to you to trigger the pixel tags only once the user’s consent has been obtained, in accordance with the regulations applicable to your site.

The pixel and the server-side OpenAI CAPI tag must respect the same consent: a user who refuses must not be measured by either method.

Pass user data to the pixel (advanced matching)

The pixel accepts a user object in init, with the same identifiers as the Conversions API. Plain values are normalized then hashed with SHA-256 in the browser before sending; a value that is already hashed (64 hexadecimal characters) is forwarded as-is. Geographic data is sent in plain text.

KeyExpected content
email_sha256Plain or already hashed email (up to 3 values)
phone_number_sha256Phone number with country code, plain or already hashed (up to 2 values)
external_id_sha256Customer identifier, plain or already hashed
first_name_sha256, last_name_sha256First and last name, plain or already hashed
country, city, region, postal_codePlain geographic values
<script> oaiq("init", { pixelId: "<YOUR-PIXEL-ID>", user: { email_sha256: "{{User Email}}", phone_number_sha256: "{{User Phone}}" } }); </script>

OpenAI Ads Manager can also enable automatic advanced matching: the pixel then detects email, phone, name and address fields in your forms and dataLayer by itself. This option is controlled on the OpenAI side, with no change in GTM.

Send events to the pixel with the event ID

For each event shared with those sent to OpenAI CAPI, create a Custom HTML tag calling oaiq("measure", name, properties, options). The pixel applies the same validation rules as the API and silently drops any non-compliant event:

  • the third argument (properties) is required and must contain type with the value expected for the event (contents, customer_action, plan_enrollment or custom, see the mapping table);
  • amount must be an integer in the currency’s minor unit (cents) and currency is required whenever an amount is present;
  • only documented fields are accepted: amount, currency, contents (with id, name, content_type, quantity, amount, currency) and plan_id;
  • the fourth argument (options) accepts event_id, custom_event_name and opt_out.

The event identifier is passed through the event_id key, using the Event Id variable created earlier. Without this key, the pixel generates its own UUID and deduplication with the server becomes impossible.

Example for a page view:

<script> oaiq("measure", "page_viewed", { type: "contents" }, { event_id: "{{Event Id}}" }); </script>

This tag must always run after the pixel initialization tag. Trigger it on All Pages (not on Initialization) or, more safely, configure it with tag sequencing, using the initialization tag as the setup tag.

Example for a purchase, with the amount in cents and your dataLayer variables:

<script> oaiq( "measure", "order_created", { type: "contents", amount: Math.round({{Ecommerce Value}} * 100), currency: "{{Ecommerce Currency}}" }, { event_id: "{{Event Id}}" } ); </script>

Example for a custom event, where custom_event_name must be identical on the server side:

<script> oaiq( "measure", "custom", { type: "custom" }, { custom_event_name: "newsletter_opened", event_id: "{{Event Id}}" } ); </script>
Custom HTML tag sending an event to the OpenAI pixel with event_id

Use the same standard event names as on the server side (page_viewed, order_created, etc.). The pixel does not know app_installed or app_opened, which are reserved for the Conversions API.

Add the event ID to GA4 events

We will now do the same for all GA4 events that are shared with those sent to the OpenAI pixel.

Add the event_id parameter with the Event Id variable to your GA4 tags. The server-side OpenAI CAPI tag automatically reuses this parameter as the event identifier.

For the Google Tag

event_id parameter configured in the Google Tag

For a GA4 Event tag

event_id parameter configured in a GA4 Event tag

Triggering the OpenAI pixel tags

For deduplication to work properly on the OpenAI side, you must trigger your OpenAI pixel tags with the same triggers as those used for GA4. The Event Id variable then returns the same value for both tags of a given event.

Matching triggers between the OpenAI pixel and GA4

Verifying received data

After configuring your OpenAI Conversions API tag, it is essential to verify the following:

  • your server container successfully sends events to OpenAI;
  • the volume of events received by OpenAI is consistent and deduplication works if you also use the pixel;
  • the data quality is sufficient for OpenAI to match your key events to a ChatGPT user.

Verifying event transmission

GTM Server-Side preview

The first step is to verify that the OpenAI Conversions API tag fires correctly for the events defined in the trigger.

In the server container preview, make sure the tag fires for a specific event (in our example, we check its activation on the purchase event). Confirm it appears in the Tags Fired section with the status Succeeded.

Verify the OpenAI Conversions API tag firing server-side

In the preview, click the OpenAI Conversions API tag to check that the request was sent to bzr.openai.com. You can inspect the event content there: event type, identifier, amount in cents, hashed user data, and the oppref and obref identifiers when available.

Verify data sending via the OpenAI Conversions API

If the request fails, OpenAI’s response indicates the field at fault. The most frequent errors are a missing currency when an amount is sent, and an invalid custom event name. See the testing events page to validate your configuration without recording conversions.

Checking event volume

OpenAI side: received events and deduplication

Go to the Conversions tab of your OpenAI Ads Manager account, then click Start polling events to display in real time the events arriving at OpenAI.

Start polling events button in OpenAI Ads Manager

The events received by OpenAI are displayed by data source: pixel and Conversions API.

Verify data received via the OpenAI Conversions API and the OpenAI pixel

If you implemented dual tracking of your events via the pixel and OpenAI CAPI, make sure that events:

  • come from both data sources, from the pixel and from the Conversions API;
  • are properly deduplicated: the same event received from both sources carries the same Event ID.

The number of events received from the pixel should remain fairly stable after adding OpenAI CAPI. However, the number of events received from the server must be higher than the pixel’s: a 5 to 20% surplus for the Conversions API indicates a good setup.

If you see a higher volume of events from the pixel than from the Conversions API, you probably still have a pixel implementation without event_id, or a pixel hardcoded on the site (check with your development team).

Addingwell side via Events Monitoring

Click the Events Monitoring tab in your Addingwell container. Select the desired time range, then click the OpenAI Conversions API tag card.

Verify OpenAI Conversions API requests in the Addingwell container via Events Monitoring

This screen provides the details of the events sent by your server to the OpenAI Conversions API, along with the success rate of each event.

If your requests do not show a 100% success rate, analyze the errors in the logs. Click the Logs tab, then select the OpenAI API logs.

Log details for OpenAI Conversions API requests via the Addingwell container

You will then see the failed requests, with the detail of the error message returned by OpenAI. The most frequent errors are a missing currency when an amount is sent, an invalid custom event name, or an authentication problem with the API key (which is the case here).

Detail of an error on OpenAI Conversions API requests via the Addingwell container

Checking data quality

Sending your conversion events to OpenAI is an important first step. You can go further by adding user data (email, phone number, first and last name, city, postal code, country) to these events. The tag normalizes and hashes them following OpenAI’s rules before sending, which allows OpenAI to match the received events to a real ChatGPT user.

This allows OpenAI to:

  1. Better attribute received conversions, by identifying those that would otherwise not have been linked to your ChatGPT Ads campaigns.
  2. Optimize your campaign performance, thanks to higher-quality user signals.

To follow our methodology on reliably sending user data server-side, see our dedicated documentation.

Addingwell side via Events Monitoring

Click the Events Monitoring menu in your Addingwell container. This screen displays all user data processed by your GA4 client and made available to your server-side events.

Take the purchase event as an example: by clicking the event name, you can check the parameters available for this specific event.

Checking the parameters attached to a purchase event server-side

On this screen, you can see the presence rate of user data such as email in your purchase events, as well as the coverage rate of each parameter.

Checking the user data attached to an OpenAI event server-side

The data sent is of good quality when events contain the user information expected and available at this stage of the customer journey.

Congratulations

You have completed the OpenAI Conversions API configuration and verified that your events are properly sent to OpenAI and correctly deduplicated.

If you encountered any issues during these steps, feel free to contact our support team.