← Volver a Artículos

Deduplicación de eventos de Shopify entre navegador y servidor

Aprenda a deduplicar eventos de Shopify Web Pixel y webhooks de servidor CAPI para OpenAI Ads mediante IDs de pedido compartidos.

2026-09-21 • Shopify

Running a hybrid tracking architecture on Shopify is the gold standard for ecommerce measurement: a browser Web Pixel captures front-end session intent, while server-to-server CAPI guarantees order delivery.

There is just one problem: without deduplication, you double-count every single order.

When a customer completes a purchase, the browser pixel fires order_created. Milliseconds later, your Shopify checkout webhook fires the exact same order_created event to OpenAI's server endpoint. If both events arrive with different identifiers, OpenAI Ads Manager counts two purchases for one order. Your reported revenue doubles, and your ad algorithms get corrupted by false signals.

Deduplication requires passing the exact same event_id from both the browser JavaScript and the server webhook.

Here is how to generate deterministic deduplication keys across Shopify's sandboxed Web Pixels API and backend order webhooks to guarantee a 100% match rate.


1. The Architectural Challenge of Shopify Customer Events

In older Shopify architectures, developers had direct access to Liquid templates (additional_scripts) and could inject global JavaScript variables on checkout.liquid.

In modern Shopify (Checkout Extensibility), tracking scripts run inside a sandboxed Web Worker:

  • No direct access to window or DOM elements on the main thread.
  • Asynchronous communication via Shopify's analytics.subscribe API.
  • Strict Content Security Policy (CSP) enforcement.

To deduplicate events across this sandbox boundary and your backend cloud servers, you must rely on identifiers that exist identically in both contexts:

[ Shopify Browser Sandbox ]                      [ Shopify Backend Cloud ]
checkout_completed event                         orders/create Webhook
         |                                                 |
Extract: checkout.order.id                       Extract: order.id
         |                                                 |
Format: "shopify_order_8921"                     Format: "shopify_order_8921"
         |                                                 |
oaiq('event', 'order_created', { event_id })     CAPI POST to bzr.openai.com { event_id }
         \                                                 /
          \                                               /
           ------> [ OpenAI Ads Deduplication Engine ] <---
                   Matches exact event_id within 48h
                   Counts exactly 1 conversion!

2. Implementing the Client-Side Customer Event

Inside your Shopify Admin under Settings > Customer Events, configure your custom pixel or install our pre-built app:

analytics.subscribe("checkout_completed", (event) => {
  const checkout = event.data.checkout;
  if (!checkout) return;

  // Derive unique order identifier
  const rawId = checkout.order?.id || checkout.token;
  const dedupKey = "shopify_ord_" + rawId;

  // Convert decimal to minor-unit integer (cents)
  const amountCents = Math.round(checkout.totalPrice.amount * 100);

  // Emit client conversion
  window.oaiq('event', 'order_created', {
    amount: amountCents,
    currency: checkout.totalPrice.currencyCode,
    order_id: String(rawId),
    event_id: dedupKey,
    contents: (checkout.lineItems || []).map(item => ({
      content_id: item.variant?.id ? String(item.variant.id) : undefined,
      quantity: item.quantity,
      item_price: item.variant?.price?.amount ? Math.round(item.variant.price.amount * 100) : undefined
    }))
  });
});

3. Implementing the Server-Side Webhook Relay

On your server (Node.js, AWS Lambda, Cloudflare Worker, or custom backend), subscribe to Shopify's orders/create webhook.

Format the CAPI payload using the exact same prefix and ID pattern:

app.post('/webhooks/shopify-orders', async (req, res) => {
  const order = req.body;
  if (!order || !order.id) {
    return res.status(400).send("Invalid order payload");
  }

  // Construct matching deduplication key
  const dedupKey = "shopify_ord_" + order.id;
  const amountCents = Math.round(parseFloat(order.total_price) * 100);

  const capiPayload = {
    validate_only: false,
    events: [
      {
        id: "srv_" + order.id + "_" + Date.now(),
        type: "order_created",
        timestamp_ms: new Date(order.created_at).getTime(),
        action_source: "website",
        event_id: dedupKey, // EXACT MATCH to client-side key
        user_data: {
          em: sha256(order.email),
          ph: sha256(order.phone || order.billing_address?.phone),
          client_ip_address: order.browser_ip,
          client_user_agent: order.client_details?.user_agent
        },
        data: {
          amount: amountCents,
          currency: order.currency,
          order_id: String(order.order_number)
        }
      }
    ]
  };

  await dispatchToOpenAiCapi(capiPayload);
  res.status(200).send("Webhook processed");
});

4. Edge Cases: Checkout Tokens vs. Order IDs

In rare edge cases, a customer's browser triggers checkout_completed before Shopify has generated the numeric order.id, exposing only checkout.token.

To handle this gracefully:

  1. In the Web Pixel, check checkout.order?.id. If present, use "shopify_ord_" + checkout.order.id.
  2. If order.id is missing, fallback to "shopify_chk_" + checkout.token.
  3. In your server webhook handler, inspect order.checkout_token. If present, your server can send both keys or maintain a translation cache to ensure deduplication is bulletproof under all checkout network conditions.

5. Automated Plug-and-Play Deduplication

Building custom Web Pixels and maintaining cloud webhook infrastructure requires ongoing maintenance whenever Shopify updates its APIs.

To automate this entire deduplication pipeline in one click:

  • Install our free Shopify Pixel App.
  • The app automatically registers the Customer Events pixel, manages the server-side webhook relay, and ensures 100% deduplication parity across browser and server pipelines.

For complete managed setup, review our Done-For-You Ecommerce Tracking service.