← All articles

Blog

Meta Pixel + CAPI Deduplication: How to Verify event_id Is Working

meta deduplication event_idpixel capi duplicate eventsfacebook deduplicationmeta duplicate conversions

To measure Meta conversions accurately, you send the same event from both the Pixel (browser) and the Conversions API (CAPI / server) — this is the setup Meta itself recommends. If one side drops out due to consent or browser restrictions, the other can still catch the event, giving you redundancy. But when this "send both" runs without deduplication, a single conversion gets counted twice. A design meant for redundancy turns straight into inflated numbers.

Does any of this sound familiar?

  • Since adding both the Pixel and CAPI, conversions are higher than reality
  • In Events Manager, the same purchase shows up as two events — one browser, one server
  • The total revenue (value) is inflated beyond actual sales
  • You set up deduplication, but the duplicates haven't gone away

This guide organizes why Meta's deduplication is necessary, its condition (event_id plus event name), and how to verify it's actually working across the browser and server sides — from a practical, hands-on perspective.

First principle: "send both" and "double counting" are a hair apart

Start with the premise. Meta recommends running the Pixel and Conversions API together to reduce missed events. The browser side is easy to lose to tracking protection and ad blockers; the server side is largely immune to those. So you send the same event from both, on the assumption that Meta will merge the duplicate into a single event (deduplication).

State What happens
Send one side only Missed events are likely (no redundancy)
Send both + deduplication on Counted correctly as one event (recommended)
Send both + deduplication off The same single event is inflated to two

So the problem isn't "sending both" — it's whether deduplication works once you've sent both. What you need to verify isn't "did it get sent" but "did Meta merge it into one."

The deduplication condition: same event_id + same event name

The condition for Meta to treat a browser-side and a server-side event as "the same one" is simple.

  • Matching event_id … for a single conversion, pass the exact same value from browser and server
  • Matching event_name … use the same event name on both sides, such as Purchase or Lead

Only when these two line up does Meta decide "this is the same occurrence arriving from both browser and server" and merge it into one. The fbp (browser ID, the value of the _fbp cookie) is also used as a supporting signal, but the core axis is always the match on event_id plus event name.

Common pitfall: matching the event name but attaching event_id to only one side. Then it's treated as "same name but a different occurrence," and two events survive without being deduplicated. Conversely, even if you align event_id, an event-name mismatch like Purchase vs. purchase also makes them count as separate things (Meta conversion tracking guide).

The 48-hour deduplication window

Meta does not hold events indefinitely for matching. When a browser-side and a server-side event share the same event_id and event name, Meta will merge them only if both arrive within 48 hours of each other. After that window closes, even a perfect event_id match is ignored — the two events are counted separately.

In practice this rarely causes problems, because the Pixel fires instantly and CAPI typically follows within seconds or minutes. But if your server-side pipeline has a long delay — batch jobs that run overnight, queues that back up on weekends, or retry logic that holds failed events — the CAPI event can land outside the 48-hour window and deduplication silently stops working.

Tip: if you process conversions in batches, keep the delay well under 48 hours. Real-time or near-real-time sending from the server is the safest approach.

How to verify: do the browser-side and server-side event_id match?

Verifying that deduplication works comes down to comparing the event_id on both sides and confirming the same value. Step by step.

1. Read the browser-side event_id

Open your browser's DevTools "Network" tab and filter for facebook.com/tr. Perform the target conversion action once, and check the eid (= event_id) parameter in the request that fires. The eventID from fbq('track', 'Purchase', {...}, {eventID: '...'}) rides here.

2. Read the server-side event_id

On the CAPI side, confirm that the payload your server sends to Meta (data[].event_id) contains the same value. Using your implementation logs or test-event code, compare it against the exact value you confirmed in the browser.

3. Reconcile in Events Manager "Test Events"

Open Events Manager → your dataset → Test Events, and generate one conversion on the site. Two events should arrive — one from the browser, one from the server. If Meta merges them into one as "deduplicated," it will say so. If the two remain listed separately, deduplication isn't working.

Common pitfall: Test Events only shows "this moment, in your environment." Even if it lines up on your machine, if the spot where you generate event_id dynamically in production gets out of sync, duplicates appear only on real visitors' paths. Don't take comfort in a single pattern on your own machine.

Reading deduplication rates in Events Manager

Test Events shows you a single snapshot, but Events Manager also provides aggregate deduplication metrics for ongoing monitoring. To find them:

  1. Open Events Manager and select your dataset (pixel).
  2. Click a specific event name — for example, Purchase.
  3. In the detail view, compare the Received count (total raw events from all sources) against the Deduplicated count (events recognized as duplicates and merged).

The gap between these two numbers is the deduplication that actually happened. A healthy dual-source setup (Pixel + CAPI both firing reliably) typically shows a deduplication rate of roughly 40--70 % for a given event. What the numbers tell you:

Dedup rate Likely meaning
40--70 % Healthy — both sources are firing and Meta is merging them
Near 0 % event_id is not being passed or is not matching
Near 100 % Unusual — possibly one source is not reaching Meta at all

Note: deduplication rates in the Overview tab are not real-time. Allow at least 48--72 hours of live traffic before drawing conclusions, especially right after deployment.

Common reasons deduplication doesn't work

You added event_id but the duplicates won't go away — here are the typical patterns.

1. The event_id differs between the two sides

The most common cause. If the browser and server generate event_id independently, the values won't match and they're treated as different things. event_id needs a mechanism that always produces the same value on both sides — pass the value generated on the browser side to the server, or derive the same value from shared logic.

2. event_id exists on only one side

You pass eventID to the Pixel but don't include event_id in CAPI (or vice versa). With nothing on one side there's nothing to reconcile, and deduplication never happens.

3. The event name doesn't match

Purchase vs. purchase, or mixing a standard event with a custom event — an event-name mismatch also disables deduplication. Use the exact same name on both sides.

4. fbp / fbc aren't being passed

If fbp (browser ID) or fbc (click ID), used for supporting reconciliation, aren't passed to the server side, it affects reconciliation accuracy and match quality. The event_id match is the main axis, but passing these as well is the preferable setup.

Passing event_id through GTM Server-Side

If you use Google Tag Manager (GTM) Server-Side for your CAPI implementation, the flow for keeping event_id consistent across both sides typically looks like this:

  1. Generate event_id on the client. In your website JavaScript (or a client-side GTM tag), create a unique ID (a UUID or order ID) for each conversion.
  2. Pass it to the Pixel. Include the ID as eventID in your fbq('track', ...) call.
  3. Forward it to the server container. Send the same ID as a parameter in your GA4 event (or via a custom data-layer variable) so it reaches the server-side GTM container.
  4. Map it in the Meta CAPI tag. In your server-side Meta tag configuration, map the incoming parameter to the event_id field.

The critical point: the client and the server must use a single source of truth for the ID. If the server container generates its own ID instead of reading the one the client sent, the values diverge and deduplication breaks. For a broader look at verifying your server-side GTM setup, see server-side GTM verification.

What checking on your own machine can't tell you

Checking once, by hand, on your own machine has two structural limits.

  1. Your environment isn't your visitors' environment. Depending on login state, extensions, and consent status, event_id can look aligned on your machine yet have deduplication break under real visitor conditions (only the browser side drops when consent is denied, the timing of event_id generation slips on a particular traffic source, and so on).
  2. Conversions involving an ad click are hard to verify. To properly recreate "does it really get merged into one via an ad," you'd need to click a live ad and follow the path — which carries the risk of an ad-policy violation as a self-click.

In other words, confirming "the event_id lines up" on your own action is not proof that deduplication works on the real path your visitors take.

Verification checklist

  • Do the Pixel and CAPI pass the same event_id for the same conversion?
  • Does the event name (event_name) match exactly on both sides (including case)?
  • Did you actually reconcile the browser-side eid against the server-side event_id?
  • Did you confirm the "deduplicated" status in Test Events?
  • Is event_id unique per conversion and identical on both sides?
  • Are fbp / fbc passed to the server side as well?
  • Beyond a single pattern on your machine, is it duplicate-free under real production visitor conditions?

Frequently asked questions

Q. Should I install both the Pixel and CAPI in the first place? A. Yes — it's Meta's recommendation. If one side drops out to consent or browser restrictions, the other can still catch the event, giving you redundancy. But that holds only on the premise that deduplication (event_id + event name) is working. If it isn't, sending both becomes double counting outright (the basics of double counting).

Q. What value should event_id be? A. Any value that uniquely identifies a single conversion (an order ID, for instance) works, as long as you use the same one on browser and server. The two things that matter: "unique per conversion" and "identical on both sides." It won't work if a different value is assigned each time, or one side is empty.

Q. I matched the event name but the duplicates won't clear. A. Most likely the event_id doesn't match on both sides. Check whether the value generated on the browser side is really passed to the server, and whether independent generation has caused the values to diverge (verifying CAPI).

Q. If Test Events says deduplicated, is production fine too? A. Test Events is a check of your environment, at that moment. In production, the assignment and matching of event_id can break depending on consent status and traffic source, and a single pattern on your machine may not reproduce it. Verification under real visitor conditions is needed.

Q. I also want to know how to verify the Pixel itself. A. Verifying the Pixel's installation, firing, and receipt on their own is covered in a separate article (verifying the Meta Pixel). The deduplication in this article is the next stage — making the Pixel and CAPI coexist.

Conclusion: "send both" isn't done until it "merges into one"

Installing both the Pixel and CAPI is Meta's recommendation and a sound design for reducing missed events. But that rests on the premise that Meta merges them into one (deduplication) via the same event_id plus the same event name. If deduplication doesn't work, a design meant for redundancy becomes the cause of double counting. Start by reconciling the event_id on both sides, and confirm "deduplicated" in Test Events.

Still, a single check on your own machine can't catch deduplication that breaks only on real visitors' paths. ConversionOK runs your live page in an independent, isolated browser and intercepts the Pixel and CAPI events actually sent (and whether their event_id match), then verifies them — with no need to click your own ad and no interference from your office environment. Start with a free static check to confirm the entry point of your measurement.