---
title: "OpenAI Pixel event_id missing on Framer: fix deduplication"
description: "Your Framer site sends ChatGPT Ads events without its own event_id. When that matters, and how to share one ID between the pixel and server events."
updated: "2026-10-23"
url: "https://ispixelworking.com/guides/openai.missing_event_id/framer"
---

# OpenAI Pixel event_id missing on Framer: fix deduplication

Fix guide · Framer · advanced · about 60 min · updated 2026-10-23

For the finding “OpenAI events have no event ID” (`openai.missing_event_id`).
Also for: [Any website](https://ispixelworking.com/guides/openai.missing_event_id/generic), [Shopify](https://ispixelworking.com/guides/openai.missing_event_id/shopify), [WordPress](https://ispixelworking.com/guides/openai.missing_event_id/wordpress), [Webflow](https://ispixelworking.com/guides/openai.missing_event_id/webflow).

## What this means

Each event the OpenAI Pixel sends can carry an **event ID** that your site sets: the `event_id` option in the fourth argument of `oaiq("measure", ...)`, or the **Event ID** field of a Google Tag Manager (GTM) tag. Your Framer site sends its events without one.

The requests still contain an ID: when your site passes none, the pixel puts a random value in the event's `id` field by itself (OpenAI does not document this, but you can see it in the request payload). That value exists only in the visitor's browser. Your server never learns it, so it cannot send the same ID with its copy of the event.

Whether this costs you money depends on one question: **does your site also send these events to OpenAI from a server, through the OpenAI Conversions API?**

- **Yes, or you are not sure:** OpenAI recognizes a browser event and a server event as one conversion when they share the Pixel ID, the event name and the event ID. With a random browser ID they never match, so the same lead can be counted twice.
- **No, you only use the browser pixel:** there is nothing to deduplicate yet. It matters the day you add the Conversions API.

We cannot see server-to-server traffic from a browser, so we cannot tell whether your Conversions API works. We only see whether your site passes its own event IDs to the pixel.

## How to confirm it yourself

Because the pixel fills in an ID on its own, the Network tab cannot tell you whether your site sets one. Look at your setup instead.

1. Search **Site Settings > Code**, each page's own custom code, your code overrides and your GTM tags for `oaiq("measure"`. For each call, look for a fourth argument with `event_id`, as in the [general guide](https://ispixelworking.com/guides/openai.missing_event_id/generic).
2. In GTM, open each OpenAI tag. In OpenAI's template (**OpenAI Ads Measurement Pixel**) the field is **Event ID**; in Stape's **OpenAI Ads Pixel** template it is in the **Server-side tracking settings** section. An empty field means the pixel uses its own random value.
3. Submit a test form on the published site with the Network tab open (filter `bzr.openai.com`) and compare the `id` in the `lead_created` event with the ID your server sends for the same submission. If they differ, deduplication fails.

## How to fix

OpenAI keeps the first event it receives for the same **Pixel ID**, **event name** (for custom events, `custom_event_name`) and **event ID**, and ignores later duplicates. So: give the browser event your own ID, send exactly the same ID from the server, and never reuse a fixed value, or real conversions are dropped as duplicates.

On a Framer site the key conversion is usually a form submission (`lead_created`). Pick the route that matches how your server events are sent.

**Route 1: Tag Manager with a server container.** This fits when your OpenAI tags already run in GTM behind Framer's Cookie Banner.

1. Add a variable that produces a unique ID per event, for example Stape's **Unique Event ID** variable (third-party, from the Community Template Gallery).
2. Put it in the web tag's event ID field: **Event ID** in OpenAI's template, **Server-side tracking settings** in Stape's.
3. Send the event to your server container (for example through server-side GA4 or Stape's Data Tag) and map the same value to the event ID of the server tag. In Stape's **OpenAI Ads Events API** tag this is **Event ID** under **Server Event Data Parameters**.
4. To fire the `lead_created` tag when a Framer form is submitted, give the form a **tracking ID** in its settings. Framer then dispatches a `framer:formsubmit` browser event on each submission. Pass it to the data layer with a custom code entry in **Site Settings > Code**, set to **Run: Once** (Framer recommends Once for event listeners):

   ```html
   <script>
     document.addEventListener("framer:formsubmit", function (event) {
       window.dataLayer = window.dataLayer || [];
       window.dataLayer.push({
         event: "framer_form_submit",
         form_tracking_id: event.detail.trackingId
       });
     });
   </script>
   ```

   In GTM, use a **Custom Event** trigger for `framer_form_submit`, and keep the same `ad_storage` consent requirement as your other OpenAI tags.

**Route 2: a Framer form webhook and your own server.** This fits when the form goes to a webhook (your backend or an automation tool) that sends `lead_created` to the Conversions API.

1. **Add a hidden field** to the form: select the Input, turn on **Hidden** and give it the name `event_id`. Do not hide it with the **Visible** property: Framer leaves invisible inputs out of the submission.
2. **Fill it with a fresh ID** for each submission. Framer does not fill hidden fields by itself; its help points to a code override for this (its example is UTM parameters). Have the override write a new random value, for example from `crypto.randomUUID()`, whenever the form is shown.
3. **Send the same value with the browser event.** Give the form a tracking ID and read the field when Framer reports the submission (custom code entry, **Run: Once**). Replace `contact-form` with your form's tracking ID:

   ```html
   <script>
     var lastForm = null;
     // The browser's own submit event says which form was sent
     document.addEventListener("submit", function (event) {
       lastForm = event.target;
     }, true);
     document.addEventListener("framer:formsubmit", function (event) {
       if (event.detail.trackingId !== "contact-form" || !lastForm) return;
       var field = lastForm.querySelector('input[name="event_id"]');
       if (!field || !field.value || !window.oaiq) return;
       oaiq("measure", "lead_created", { type: "customer_action" }, { event_id: field.value });
     });
   </script>
   ```

   `framer:formsubmit` only tells you the form's tracking ID, so the code reads the field inside the form the browser just submitted. A plain `document.querySelector` would take the field of the first form on the page, which is wrong on pages with several forms. Framer fires `framer:formsubmit` when someone submits the form, not when the submission is confirmed, so a failed submission can still send a browser event; step 2 of "How to verify the fix" compares the IDs on both sides.

   The `window.oaiq` check skips visitors whose pixel has not loaded because they have not consented. If the pixel runs in GTM, push `field.value` to the data layer instead and use it in the tag's **Event ID** field through a Data Layer Variable.
4. **Reuse it on the server.** Framer's webhook sends the submission as JSON with the input names as keys, so the ID arrives as `event_id`. Send it as `id` on the Conversions API event, with the type `lead_created` and the same Pixel ID. Do not use the `Framer-Webhook-Submission-Id` header for this: it is unique per submission, but the browser never sees it, so the pixel cannot send it.

**Route 3: a third-party tool sends your server events.** Check its documentation for how it sets event IDs. It can only match browser events it sends itself, so remove any manually installed pixel; a second copy keeps sending random IDs and usually also shows up as "Duplicate OpenAI events".

Publish the Framer site, and the GTM container if you changed it.

## Common causes

- The snippet and the `measure` calls were pasted into Framer's custom code without the optional fourth argument.
- The **Event ID** field of the GTM web tag is empty, or the server tag reads a different variable.
- Both sides generate their own ID: for example the server uses Framer's webhook submission ID while the pixel makes up its own.
- The hidden field was hidden with **Visible** instead of **Hidden**, so the ID never reaches the webhook.
- The Conversions API was added later, and the browser calls were never updated.

## How to verify the fix

1. Every key OpenAI event (tag or `measure` call) passes an event ID, and the value changes from one submission to the next.
2. For one test submission, the `id` in the browser request equals the `event_id` in the webhook payload and the `id` your server sends.
3. With access to the Advertiser API, OpenAI's recent-events endpoint (`GET /v1/conversions/events?pid=<PIXEL-ID>`) lists a sample of events from roughly the last 15 minutes with their channel: `pixel_sdk` for the browser and `server_to_server` for your server.
4. Re-run the check on IsPixelWorking. The issue should be gone.

## Sources

- OpenAI Developers, Measurement Pixel (`measure` arguments, `event_id` option, deduplicating browser and server events, first event wins): https://developers.openai.com/ads/measurement-pixel
- OpenAI Developers, Conversions API (event `id`, deduplication on Pixel ID, event name and `id`): https://developers.openai.com/ads/conversions-api
- OpenAI Developers, Conversion Tracking (same Pixel ID, event name and event ID through both integrations; Monitoring Events): https://developers.openai.com/ads/conversion-tracking
- OpenAI on GitHub, Ads Measurement Pixel GTM template (Event ID field): https://github.com/openai/ads-measurement-pixel-gtm-template
- Stape, OpenAI Ads Pixel tag (third-party; Server-side tracking settings): https://stape.io/helpdesk/documentation/openai-ads-pixel-tag
- Stape, OpenAI Ads Events API tag (third-party; Unique Event ID variable, Event ID in Server Event Data Parameters): https://stape.io/helpdesk/documentation/openai-ads-events-api-tag
- Framer Help, How to track links and forms in Framer (form tracking ID, `framer:formsubmit` event with `trackingId`): https://www.framer.com/help/articles/how-to-track-links-and-forms-in-framer/
- Framer Help, How to add hidden fields to forms for tracking (Hidden property, invisible inputs excluded, code override): https://www.framer.com/help/articles/hidden-fields-form-tracking/
- Framer Help, Connect Framer forms to a webhook (JSON with input names as keys, `Framer-Webhook-Submission-Id` header): https://www.framer.com/help/articles/framer-form-webhook-setup/
- Framer Help, How to add custom code ("Once" for event listeners): https://www.framer.com/help/articles/how-to-add-custom-code/
