Deduplication
Running a pixel and a server side connection together is the right setup. It also means the same conversion reaches the platform twice. Deduplication is how the platform recognizes the pair as one event.
Get it wrong and your reported conversions inflate, your cost per acquisition looks better than it is, and the platform optimizes against numbers that are not real.
How it works
Section titled “How it works”Both copies of the event carry the same identifier. When the platform sees a second event with an identifier it has already recorded, it discards the duplicate instead of counting it.
Two things have to match, not one: the event ID and the event name. An event sent as Purchase from the browser and purchase from the server will not deduplicate.
You set the event ID
Section titled “You set the event ID”This is the part most implementations get wrong, so it is worth being blunt about it. Datahash does not generate an event ID for you. You set it, on both copies, and you keep it identical.
Meta’s guidance is to use a value that already exists and is naturally unique, such as an order number or transaction ID. For events with no intrinsic identifier, a random value works, provided the same value is sent from browser and server.
The requirement is not that the value is clever. It is that both copies carry it.
Per platform keys and windows
Section titled “Per platform keys and windows”| Platform | Key | Window | Notes |
|---|---|---|---|
| Meta | event_id plus event_name | 48 hours | The pixel eventID is the fourth argument of fbq track and must equal the Conversions API event_id. |
| TikTok | event_id | 48 hours | Identical event plus event ID within the window is deduplicated. |
| Snapchat | Pixel client_dedup_id equal to CAPI event_id | 48 hours | Values must be byte identical for the same Pixel ID and event name. |
Meta specifics
Section titled “Meta specifics”Where a server event and a browser event arrive within about 5 minutes of each other, Meta favors the browser copy.
Meta also supports a fallback using fbp or external_id, but it only works for events sent first from the browser and then through the server. It is not a substitute for a shared event ID.
Snapchat specifics
Section titled “Snapchat specifics”Two Snapchat details cause real problems.
- Auto-generated pixel IDs prefixed
@-exist only in the browser. They can never match a Conversions API event, so an implementation relying on them will never deduplicate. - For PURCHASE, Snapchat also accepts a pairing of the pixel
transaction_idwithorder_idincustom_data, which gives a 30 day fallback window alongside the 48 hour event ID window.
App events
Section titled “App events”The same rule applies across app sources. Send a unique event_id and keep it identical across every source reporting the same action, including any mobile measurement partner. Where an MMP and Signals both report a purchase, matching event names and matching event IDs are what stop it counting twice. See Set up a deduplication ID across Firebase, your MMP and Signals for where the value goes in each SDK.
Offline files and CRM leads
Section titled “Offline files and CRM leads”Two source types deduplicate on something other than an event ID you set.
| Source | Key | Notes |
|---|---|---|
| An offline conversions file | transaction_id | The same purchase carrying the same transaction ID resolves to one conversion however many times the file is read. Map a reference that stays stable across exports: a system that generates a new one each time makes every re-send look like a new conversion. |
| A CRM lead status change | An event ID Signals derives | Built from the Meta lead ID and the last modified date. A lead re-synced without changing produces the same ID; a real status change produces a new one. |
Resending a record more than 48 hours after the first delivery puts it outside Meta’s match window and counts it again, which is worth checking before you run a backfill.
Verifying it works
Section titled “Verifying it works”In Meta, open Events Manager, then Event Details, then the Event Deduplication tab.
Meta’s own reading of the result: low Overlap means the implementation is either sending non-unique dedupe keys, or sending events with a dedupe key from only one source. In practice a low overlap almost always means the server copy has an event ID and the browser copy does not, or the two are generated independently.

