Meta Conversions API: why pixel-only tracking under-reports your leads
If you are running Meta on the pixel alone, you are hiding a meaningful share of your own conversions from the algorithm that needs them most.
Since iOS 14.5 there has been a gap between the leads that arrive in your inbox and the leads Meta thinks it produced. If you have ever counted twelve enquiries and seen Ads Manager report seven, this is why.
Why the pixel loses events
The pixel is JavaScript. It runs in the visitor's browser, and it needs three things to survive: the script must load, it must be allowed to set and read identifiers, and the request back to Meta must not be blocked.
All three fail routinely:
- App Tracking Transparency. A large share of iOS users decline tracking, which limits what the pixel can attribute.
- Safari ITP caps first-party cookie lifetime at seven days, so a longer consideration window silently loses its attribution.
- Ad blockers block
connect.facebook.netoutright, so the pixel never loads at all. - Consent banners — correctly — hold the pixel back until consent is given, and not everyone gives it.
None of these mean the conversion did not happen. They mean Meta cannot see it. And an optimisation algorithm cannot optimise towards conversions it cannot see, so your campaigns are being steered by a partial, biased sample of your real results.
What the Conversions API changes
CAPI sends the event from your server directly to Meta, over HTTPS, server to server. There is no browser in the path, so there is nothing to block. If your form handler ran, the event fires.
The point is not really the reporting. It is that Meta's bidding model gets a fuller picture of who actually converts, and gets measurably better at finding more of them.
The part people get wrong: deduplication
Run the pixel and CAPI together and Meta will see the same conversion twice unless you tell it they are the same event. You do that with a shared event_id.
Generate one identifier per conversion, pass it to both:
// browser
var eventId = 'lead_' + Date.now() + '_' + Math.random().toString(36).slice(2, 10);
fbq('track', 'Lead', { content_name: 'Audit request' }, { eventID: eventId });
// then send the SAME eventId to your server with the form post
And server-side, in the handler that processes the form:
$payload = [
'event_name' => 'Lead',
'event_time' => time(),
'event_id' => $eventId, // identical to the browser one
'action_source' => 'website',
'event_source_url' => $pageUrl,
'user_data' => [
'em' => [hash('sha256', strtolower(trim($email)))],
'ph' => [hash('sha256', preg_replace('/\D/', '', $phone))],
],
];
Worth knowing: email and phone must be SHA-256 hashed, and normalised before hashing — lowercase and trim the email, strip everything but digits from the phone. Hash an unnormalised value and it simply will not match, so you lose the benefit while believing you have it.
Matching quality is the number to watch
In Events Manager, each event has an Event Match Quality score. It reflects how much identifying information you send and how well it matches a real account.
| Score | Reading | Usual cause |
|---|---|---|
| Below 4.0 | Poor | Only sending an IP and user agent |
| 4.0 – 6.0 | Workable | Hashed email only |
| 6.0 – 8.0 | Good | Email plus phone, correctly normalised |
| Above 8.0 | Excellent | Email, phone, name, location, click ID |
Send fbc and fbp as well — those are the click and browser identifiers Meta itself set, and they are the strongest match signals available. They sit in cookies of the same name.
How to verify it actually works
- Open Events Manager → Test Events and grab the test code.
- Submit your own form. You should see the event arrive twice, marked browser and server.
- Confirm the deduplication notice appears. If it does not, your
event_idvalues differ. - Wait 24 hours and check the event's match quality has settled where you expect.
On a US client account, rebuilding pixel and CAPI from scratch — the account previously had no structured tracking at all — was the change that turned self-run boosted posts into a steady ten to fifteen leads a day on a $100 daily budget. Not because the ads got cleverer, but because the algorithm could finally see which clicks turned into customers.
Frequently asked
Do I still need the pixel if I have the Conversions API?
Yes. Meta explicitly recommends running both. The browser pixel captures signals the server cannot see, such as full browsing behaviour and the fbp cookie, while the server captures what the browser loses. Together with deduplication they cover far more than either alone.
Will the Conversions API break my GDPR or DPDP compliance?
Not by itself, but it does not exempt you either. You still need a lawful basis and consent where it applies, and you should not fire server events for users who declined. Pass the consent state through to your handler and skip the call when consent was refused.
How much of a lift should I expect?
It varies with how much of your traffic is iOS and how many people block scripts. Recovering a double-digit percentage of previously unseen conversions is common. The bigger gain is usually the improvement in bidding once the algorithm has cleaner data.