Skip to content

TroubleshootingMeta

Meta CAPI Not Deduplicating: Fix Duplicate Events

Meta Pixel and CAPI reporting the same purchase twice? Diagnose event_id mismatches, double-fire sources, and verify dedup in Events Manager.

Published
Reviewed

Diagnosis

  1. Platform Meta
  2. Usual cause The browser and server events do not share the same event_name and event_id.
  3. Causes, ranked 4
  4. How to diagnose it 7
Go to the checks

First answer free, within one working day. Describe your case

Sounds familiar?

The symptom

Symptom report Meta

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.

Two delivery routes carrying the same key, resolved into one deduplicated event
Tick what you see

Tick the lines that match your store.

Describe my case

The short version

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.

Where to look

Causes, ranked

Pixel and CAPI double-count4 causes

  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.

7 steps

How to diagnose it

Work through them in this order.

  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.

Signal and fix

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

A note from Daniilbefore you decide

Should you 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.

— Daniil

Next

If the self-check does not settle it.

The checks above find the cause in most stores. When two or more overlap, an order-level reconciliation is faster than another afternoon spent comparing dashboards.

Tracking Health Check

Price
USD 395
Access
Read-only
Timeline
verdict two working days after the kickoff

What the reconciliation shows for this symptom.

A Health Check reconciles this symptom order by order against your Shopify orders, so the cause is a fact from your own data, not a guess from a dashboard. Real numbers for this symptom are not published yet — ask for the sample report.

Request a Health Check · USD 395

Follow the order. Then compare the evidence.

  1. Real orderOrder ID, amount, currency
  2. Browser / server eventsConsent, event ID, delivery
  3. GA4 / advertising platformsReceived events and reporting
  4. Reconcile the recordsMatch IDs, time windows and definitions
A completed order and a reported conversion are different records. Check the path and compare like-for-like before treating a difference as missing data.

Questions

Questions this symptom raises

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.

Read more, or check a neighbouring symptom.

All symptoms
Daniil Maximkin

Hi, I’m Daniil.

I work with you from defining the problem to implementation and handover. You talk to the person who does the work. I work in English and Russian.

Tried it and still stuck?

Describe your task

The first answer is free, within one working day. Or write directly: next@taskfordaniel.com