Fixing Facebook event deduplication (event_id) for mobile apps
Updated July 10, 2026 · 6 min read
If you send a purchase from both the client SDK and the Conversions API — which you should — Meta needs to know they're the same event or it double-counts. Deduplication is how it collapses the two into one, and it hinges on a shared event ID.
When dedup is misconfigured you'll see purchases counted twice, or one path discarded so match quality drops. Both are fixable.
How deduplication works
For each purchase you generate a single event ID and send it on both events: the client-side Purchase (via the SDK) and the server-side Purchase (via CAPI). Meta matches on the combination of event name and event ID and keeps one.
The two events should also share the same event name and, ideally, the same value and currency. Meta gives a deduplication window, so the two don't have to arrive at the exact same moment — but they must carry the same ID.
Why deduplication fails
- The client and server generate different event IDs (e.g. each makes its own UUID) — Meta sees two distinct events and counts both.
- Only one path sets an event ID; the other omits it, so there's nothing to match on.
- The event name differs (e.g. 'Purchase' on one path, a custom name on the other).
- The server event is generated fresh on a webhook that never received the client's event ID, so it can't reuse it.
- The two events fall outside Meta's deduplication window because one path is badly delayed.
How to fix it
- 1Generate the event ID once, at the moment of purchase, tied to the transaction (not a random value per call).
- 2Pass that ID from the app into your purchase metadata so the server path (webhook, RevenueCat/Adapty, your backend) can reuse the exact same ID.
- 3Send it as the event ID on the client SDK event and on the CAPI event, with an identical event name.
- 4Verify in Test Events: a correctly deduplicated purchase shows one event with both a 'Browser'/SDK and 'Server' source, not two separate purchases.
Frequently asked questions
Why is Meta counting my app purchases twice?
Because the client-side and server-side Purchase events aren't sharing an event ID (or event name), so Meta treats them as two separate conversions. Generate one event ID per transaction and send that same ID on both paths.
What is event_id in Meta deduplication?
It's a unique identifier you assign to a single conversion and send on both the client and server versions of the event. Meta uses the event ID together with the event name to recognize the two as one event and count it once.
How do I make the server reuse the client's event ID?
Generate the ID in the app at purchase time and pass it through your purchase metadata (for example, in the subscription platform's attributes or your checkout payload) so the webhook or backend that fires the CAPI event can read and reuse the exact same value.
Do the client and server events have to arrive at the same time?
No. Meta applies a deduplication window, so the two can arrive minutes apart. They must, however, carry the same event ID and event name to be matched.
Related guides
Not sure which of these is breaking your app?
Zoruko audits your app code for broken Meta and TikTok signal chains — free — and ships each fix as a pull request you review.
Run a free audit