Skip to content

Why the same conversion is counted twice

Reporting the same conversion from two places is normal and usually deliberate. A browser pixel and a server integration both watching the same checkout is how you get coverage when one of them is blocked. The two are meant to overlap.

What makes the overlap safe is an identifier that is the same on both. When that identifier differs, the destination has no way to tell the two apart and counts them separately, which is why reported numbers roughly double for any event sent on both paths.

Where the conversion comes fromWhat deduplicates it
A browser pixel and your server, both reporting a web conversionThe event ID together with the event name, against the same dataset. The match window is 48 hours. Where both arrive within about five minutes of each other, the browser event is the one kept.
An app SDK or MMP and your server, both reporting an in-app actionThe event ID. Send the same value from both and the conversion is counted once.
An offline fileThe transaction ID. The same purchase carrying the same transaction ID resolves to one conversion however many times the file is read.
A CRM lead status changeAn event ID that Signals builds 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.
  • The two paths generate their own IDs independently, so no two ever agree. This is the common one, and it needs the ID to be generated once and passed to both.
  • The event name differs. Purchase and purchase are two events, as are Add To Cart and add_to_cart. The name has to match as exactly as the ID.
  • The events go to two different datasets. Deduplication happens within a dataset, so the same ID sent to two datasets is two conversions.
  • The same file is sent twice for the same date, and the transaction ID is missing or regenerated on each export.
  • A record is re-sent more than 48 hours after the first delivery, which puts it outside the match window and counts it again. This is worth knowing before you run a backfill.
  • Generate the event ID once, at the moment the conversion happens, and pass the same value to every path that reports it.
  • Agree the event names before implementation and write them down, because they have to be identical everywhere.
  • On file sources, map a transaction ID that stays stable across exports. If your system generates a new reference each time it exports, every re-send looks like a new conversion.
  • Keep backfills and replays deliberate rather than routine, and check the date range against the 48 hour window first.
  • Where an app SDK and your server both report the same action, see Set up a deduplication ID across Firebase, your MMP and Signals.

A destination showing a conversion as received from both the browser and the server is the intended behavior rather than a fault. It means both paths are working and deduplication is doing its job. Compare the total against your own records before assuming a problem.