Guide

OpenAI Ads Pixel and CAPI for Shopify: Complete Setup

There are two ways to get the OpenAI Ads pixel and Conversions API working on Shopify: install the free "Pixel OpenAI Ads & ChatGPT Ads" app and paste in your Pixel ID (a few minutes, no code), or wire it up manually with a theme snippet, a custom pixel for checkout events, and an order webhook feeding server-side purchase events. Both land in the same place — browser events from the storefront, server-side purchase events from the order, deduplicated against one Pixel ID.

Shopify is one of the few platforms where "paste a script tag everywhere" flatly doesn't work past the cart page. Checkout is locked down by design, which means your purchase event — the one number your campaigns optimize toward — needs a server-side path more than it does on most other ecommerce stacks. This guide covers both the manual build and the free-app shortcut, what each covers, and the Shopify-specific ways this setup breaks.

Why Shopify's checkout restrictions make CAPI especially important here

On a self-hosted storefront, you can usually drop the OpenAI Ads pixel snippet into every template, including checkout, and call it done. Shopify doesn't allow that. Shopify restricts third-party script access at checkout — you can't just edit checkout.liquid and inject arbitrary JavaScript. The sanctioned path for tracking anything at or after checkout is Shopify's customer events system (also called web pixels), where custom pixels run inside a sandboxed environment with restricted access to the page, or an app that implements that integration for you.

That sandbox is good for shoppers' security and platform integrity, but it changes what you can rely on. A sandboxed pixel can still fire browser-side events like checkout_started, but it's more fragile than a plain theme script: it depends on the customer events runtime firing correctly, it can be affected by consent settings, and — like any browser-based measurement — it's subject to ad blockers that never send the request at all.

That's the exact gap the Measure Results documentation calls out for Shopify, headless storefronts, and server-side purchases: use the browser Pixel for browser-side events, and the Conversions API for server-side events, and preserve and pass the click reference (oppref) with server events so they still attribute correctly. On Shopify, your order_created event — the purchase — shouldn't depend solely on a browser pixel surviving checkout. It should also arrive through a server-side path triggered by the order itself.

Method 1: manual install

This is the DIY path: full control, more moving parts. Three components — the base pixel in your theme, a custom pixel for checkout events, and a webhook-driven Conversions API call for the purchase.

Step 1: pixel snippet in theme.liquid

The base JavaScript Pixel loads on every storefront page the same way it would on any site — product pages, collection pages, cart, and your theme's rendered pages generally. Add it near the top of the <head> in your theme's layout file (typically theme.liquid):

<head>
  
  <script async src="https://bzrcdn.openai.com/sdk/oaiq.min.js"></script>
  <script>
    window.oaiq = window.oaiq || function () {
      (window.oaiq.q = window.oaiq.q || []).push(arguments);
    };
    oaiq("init", { pixelId: "YOUR-PIXEL-ID" });
  </script>
  
</head>

This covers page_viewed automatically and gives you the hook for contents_viewed and items_added via oaiq("measure", ...) calls placed at those interactions. It also captures oppref from the landing URL into a first-party __oppref cookie, which is what makes later server-side attribution possible.

What it does not cover: checkout. theme.liquid doesn't render Shopify's checkout — that has its own template third-party scripts can't touch directly.

Step 2: checkout events via a custom pixel

For checkout_started and anything else inside Shopify's checkout, you need a custom pixel set up through Shopify's customer events. It runs in Shopify's sandboxed pixel environment, subscribes to Shopify's checkout lifecycle events, and calls oaiq("measure", "checkout_started", ...) from inside that sandbox when the relevant Shopify event fires.

Two practical constraints follow from the sandbox: you're working with whatever data Shopify's customer events API exposes (line items, totals, currency), not arbitrary DOM values; and it's a separate execution context from your theme's pixel init, so you generally need to initialize oaiq again inside the custom pixel with the same Pixel ID.

If writing and maintaining a custom pixel isn't something your team wants to own, this is the exact piece the free Comercio app installs for you — see Method 2 below.

Step 3: purchase events server-side via the orders/create webhook

This is the part that matters most, and it's why CAPI isn't optional on Shopify. Register a webhook on the orders/create topic. When a real order is placed — regardless of ad blockers, a closed tab before the confirmation page loaded, or a custom pixel that didn't fire — Shopify sends that webhook to your endpoint with the order payload.

Your webhook handler then builds and sends a server-side order_created event to the Conversions API:

curl -X POST "https://bzr.openai.com/v1/events?pid=<YOUR-PIXEL-ID>" \
  -H "Authorization: Bearer <YOUR-CAPI-KEY>" \
  -H "Content-Type: application/json" \
  --data '{
    "validate_only": false,
    "events": [
      {
        "id": "order_1001",
        "type": "order_created",
        "timestamp_ms": 1753315200000,
        "oppref": "<value captured from __oppref cookie or checkout metadata>",
        "source_url": "https://yourstore.com/checkout/thank-you",
        "action_source": "web",
        "data": {
          "type": "contents",
          "amount": 8998,
          "currency": "USD",
          "contents": [
            { "id": "SKU-1001", "quantity": 1, "amount": 8998, "currency": "USD" }
          ]
        }
      }
    ]
  }'

A few things worth being precise about here:

  • amount is an integer in the currency's minor unit — 8998 for $89.98, not 89.98. This applies at the event level and inside each contents[] item.
  • timestamp_ms must be within the last 7 days and not more than 10 minutes ahead of when you send it — Shopify webhooks typically fire within seconds of order creation, so this is rarely an issue.
  • oppref is not captured automatically by CAPI. You need to get the value yourself — usually by reading it from the __oppref cookie client-side and passing it through to the server before the webhook fires.
  • Only use the contents[] fields OpenAI documents (id, name, content_type, quantity, amount, currency) — see Supported events for the full shape.

Passing oppref through

The trickiest part of a manual Shopify build is getting oppref from "captured in a cookie on the browser" to "attached to the server-side webhook event," since those happen in different contexts — the browser during the shopper's session, your backend potentially minutes later when the webhook arrives. Two common approaches: write oppref into a Shopify order note attribute or cart attribute during checkout so it rides along with the order into the orders/create payload, or store it against the customer's session server-side and look it up by order/session ID when the webhook fires.

The goal either way: don't let the value get captured and then dropped before it reaches your CAPI call. Without it, purchase events still record, but with less to work with for attribution.

Dedup between the custom-pixel event and the webhook event

If your custom pixel successfully fires an event and your webhook later sends a related server-side event for the same action, you risk double-counting. The fix, per the Conversions API documentation, is deduplication: reuse the same unique ID as both the pixel's event_id and the CAPI event's id, and send both through the same Pixel ID. For custom events, also match the custom_event_name. OpenAI Ads treats a matched pair as one event, not two.

On Shopify, the highest-value place to apply this is the purchase event, since that's most likely to have both a fragile browser signal and a reliable webhook signal for the same order. Use the Shopify order ID, or a derivative of it, as the shared ID on both sides.

Method 2: the free "Pixel OpenAI Ads & ChatGPT Ads" app

If the custom-pixel-plus-webhook build above sounds like more infrastructure than you want to own, the free Comercio Shopify app, Pixel OpenAI Ads & ChatGPT Ads, installs the pieces above without you writing a custom pixel or a webhook handler.

The install is three steps: install the app from the Shopify App Store (linked on the app's page), paste in your Pixel ID from Ads Manager's conversions tab, and save. That's it — the app handles loading the pixel across your storefront and forwarding server-side purchase events via the Conversions API, without you touching theme.liquid, building a custom pixel, or standing up a webhook endpoint.

Verifying events on product, cart, and checkout pages

Whichever method you use, verify before you trust the data:

  1. Product pages — open dev tools' Network tab, filter for bzr.openai.com, and confirm a request (ideally a 202) fires on page load and again if you trigger contents_viewed manually.
  2. Cart / add-to-cart — add an item and confirm items_added fires with the correct amount in minor units and populated contents[] data.
  3. Checkout — since checkout runs in Shopify's sandbox, dev tools inspection is less reliable here. If you installed a custom pixel manually, use Shopify's own web pixel debugging tools (in the admin's customer events settings) to confirm it's registered and firing. If you're using the app, this step is handled for you.
  4. Purchase confirmation — place a real or test-mode order, check your webhook logs for a successful CAPI call, and confirm the event lands in Ads Manager's event stream a few minutes later.
  5. Ads Manager event stream — the final check regardless of method. If events fire but display 0 against a campaign, confirm the event type (or exact custom event name) matches what's configured on that campaign.

What the free app covers vs. when you need the full CAPI/dedup layer

To be direct about scope: the free app gets your Pixel ID onto your storefront and forwards server-side purchase events through the Conversions API without code. For a lot of stores, especially ones running standard checkout with a single sales channel, that's genuinely enough to get real purchase data into Ads Manager.

Where it's worth layering on a more complete implementation:

  • Multiple sales channels or complex order flows — draft orders, POS orders that later sync to Shopify, subscriptions, or marketplace integrations creating orders through non-standard paths can need custom webhook logic beyond a general-purpose app.
  • Full event-level deduplication across every funnel step, not just the purchase.
  • Custom event data beyond the standard shapes, if your catalog needs line-item detail a general integration doesn't send.
  • Auditing an existing setup that's live but you're not confident is sending clean, deduplicated data.

If any of that applies, the fully managed Ecommerce Tracking service covers the complete pixel-plus-CAPI-plus-dedup build, done for you. If you just want a second set of eyes on what you already have, a tracking audit is the lighter-weight option.

Common Shopify-specific errors

ErrorWhat it looks likeFix
Theme conflictsPixel snippet stripped or duplicated after a theme update or theme switchRe-check theme.liquid (or your app embed block) after every theme change
Duplicate pixels from multiple appsTwo apps, or an app plus a manual install, both load oaiq.min.js with the same or different Pixel IDsAudit installed apps for anything that also touches OpenAI Ads tracking; install the pixel in exactly one place
Consent apps gating tagsA cookie-consent app blocks the pixel script until consent is granted, silently reducing measured trafficConfirm your consent setup explicitly allow-lists the pixel's script and connect sources, consistent with your privacy policy
Custom pixel not registeredcheckout_started never appears, even though the theme pixel works fine on product pagesConfirm the custom pixel is added and enabled in Shopify's customer events settings — code that isn't activated in Shopify won't run
Webhook not verified or misconfiguredorders/create webhook returns errors or never firesConfirm the webhook is registered against your live theme/app and your endpoint returns a success response quickly — Shopify disables webhooks that fail repeatedly
Missing oppref on server eventsCAPI events send successfully but attribution back to the ad click is weak or missingConfirm oppref is actually captured and passed through to the webhook handler, not just captured and discarded client-side

Most of these surface the moment you check the Network tab, Shopify's customer events debugging, and the Ads Manager event stream side by side.

Next steps

Once your pixel and CAPI are firing cleanly, two things are worth doing next. If you're running product-based campaigns, a clean product feed is the other half of the setup — feed data and event data both need to be accurate for OpenAI Ads to optimize toward real purchases. And for the fuller picture of which events map to which funnel step and what parameters they need, tracking cart, checkout, and purchase events covers that in more depth than this Shopify-specific guide does.

Want this done for you?

Fixed-scope setup, tested end-to-end and documented.

Explore the serviceTake the free audit