Event Deduplication: Facebook CAPI + Pixel

The same deposit can get counted twice by Facebook — once from the browser pixel on the witrina, once from a server-side CAPI postback. Here's how event_id glues those two signals into a single event, and why skipping it leaves your optimization running on inflated numbers.

Why a conversion doubles up

One real deposit can physically generate two Facebook signals: a client-side one, fired by the pixel in the browser on the witrina, and a server-side one, sent via CAPI postback from Keitaro after the affiliate network confirms it. If Facebook can't tell these are the same event, it counts both, and your conversion numbers end up roughly double the real figure.

How event_id works

event_id is a unique string you generate for each real-world event — a specific deposit, a specific lead — and send identically on both calls, the pixel one and the server one. Facebook matches events on the pair event_name plus event_id within a time window, keeps one record, and flags the other as a duplicate rather than a new conversion.

Where to generate event_id in a PWA + Keitaro setup

The cleanest approach is generating the identifier at the moment the event itself happens — when the deposit postback arrives, for instance — and passing it into both channels at once: the server-side CAPI call from Keitaro, and the pixel call on the witrina if it fires for the same action. What matters is that it's the exact same string on both ends, not two similar-looking but different values.

The rules that most often break dedup

The most common mistake is using different event_name values on the pixel and CAPI sides for the same action — Lead on the client, CompleteRegistration on the server, say — so Facebook never even attempts to match them. The second is regenerating event_id on every retry instead of reusing the original value. The third is too large a time gap between the client and server events, pushing them outside the matching window.

How to verify dedup is actually working

In Facebook Events Manager's test events tab, both calls for the same action should show the identical event_id with a deduplication flag. It's also worth reconciling confirmed deposits from the affiliate network over a control period against the conversions Facebook actually counted — if the numbers differ by a wide margin, dedup isn't configured correctly.

What clean dedup buys you for optimization

Facebook's algorithm optimizes delivery toward whatever target action it sees, and it only does that well if the input numbers are honest. Doubled conversions artificially understate the real cost per action and push the system to scale something that actually costs more than it appears to — clean dedup gives your budget decisions solid ground again.

FAQ

Can I set up dedup without my own server, just through Keitaro?
Yes — Keitaro's outgoing CAPI integration can generate and pass event_id under the same rules without a separate backend; the mechanism only needs a consistently shared identifier.
Does event_name have to match for dedup to work?
Yes, Facebook matches on event_name and event_id together — if the event names differ, dedup won't kick in even when the id matches.
Can a conversion double up without CAPI at all, just on the pixel?
Less often, but yes — a script refiring on a page reload is one example — and the same event_id principle protects against that case too.
How do I tell if conversions are being lost instead of doubled?
Compare confirmed conversions in the affiliate network or Keitaro against events Facebook actually received — if Facebook's count is noticeably lower, you're losing data, not doubling it.
Does APEX need separate configuration for dedup?
APEX passes clickid and event data cleanly from the witrina through to the postback, so the one thing left on you is using a single event_id on both ends of the chain.
Build your PWA in APEX in minutes

Cloaking, anti-bot, push, split tests and your own domains — in one service.

Get started free

Read also