Webclat / Signals
Signals  /  QA  /  CAPI-01

Why doesn't Meta Conversions API deduplicate against my Pixel event even with a matching eventID?

Answer in brief

Meta only deduplicates two events when event_name and event_id match exactly - byte for byte, including case - between the browser Pixel call and the server CAPI call, and both events have to land within Meta's matching window. A regenerated ID instead of a shared one, a case mismatch in the event name, or a delivery delay past the window will each defeat dedup on their own and produce two counted conversions instead of one.

Why this happens

Deduplication is a strict string comparison Meta runs at intake, not a fuzzy match on "roughly the same purchase." Two implementation mistakes look identical in your own logs but break dedup differently: generating a fresh event_id server-side for what is logically the same action instead of reusing the ID the browser Pixel already created, and sending a different event_name string for the client versus the server call for the same action - a capitalization difference (Purchase versus purchase) is enough to make Meta treat them as two unrelated events.

Both mistakes pass basic validation on both sides. The server call still succeeds, the Pixel call still succeeds, and neither produces an error - the only symptom is a doubled conversion count that looks like real growth until someone reconciles it against actual orders.

Fix it

  1. Generate exactly one event_id per real-world event, as early as possible - typically client-side, at the moment the action happens (for example crypto.randomUUID() in the browser on the purchase-confirmation page load).
  2. Pass that same ID to the server: a hidden form field submitted with the order, a dataLayer push read by server-side GTM, or a value your backend already has that is unique per event - never regenerate a new ID server-side for the same action.
  3. Send identical event_name strings on both sides, matching Meta's standard event taxonomy exactly (Purchase, not purchase) unless you are intentionally using a custom event name, in which case use the same custom name on both sides.
  4. If using server-side GTM, confirm the Meta CAPI tag template reads event_id and event_name from the same variables the client-side Pixel tag reads - a common bug is two separate variables populated by two separate pieces of logic that quietly drift apart over time.
  5. Check timing: send both events without an unnecessary delay. Meta's matching window is generous but not infinite, and a batched or queued server send that goes out hours later can miss it.

How to verify it worked

  • In Meta Events Manager's Test Events tool, trigger one real action and confirm exactly one event row appears carrying both a Browser and a Server source tag on that same row - two separate rows for one action means dedup failed.
  • Check the Overview tab's deduplication column over a day of real traffic - a healthy setup shows the large majority of matched pairs collapsing into one counted event; a persistent pattern of duplicates confirms the mismatch is systemic, not a one-off test artifact.
  • Log the raw payload your server sends before the POST and compare the event_id and event_name strings character-by-character against what the browser Pixel actually sent, visible in the Network tab request to facebook.com/tr, for the same action.

Want This Checked On Your Own Setup?

Send us the platform and the symptom and we will tell you whether this is the fix, or whether something else in your pipeline is masquerading as it.

Talk To The Practice