nod.

Avoid double counting with your own Meta pixel

Stop Meta from counting one order as two purchases when you run your own browser pixel alongside nod.'s server-side send-back.

Updated July 31, 2026

Who needs this

nod. sends a server-side Purchase event to Meta after every qualifying Shopify order (see Set up the Meta server-side send-back (CAPI)). If that's the only Purchase event reaching your Meta pixel, you're done — nothing else to configure.

You need this article if any of the following is true:

  • You run your own Meta pixel in your theme, in a tag manager, or through a separate app, and it fires a browser-side Purchase event.
  • Shopify's Facebook & Instagram sales channel has data sharing turned on for your store.
  • You've noticed Meta Ads Manager shows more purchases or more revenue than your Shopify orders or your nod. dashboard.

In any of these cases, Meta may be counting the same order twice: once from nod.'s server-side send, once from your own browser pixel. This article explains why that happens and how to stop it.

The simplest fix is ownership, not more code:

  • Keep the existing Meta integration as the only conversion sender and disable nod. CAPI; or
  • Let nod. send the server event, remove the competing browser Purchase, and use the matching custom pixel below only if you still need browser evidence.

Do not install the custom pixel beside an existing browser Purchase. That creates another event instead of solving the duplicate.

How Meta's deduplication works

Meta will merge two Purchase events into one conversion only when both of these match, byte for byte, on the same pixel (dataset):

  • event_name — both events must be named Purchase.
  • eventID (browser) / event_id (server) — both events must carry the identical id.

nod.'s server-side send-back uses the id nod-order-<order id>, built from the numeric Shopify order id. This is a per-order id, not a per-visitor id — deliberately, so a returning customer's second purchase never gets deduped away as a "repeat" of their first.

When the ids don't match exactly, Meta counts both events as separate conversions.

This means: for Meta to deduplicate your own browser pixel's Purchase against nod.'s server Purchase, your browser pixel has to fire the exact same eventIDnod-order-<order id> — on the same Meta pixel. Nothing else will match.

The fix: a custom pixel with nod.'s dedup code

Shopify's old "Additional scripts" box on the order-status page is read-only since August 2025 and no longer executes on any store. If you've seen instructions elsewhere to paste a dedup script there, ignore them — it won't run.

The current, correct path is a Shopify custom pixel:

  1. In Shopify admin, go to Settings → Customer events.
  2. Click Add custom pixel.
  3. Paste the code below, replacing PIXEL_ID with your own Meta Pixel / Dataset id. This custom pixel must replace the competing browser Purchase, not run beside it.
  4. Click Connect.

The code box takes plain JavaScript — paste exactly this, with no <script> tags around it:

// nod. dedup pixel — fires ONE browser Purchase that Meta
// deduplicates against nod.'s server-side send (same event id).
const PIXEL_ID = 'YOUR_META_PIXEL_ID'; // ← your Meta pixel id

// Load Meta's base code inside the pixel sandbox (the theme's fbq is not
// reachable from here).
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}
(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', PIXEL_ID);

analytics.subscribe('checkout_completed', (event) => {
  const co = event.data?.checkout;
  // order.id can be a bare number or a gid://…/OrderIdentity/<n> depending on
  // the shop — keep the digits so it matches nod.'s server event id exactly.
  const rawId = co?.order?.id;
  if (!rawId) return;
  const numericId = String(rawId).replace(/\D/g, '');
  if (!numericId) return;
  fbq('track', 'Purchase',
    { currency: co.currencyCode, value: co.totalPrice?.amount },
    { eventID: 'nod-order-' + numericId });
});

The eventID this snippet sends is byte-for-byte the same event_id nod.'s server-side send uses. That is the required dedup key. It is not proof that Meta received both events.

The one-source rule

For dedup to work, exactly one browser Purchase event may reach that Meta pixel per order — the one from this custom pixel. If a second, competing browser Purchase reaches the same pixel, Meta will not merge it with anything, because its event id won't match nod-order-<order id>.

Check for these competing sources and remove them:

  • Shopify's Facebook & Instagram sales channel. If its data sharing setting is sending purchase events, turn it off for this pixel. Its event ids are opaque and will never match nod.'s, so it always double-counts rather than deduplicating.
  • Any leftover Meta pixel code in your theme or a tag manager that still fires its own Purchase event. Remove it once the custom pixel above is live — otherwise you have two uncoordinated browser Purchases plus the server send, and nothing lines up.

If you don't run your own Meta pixel at all, none of this applies — remove any of the above sources you find, and you're covered by the server-side send-back alone.

Verifying it worked

Open Meta Events Manager → Test Events, and set a matching test code in nod.'s CAPI settings (see Set up the Meta server-side send-back (CAPI)) so live sends route there while you check. Place a test order.

The order should show as one Purchase with browser and server evidence merged. If you see two Purchase rows, the event ids do not match or another browser source is firing. nod. reports Dedup not verifiable until matching provider evidence exists. Its own pixel event is never used as proof that Meta received the browser event.

What happens if you skip this

If double counting isn't fixed:

  • Meta Ads Manager shows inflated conversions and revenue for the campaigns driving those orders.
  • ROAS looks better than it is, because the same revenue is counted twice against the same spend.
  • Meta's bidding algorithm trains on the inflated numbers, which can push budget toward audiences and placements that aren't actually performing as well as they appear.

nod.'s own dashboard is unaffected either way — it stitches attribution from your Shopify orders directly, not from what Meta reports back. The double counting only distorts what you see inside Meta.