What This Tutorial Covers
By the end, every purchase will carry one shared event ID across the pixel and the server event, both events will use the same event name, and Meta's event tools will confirm the two are being deduplicated instead of counted separately.
You will need:
- A Meta pixel (dataset) installed on your funnel and firing Purchase events
- The Conversions API configured to send the same events server-side, whether through a tracker or a custom endpoint
- Access to your thank-you page or checkout template so you can control the event ID
- Access to Events Manager to verify the result
I will use ClickerVolt as the reference layer where it makes the setup concrete, because it fires the pixel and server events from one place with a shared event ID by default. The same steps apply to any stack using RedTrack, FunnelFlux Pro, a custom server, or a manual pixel-plus-CAPI setup. I will flag where a two-system setup adds risk.
Why This Matters Before You Touch a Setting
A quick refresher on the mechanism, because the fix only makes sense if you hold the shape in your head. Meta reconciles the pixel report and the server report of the same conversion using a matching key: a shared event ID plus the event name. Same ID and same name, Meta keeps one. Different ID, missing ID, or mismatched name, Meta keeps both and your count doubles.
Deduplication succeeds or fails on one thing: whether the pixel and the server event carry the same event ID for the same sale.
Step 1: Generate One Event ID at the Moment of Purchase
Create a single unique identifier for the conversion at the instant it happens, before either event fires. A UUID works. An order ID works, as long as it is unique per purchase and available to both the browser and the server. The rule that matters: this ID is generated once and reused, never generated separately on each side.
Failure point: the most common break is generating the event ID independently in the pixel and again in the server code. Two independent IDs never match, so nothing deduplicates. Generate it in one place and pass it to both.
If your tracker owns the conversion, it should mint this ID for you. On ClickerVolt the shared event ID is created once per conversion and attached to both the pixel and the server event automatically, so there is nothing to wire here. On a hand-built setup, this is step one and it is on you.
Step 2: Send the ID on the Pixel Event
When the browser pixel fires the Purchase, attach the event ID as eventID. In a standard fbq call that is the fourth argument:
fbq('track', 'Purchase',
{ value: 49.00, currency: 'USD' },
{ eventID: 'abc123' }
);
The eventID value here must be the exact ID you generated in step 1. Read it from wherever you stored it, do not create a new one inline.
Failure point: hardcoding, regenerating, or misspelling the key. Meta expects eventID (camel case) on the pixel side. Send event_id there, or a freshly generated value, and the browser event will not match the server event.
Step 3: Send the Same ID on the Server Event
When the Conversions API fires the same Purchase from your server, include the identical ID as event_id in the event payload, along with a matching event_name:
{
"event_name": "Purchase",
"event_time": 1720000000,
"event_id": "abc123",
"action_source": "website",
"user_data": { ... },
"custom_data": { "value": 49.00, "currency": "USD" }
}
Note the two things that must line up across both channels: the ID (eventID on the pixel, event_id on the server) must be the same value, and event_name must be identical, "Purchase" on both. Meta matches on the pair, not on the ID alone.
Failure point: mismatched event names. If the pixel sends "Purchase" and the server sends "purchase" or a custom name, the dedup fails even when the IDs match. Keep the event name byte-for-byte identical on both sides.
On a tracker that fires both events, this is handled for you. On a two-system setup, where the pixel lives in your page template and the server event lives in your backend or a separate tool, this is the seam where the ID gets lost, because two teams or two configs have to agree on one value. That seam is exactly why single-layer tracking removes the risk.
Step 4: Verify the Deduplication in Events Manager
Do not trust that it works because it deployed. Confirm it. In Events Manager, open your dataset and look at the event details for Purchase. Meta surfaces whether incoming events are being received as deduplicated, and its diagnostics will flag duplicate or unmatched events. You want to see the pixel and server events pairing up, not stacking as two separate counts.
Give it a little time to populate after a test purchase, then check that a single real purchase shows as one deduplicated conversion, not two. If you see the count doubling, walk back through steps 1 to 3: the ID is being regenerated, one side is missing it, or the event names disagree.
Failure point: assuming a one-time check is forever. A deploy that changes how the page or the backend generates the event ID silently breaks the match with no error. Re-verify after any change that touches conversion firing.
Step 5: Lock It Against Regression
Because dedup fails silently, the last step is making the failure loud. Add a check to your release process: after any deploy that touches the thank-you page, the pixel, or the server event, do a test conversion and confirm in Events Manager that it deduplicated. Treat a sudden jump in reported conversions with no matching jump in real sales as a dedup regression until proven otherwise.
If your tracking layer stamps both events with one ID by construction, this class of regression mostly disappears, because there is no second system to drift out of sync. If you are wiring two systems together, this verification is not optional. It is the difference between catching double-counting in a test and discovering it three weeks into a scaled campaign built on inflated numbers.
The Setup That Removes the Risk
Every failure point above comes from the same root: two channels that have to agree on one value, wired together by hand. The pixel and the server event are the same sale, but in a two-system setup they are generated by two different pieces of code that can drift apart on any deploy.
A tracking layer that owns both events removes the seam. ClickerVolt generates one event ID per conversion and fires both the pixel and the Conversions API event with it, so the pair deduplicates by default and stays deduplicated through your deploys. See how one layer keeps the pixel and server event in sync. Whatever you run, the rule is the same: one ID, both sides, matching event name, and verify it before you trust the number.
FAQ
How do I deduplicate Meta pixel and CAPI events?
Generate one event ID at the moment of purchase, send it on the pixel event as eventID and on the Conversions API event as event_id, use the same event name on both, and verify in Events Manager that the events are being deduplicated.
What is the eventID on the Meta pixel?
It is the unique identifier you attach to a pixel event so Meta can match it to the same event sent server-side. On the pixel it is passed as eventID; on the Conversions API the same value is passed as event_id.
Why is Meta double counting my conversions?
Because the pixel event and the server event are not carrying the same event ID, or the event names do not match, so Meta cannot tell they are the same sale and counts both. Fix the shared ID and matching name and the duplicates collapse to one.
Do I need the same event name on the pixel and the server?
Yes. Meta deduplicates on the event ID plus the event name together. If the IDs match but one side sends "Purchase" and the other sends a different name, the events will not deduplicate.
How do I verify deduplication is working?
Run a test purchase, then check the event details for that event in Events Manager. Meta's diagnostics show whether events are being received as deduplicated or counted separately. Re-verify after any deploy that changes how conversions fire.
