Skip to content
DM · Daniil Maximkin
Solution

Meta CAPI Not Deduplicating: Fix Duplicate Events

·

The short answer

Meta deduplicates a browser Pixel event and a server CAPI event only when both carry the exact same event_name and event_id for the same action. If either value differs, or two independent systems (Shopify's native Meta channel and a separate GTM setup) both send Purchase without sharing an event_id scheme, Meta counts it twice. Events Manager's Test Events tool shows this directly — a real purchase should appear once, deduplicated, not as two rows.

Symptoms you might be seeing

  • Reported ROAS looks better than the order volume can explain
  • Meta's Purchase count is higher than Shopify's order count for the same period
  • Events Manager shows two Purchase events per order from different sources
  • The deduplication metric in Events Manager's overview stays near zero
  • Duplicate counts started after installing a new tracking app or CAPI integration

The symptom

A campaign that shouldn’t be working is showing a great ROAS. Or Meta’s Events Manager reports more purchases in a week than the store had orders. Both usually trace back to the same root cause: the same real purchase being counted twice — once from the browser Pixel, once from server-side CAPI — because Meta was never given a way to recognize they’re the same event.

Direct answer

Meta deduplicates a Pixel event and a CAPI event only when both carry the exact same event_name and event_id for the same action. If either value differs — or if two independent systems, such as Shopify’s native Meta & Instagram channel and a separately configured GTM setup, both send Purchase for the same order without sharing an event_id scheme — Meta has no way to know they’re duplicates, and counts both. Events Manager’s Test Events tool shows this directly: a correctly deduplicated purchase appears once, flagged as merged from two sources, not as two separate rows.

Causes, ranked

  1. No shared event_id. The browser Pixel call and the server CAPI call generate their event_id independently instead of using one shared value (typically Shopify’s order or checkout token) — so Meta has nothing to match them on.
  2. Two independent systems firing in parallel. Shopify’s native Facebook & Instagram sales channel and a separate GTM-based Meta Pixel/CAPI setup both instrumented at once, each with its own event_id logic that knows nothing about the other. This is the single most common cause of a roughly 2x purchase count.
  3. event_name mismatch. Deduplication keys on event_name plus event_id together. If the server sends Purchase but the browser event is tagged differently, Meta doesn’t even attempt to match them — it correctly treats them as different events, which is a design feature, not a bug, but produces the same inflated count.
  4. Late CAPI delivery. If server events are batched and sent well after the browser event, they can arrive outside the window Meta uses to match events, and get counted separately even with a correct event_id.

How to diagnose it

  1. In Meta Events Manager → Data Sources, select your Pixel/dataset and open the Overview tab. Check the deduplication figure for the Purchase event.
  2. Open Events Manager → Test Events, trigger a real or test purchase, and watch for both the browser and server Purchase events to appear. A working setup shows one merged, flagged event — not two unmerged rows.
  3. On the thank-you page, open the browser’s Network tab, find the outgoing Pixel call (fbevents.js request), and note the event_id parameter it sent.
  4. On the server side, check whatever sends CAPI for that same order — Shopify’s Settings → Customer events (if using the native channel) or the Meta CAPI tag in your GTM server container — and confirm the event_id it sends for the same order matches the browser’s value exactly.
  5. In Shopify Admin → Settings → Apps and sales channels, check whether the Facebook & Instagram channel is installed at the same time as a separate GTM Meta implementation. Running both is the most common single cause of a doubled count.
  6. Confirm event_name parity — both legs must send exactly Purchase, matching case and spelling, for the dedup key to apply at all.
  7. Compare timestamps between the browser event and the CAPI event for the same order in Test Events — a large gap suggests batching delay pushing the server event outside the matching window.

Decision table

CauseSignal you’ll seeFix
No shared event_idTest Events shows two separate Purchase rows for the same order, no dedup indicatorGenerate one event_id per order (e.g., the checkout token) and pass the identical value to both the Pixel call and the CAPI call
Native channel + GTM both firingPurchase count runs roughly double the real order count; both a native Meta channel and a separate GTM setup are installedPick one system as the source of truth for Purchase events and disable it in the other
event_name mismatchDedup ratio stays near zero even though both legs are clearly firingAlign event_name exactly (Purchase) and parameter casing on both browser and server calls
Late CAPI deliveryBrowser event fires immediately; the matching CAPI event appears in Test Events much laterSend CAPI events synchronously at order creation instead of in a delayed batch

Fix it yourself, or bring in help

Checking Events Manager’s overview and Test Events, and confirming whether both a native channel and a separate GTM setup are installed, is something most merchants can do directly in the admin panels — no code required. Where it needs a developer is generating and threading a consistent event_id through both the theme/pixel code and whatever sends CAPI, or deciding which of two overlapping systems to keep and migrating cleanly off the other. If duplicates persist after confirming only one system is active and event names match, the event_id generation logic itself needs rework — that’s a Meta Conversions API engagement, not a settings change.

For the underlying mechanics of how deduplication actually works, see event_id. If low Event Match Quality is a separate concern alongside duplicates, see event match quality. If purchase data itself is missing rather than duplicated, see GA4 not tracking purchases for the equivalent GA4-side diagnosis.

FAQ

What is an event_id, exactly?

It's a unique identifier you generate once per action — one per order, not per event send — and attach to both the browser Pixel call and the server CAPI call for that same action. Meta uses the pair of event_name and event_id to recognize that two events describe the same real-world action and should be merged into one, not two.

Can I run Pixel and CAPI without deduplication at all?

You can, but you shouldn't. Without a shared event_id, every action a browser can see and the server also reports gets counted twice — inflating your conversion count and ROAS in a way that looks good until you scale spend against numbers that aren't real.

How do I know dedup is actually working, versus there just being no duplicates to begin with?

Check Events Manager's Test Events tool during a real or test purchase. If Pixel and CAPI are both firing and working correctly, you'll see both events listed with a deduplication indicator showing they were matched into a single counted event — not just an absence of a second row.

Does Shopify's native Meta channel already handle deduplication for me?

It handles it correctly within itself — the native channel's own Pixel and CAPI calls share an event_id by default. The failure mode is running the native channel alongside a separate GTM-based Meta setup, which introduces a second, independent event_id scheme Meta has no way to reconcile against the first.

Not sure whether your tracking is actually broken?

Start with a Health Check — a fast, read-only diagnosis that tells you what is wrong before you spend anything fixing it. Prefer email? Send your store URL and one sentence about what looks off.