Tracking & Attribution

Why Is My Meta CAPI Not Deduplicating? A Debug Guide

Meta CAPI deduplicates events when Pixel and CAPI share event_id, event_name, and timing. Debug guide for mismatched event_id and double-counting.

Quick answer

Meta CAPI deduplicates browser Pixel events and server CAPI events that share the same event_id, event_name, and arrive within roughly 48 hours of each other. If your events are duplicating, the cause is almost always one of three things: mismatched event_id between Pixel and CAPI, mismatched event_name, or a missing _fbp/_fbc cookie on the CAPI event. This article walks through the diagnostic in order.

The good news: deduplication failures look dramatic in reporting (doubled conversion counts, inflated ROAS, broken cost-per-result math) but the actual fixes are usually small — a misplaced hash, a casing inconsistency, a missing parameter on the server payload. The five most common causes account for roughly 90% of the failure modes we see in the field. Work through them in order.


How does Meta CAPI deduplication actually work?

Meta CAPI deduplication is a server-side process inside Meta’s ingestion layer. When Meta receives two events with the same event_id and event_name from the same Pixel ID within roughly 48 hours, it treats them as the same conversion. One event is kept for optimization, reporting, and audience-building. The other is discarded.

The selection isn’t random. Meta keeps the event with the higher match quality — the one with more customer-data parameters, correctly hashed, with valid _fbp and _fbc values. In almost every dual setup, the CAPI event wins because it carries hashed PII (email, phone, name) drawn from the server side, while the Pixel event carries only what the browser captured automatically. The Pixel event is what gets discarded.

The asymmetry has a practical implication: a well-configured CAPI integration makes the Pixel mostly redundant from a matching-data perspective. The Pixel’s remaining value is setting the _fbp cookie on first visit and view-through attribution — not most of the conversion signal.


What are the three rules for successful deduplication?

Meta’s published deduplication requirements come down to three rules. All three must hold for the events to merge.

Rule Requirement Common failure mode
1. event_id must match exactly Same string on Pixel and CAPI, character-for-character, case-sensitive Pixel uses one ID format (UUID), CAPI uses another (database row ID)
2. event_name must match exactly Same string, same case Purchase on Pixel, purchase on CAPI — silent mismatch
3. Events must arrive within ~48 hours of each other First and second event seen by Meta no more than 48h apart Server fires CAPI immediately on conversion; Pixel fires 3 days later from a cached page

The event_id rule is the single largest failure cluster. Meta has no published “fuzzy match” logic — two events with event_id values of ord-12345 and Ord-12345 are treated as different conversions. The same applies to leading or trailing whitespace, hidden Unicode characters, and any quoting differences if the IDs were JSON-encoded by one side and not the other.

The order of arrival doesn’t matter inside the 48-hour window. CAPI can fire before the Pixel or after; Meta deduplicates either direction. What matters is that both arrive, both match, and both make it within the time window.


Why are my events duplicating? (The five most common causes, ranked)

The diagnostic tree, in descending order of frequency. Walk through each one before assuming the next.

Cause 1: The event_id doesn’t match (≈60% of cases)

By far the most common. The Pixel generates one ID; the server generates another. Meta sees two different IDs and counts two events.

Diagnostic: Open Meta Events Manager → Test Events. Trigger a single conversion. Compare the event_id on the Browser event and the Server event. Are they identical character-for-character?

Fix: Generate the event_id in one place — either the browser (which then sends it to your backend so CAPI uses the same value) or the server (which then sends it to the browser via the response, set on the Pixel call). The pattern most setups use: generate a UUID server-side at the moment of conversion, include it in the response, fire both the Pixel and CAPI with that same UUID as event_id.

// Pixel side
fbq('track', 'Purchase', {value: 49.99, currency: 'USD'}, {eventID: 'order_abc123'});
 
// CAPI side - SAME event_id
{
  "event_name": "Purchase",
  "event_id": "order_abc123",
  "event_time": 1717891234,
  "event_source_url": "https://example.com/checkout/success",
  "action_source": "website",
  "user_data": { "em": ["<sha256>"], "fbp": "fb.1.1717891000.123456789" },
  "custom_data": { "currency": "USD", "value": 49.99 }
}

Cause 2: The event_name doesn’t match (≈15% of cases)

Case sensitivity is the silent killer. Meta’s standard events use PascalCase — Purchase, Lead, CompleteRegistration, AddToCart, InitiateCheckout. Sending purchase from the server or PURCHASE from a tag manager produces a mismatch.

Diagnostic: Compare the event_name field on the Browser and Server events in Test Events. They must match exactly, including case.

Fix: Standardize on Meta’s published PascalCase names for standard events. For custom events, pick a casing convention and enforce it across both Pixel and CAPI through a shared constant.

Cause 3: Missing _fbp or _fbc on the CAPI event (≈10% of cases)

The deduplication itself can succeed even without _fbp/_fbc, but the result is a Server event with low Event Match Quality (EMQ) — which Meta is less confident attributing to a real user. In some accounts the missing cookies cause the CAPI event to be counted as a separate, unmatched conversion instead of a duplicate of the Pixel event.

Diagnostic: Open the Server event payload in Test Events. Confirm user_data.fbp is present and starts with fb.1.. Confirm user_data.fbc is present when the user arrived from a Meta ad (URL contained fbclid).

Fix: Read the _fbp cookie from the request on the server, and pass it as the fbp parameter in the CAPI payload. When the user has fbclid in the URL, wrap it in Meta’s _fbc format (fb.1.<creation_time_ms>.<fbclid>) and pass as fbc. Both values must be sent unhashed — Meta explicitly does not want hashed fbp or fbc.

Cause 4: Time-stamp drift between Pixel and CAPI (≈8% of cases)

If event_time on the two events differs by more than ~5 minutes, Meta may not associate them even if event_id matches. The cause is usually a server clock that’s drifted, or a server-side queue that delays CAPI dispatch by hours.

Diagnostic: Compare event_time Unix timestamps on the Browser and Server events for a single conversion. Convert to UTC; the gap should be under 60 seconds for a real-time CAPI dispatch.

Fix: Run NTP on the server to keep the clock accurate. Send CAPI events as close to real-time as possible — queueing for batch processing is fine for offline events but adds dedup risk for online ones. If you must delay, include event_time as the conversion’s actual time, not the CAPI dispatch time.

Cause 5: Multiple Pixels firing (≈7% of cases)

A site with two Meta Pixels installed (often inherited from a tag manager migration) will fire the conversion event twice from the browser — once per Pixel. CAPI fires once. The first Pixel matches CAPI; the second Pixel has no CAPI counterpart and shows up as a separate, unmatched conversion.

Diagnostic: Use Meta’s Pixel Helper Chrome extension on the conversion page. Look for multiple Pixel IDs firing the same event. If you see more than one, that’s the cause.

Fix: Remove the duplicate Pixel or consolidate the two Pixel IDs into a single one in Events Manager. If both Pixels are needed (e.g., agency tracking + brand tracking), fire CAPI separately to both Pixel IDs so each has its server-side match.


How do I verify deduplication is working in Test Events?

Meta’s Test Events tool inside Events Manager is the right place to debug deduplication in real time. The production EMQ score updates only every ~48 hours, so production data is too slow to iterate on; Test Events shows events within seconds.

The verification steps:

  1. Open Events Manager → Data Sources → your Pixel → Test Events tab.
  2. Enter your test browser’s URL and Meta will append a ?test_event_code= parameter. Visit the conversion page through that URL.
  3. Trigger a real conversion in the test browser — submit the form, complete the test purchase, fire whatever event you’re debugging.
  4. Watch the Test Events feed in Events Manager. Within 5–15 seconds you should see two entries appear: one with Source: Browser (the Pixel), one with Source: Server (CAPI).
  5. Confirm both rows show “Deduplicated” in the right-hand status column. If they both show “Deduplicated,” the merge worked. If one shows “Deduplicated” and the other shows “Received,” the events arrived but didn’t merge — usually an event_id or event_name mismatch. The Test Events tool will also show the full event payload on click. Compare event_id, event_name, and event_time between the two side-by-side; any difference is the failure cause.

Once Test Events confirms the merge, production behavior follows the same logic with the production payload — the only difference is the 48-hour EMQ refresh cadence.


What if my server fires CAPI before the browser fires the Pixel?

Order doesn’t matter inside the 48-hour window. Meta deduplicates regardless of which event arrives first.

The CAPI-first pattern is actually preferred for some setups — a server-side conversion (a backend purchase webhook, a CRM lead-creation event) fires CAPI immediately, while the browser-side Pixel fires only when the user’s confirmation page loads. If the user closes the browser tab before the confirmation page loads, the Pixel never fires at all — but CAPI already did, and the conversion is still counted.

The edge cases worth knowing:

  • CAPI-only setups. If you’ve removed the Pixel entirely, there’s nothing to deduplicate against. Every CAPI event is a single conversion. This is the cleanest architecture when it works — see Meta Pixel vs Conversions API for when it’s the right choice. (TODO: live link when that piece publishes.)
  • Pixel fires twice (cached form submission). Some browser back-button behavior re-fires the Pixel from cache. The duplicate Pixel hits the same event_id and gets discarded on the second arrival — no double-counting, but the server-side log may show two browser-event lines.
  • CAPI retries. If your CAPI dispatch retries on transient HTTPS errors, send the retried event with the same event_id. Meta deduplicates the duplicate CAPI calls against the original CAPI event automatically. The 48-hour window is generous enough to cover almost every real workflow. Setups that exceed it (offline conversions that close 60+ days later) need a different attribution path — see Meta’s offline-conversion documentation.

How does PartialLeads handle deduplication automatically?

The five failure modes above account for the bulk of CAPI deduplication issues in the field. Each one is a configuration detail that has to be implemented correctly and stay correct across deploys, code refactors, and tag-manager migrations. PartialLeads’ managed integration removes all five from the customer’s responsibility:

  • Single source of event_id. The PartialLeads tag generates a UUID server-side at the moment of conversion and writes it to both the Pixel call (as eventID) and the CAPI payload (as event_id) in a single round-trip. There’s no parallel ID generation on two systems that can drift apart.
  • Standardized event_name constants. Standard Meta events (Purchase, Lead, CompleteRegistration, AddToCart, InitiateCheckout) are mapped to the correct PascalCase string in both the Pixel call and the CAPI payload. Case mismatches don’t happen because the customer doesn’t type the event names — the tag does.
  • Synthetic _fbp and _fbc handling on both sides. When a visitor lands without a _fbp cookie, the tag generates one in Meta’s format (fb.1.<creation_time_ms>.<random_number>) and writes it as a first-party cookie. The same value goes on the Pixel call and into the CAPI payload’s user_data.fbp parameter. For _fbc, the tag captures fbclid from the URL, wraps it in fb.1.<timestamp>.<fbclid> format, and writes the cookie. Both Pixel and CAPI see the same values.
  • Real-time CAPI dispatch. CAPI events are sent within seconds of the browser-side Pixel, so the event_time values stay aligned. No queueing delays, no clock-drift risk on a managed backend.
  • Single Pixel ID per integration. The tag installs once per site and fires once per conversion. The “multiple Pixels firing” failure mode is structurally impossible. The result for the customer is a deduplication setup that just works. Test Events shows both Browser and Server entries marked “Deduplicated” within 15 seconds of the first conversion, EMQ climbs above 8 inside the first 48 hours, and the dual-source conversion counts stay accurate without the customer touching the underlying configuration.

For accounts that previously had deduplication broken (the most common symptoms: ROAS inflated by 30–80%, EMQ stuck below 5, cost-per-result figures that don’t match backend revenue), switching to a managed setup typically restores accurate reporting inside one EMQ refresh cycle.


Sources

  1. Meta for Developers — Deduplicate Pixel and Server events: https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events
  2. Meta for Developers — Conversions API documentation: https://developers.facebook.com/docs/marketing-api/conversions-api
  3. Meta for Developers — Test Events tool: https://developers.facebook.com/docs/marketing-api/conversions-api/payload-helper
  4. Meta for Developers — fbp and fbc parameters: https://developers.facebook.com/documentation/ads-commerce/conversions-api/parameters/fbp-and-fbc
  5. Meta for Developers — Conversions API best practices: https://developers.facebook.com/docs/marketing-api/conversions-api/best-practices
  6. Meta Business Help — About Event Match Quality: https://www.facebook.com/business/help/765081237991954

Frequently asked questions

QWhat exactly happens when deduplication fails — does Meta count the conversion twice or zero times?
Twice. When the Pixel and CAPI fire for the same conversion but Meta can't match them via `event_id`, both events are counted as separate conversions. The result is reported conversions inflated by up to 2x, ROAS figures that look better than reality, and a confusing gap between what Meta reports and what your backend shows. The zero-count scenario only happens when neither Pixel nor CAPI fires correctly — that's a different problem from deduplication failure.
QHow long does Meta wait before deciding two events aren't duplicates?
Meta's published deduplication window is roughly 48 hours. If a second event with matching `event_id` and `event_name` arrives within that window, it's deduplicated against the first. After 48 hours the window closes and any later arrival is counted as a separate conversion. The window applies symmetrically — neither Pixel-first nor CAPI-first matters, as long as both arrive within 48 hours of each other.
QWhy does Meta keep the CAPI event instead of the Pixel event when they deduplicate?
Because Meta keeps the event with **higher match quality** — the one with more customer-data parameters, correctly hashed, with valid `_fbp` and `_fbc` values. CAPI events are typically configured to send hashed email, phone, name, and address from the server's CRM data; Pixel events default to browser-only information. The richer CAPI event wins almost every time, which means in a properly-configured dual setup the Pixel is mostly redundant for matching purposes.
QCan I check deduplication in production without using Test Events?
Yes, by comparing your backend conversion counts to Meta's reported counts. If Meta is reporting 2x what your CRM or shop reports, deduplication is failing. The Test Events tool is faster for real-time debugging because the production EMQ score and conversion count refresh on a 48-hour cycle, while Test Events shows events within seconds. Both are valid — Test Events for iteration, production reconciliation for ongoing monitoring.
QShould the `event_id` be a UUID, a database ID, or something else?
Any unique string works, as long as it's the same on both Pixel and CAPI for the same conversion. UUIDs (`crypto.randomUUID()` in Node.js, `uuid.uuid4()` in Python) are the safest default because they're guaranteed unique without coordination. Database IDs work when you can guarantee the ID is generated before both Pixel and CAPI fire. Avoid timestamps, hashes of the page URL, or anything that could collide between two simultaneous users.
QDo offline conversions need `event_id` deduplication?
Only if you're also sending the same conversion via the browser Pixel. Offline-only conversions — sales-team-closed leads, in-store purchases, phone-call closes — fire CAPI as a single source with no Pixel counterpart, so there's nothing to deduplicate against. The `event_id` is still useful for your own internal tracking, but Meta won't be matching it against another event. The standard pattern: include `event_id` for consistency, but don't lose sleep over uniqueness when there's no parallel browser event.
QWhat's the difference between deduplication and Event Match Quality (EMQ)?
They measure different things. Deduplication is about whether Meta correctly merges two events for the same conversion (success = one conversion counted). Event Match Quality is about whether Meta can match the conversion event back to a real Meta user (success = a high EMQ score, 8–10). A setup can have perfect deduplication and terrible EMQ (events merge but don't match users), or vice versa (events match users but get double-counted). Both need to work for tracking to be accurate.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.