← Blog ·
Browser + server events without double counting
Sending the same Purchase twice is the point of server-side tracking — as long as Meta can tell they are one. Here is how event_id works.
Two messengers, one message
In a server-side setup every Purchase is reported twice on purpose: once by the browser pixel, once by the server through the Conversions API. If Meta counted both, your conversions would double and your ROAS would be fiction. So Meta deduplicates — but it needs your help.
The rule
Meta treats a browser event and a server event as one when they have the same event name and the same event ID, and arrive within 48 hours of each other. In the pixel the ID is the eventID option; in the Conversions API it's event_id.
fbq('track', 'Purchase', { value: 2500, currency: 'BDT' }, { eventID: 'purchase_1042' });
// server: { "event_name": "Purchase", "event_id": "purchase_1042", … }
Where it goes wrong
- No ID in the browser: most pixel snippets never set
eventID, so nothing can match. - Random IDs on both sides: two plugins each generating their own IDs look like two different purchases.
- Different names:
Purchasein the browser andpurchaseorOrderon the server. - Two server sources: a theme plugin's CAPI plus your own — Meta can't dedupe server against server with different IDs.
How TrackPilot avoids it
Our script wraps fbq, so every event gets an ID and the server copy reuses it. Purchases carry purchase_<order id>, which is also what the WooCommerce plugin and your backend send — so a browser Purchase and a server Purchase for order 1042 always match, whichever arrives first. The dedup checker in the dashboard shows the pairs.
Read the deduplication guide for the checklist.