Facebook Conversions API in plain English: why the pixel alone is not enough
The Facebook Conversions API sends conversions to Meta from your server instead of the visitor's browser, so events survive iOS tracking prompts, shortened Safari cookies and ad blockers. Sending the same conversion from both places is intended, not a mistake: Meta matches the copies by a shared event_id and keeps one.
Nothing about the Conversions API is exotic. The pixel is JavaScript running inside your customer's browser, and the browser decides whether it runs. The Conversions API is the same event sent from a machine you control, where nobody else gets a vote. Everything else follows from that one difference.
Why the pixel loses events in the first place
The pixel has one job: notice that something happened, a purchase or a form submit, and tell Meta before the visitor moves on. Several separate things interrupt that, and they are not one problem wearing different hats.
| What gets in the way | What it does | What the ad account ends up with |
|---|---|---|
| iOS tracking prompt | iOS asks the visitor before an app tracks them across other companies' sites and apps | The event fires with fewer identifiers to match on |
| Safari and Firefox cookie limits | Cookies written by scripts are capped at days rather than months | A conversion after the cookie expires no longer links to the ad click |
| Ad blockers and privacy extensions | The request never leaves the page: the tag is stripped or the domain is filtered | Nothing arrives, so the conversion is invisible rather than unattributed |
| Anything after the browser closes | A lead your team qualified on Tuesday, a deal signed by phone, a refund | These never had a browser event to lose |
They fail differently, and that matters. A blocked request loses the event outright. An expired cookie keeps the event but loses its link to the ad click. A declined prompt keeps both and leaves less to match on. That is why "my numbers look off" is never a single diagnosis.
A missing conversion is a wrong instruction, not a missing row
If tracking were only reporting, undercounting would be an accounting annoyance: your bank account still knows the real revenue. But the same events are what delivery optimizes on, and Meta builds its idea of a good customer from the conversions it receives. When part of them never arrive, three things happen at once and none of them surfaces as an error.
- –Learning stretches out. Meta's own benchmark is about fifty optimization events per ad set per week, and events the account never receives do not count toward it.
- –The audience model trains on a skewed sample rather than a smaller one.
- –Slow conversions get punished. Purchases that happen days after the click are exactly the ones a short-lived cookie loses, so a longer consideration cycle looks worse than it is.
The bias costs more than the count. Losses spread at random would give you a smaller version of the same picture. These are not random: they cluster in Safari, in iOS, and in the more privacy-minded half of your audience. That is the sample the algorithm learns from.
What the server sends instead
The Conversions API is an HTTP request from your server to Meta carrying the same kind of event the pixel would have sent: an event name, a timestamp, and whatever you know about the person. No browser is involved, so nothing in the browser can stop it.
Contact details do not travel in the clear. Email, phone and name are normalized (lowercased, trimmed, digits only for the phone) and hashed with SHA-256 before they leave your system; Meta hashes its own copy and compares the hashes. Two identifiers go as-is because hashing would break them: the fbp and fbc cookies, which Meta set in the browser and compares byte for byte.
| What differs | Browser pixel | Conversions API |
|---|---|---|
| Runs on | The visitor's device | Your server |
| Fires | While the page is open | Any time, including days later |
| Knows page context | Yes: URL, referrer, the fbp and fbc cookies | Only what you stored and passed along yourself |
| Offline events | No | Yes: qualified leads, phone sales, refunds |
The last row is the one small businesses underrate. A form submit is a weak signal: some of those people become your best customers and some were never going to buy. If your CRM knows which is which, send the qualified lead or the closed deal as its own event, and the algorithm optimizes toward the outcome instead of the form.
Aevin does this from the CRM side: a lead landing on a stage flagged qualified or won sends the event from the server, the won stage as a standard purchase with value and currency, the qualified stage under its own event name so it does not double-count the lead event the site already sent.
Deduplication: sending the same event twice is the plan
The obvious worry: if the pixel fires and the server fires, does Meta count two purchases? Not if you give it a way to recognize them as one. Both copies carry the same event_name and the same event_id, Meta keeps one and drops the other, and that is the whole mechanism. The event_id is any string, as long as browser and server agree on it for that one conversion: an order number, a lead row id, a random value written into the page and passed back to your server.
Four ways it breaks:
- –The two sides generate different event_id values. The loud failure: both copies count, and one purchase shows up as two.
- –The event names differ. Purchase from the pixel and purchase from the server are two different events to Meta, and event_id is only compared within the same name.
- –Only one side sends an event_id. There is nothing to match on, so nothing gets merged.
- –The copies arrive far apart. The deduplication window is measured in days, not weeks, so a server event stuck in a retry queue can miss it.
Do not avoid overlap by sending server events only for the conversions you think the pixel missed. You cannot know which those are when the event happens, and the guess is what creates the gaps. Send everything from both sides and let event_id sort it out.
What to check after you turn it on
Setup is the short part. Confirming it works is the long part, and Events Manager answers if you ask it the right questions.
- 1.Send a test event first. Requests accept a test_event_code and the Test Events tab shows it arriving live. A misconfigured event is much harder to find once it is mixed into real traffic.
- 2.Check that duplicates are being dropped. Events Manager shows the browser count, the server count and how many events were deduplicated. If both sources are busy and almost nothing is deduplicated, your event_id is not matching.
- 3.Read the event match quality score. It reflects how often Meta could tie an event to a person, and it moves when you add identifiers: email, phone, name, fbp, fbc, an external_id of your own.
- 4.Wait a week before comparing anything. Conversions keep getting attributed for days after the click, so the first couple of days mislead in both directions.
The direction is predictable, the size is not. Events the browser never delivered can only push the reported count up, and reported cost per conversion down by the same arithmetic, though you did not spend a cent less. Both numbers were wrong before.
What it does not do
- –It does not create conversions, only reports the ones that already happened. A real cost-per-lead problem survives the setup intact, now with better bookkeeping.
- –It does not make the numbers exact. Meta still models part of what it cannot observe, and a modeled conversion does not become a measured one because a server started sending.
- –It does not replace the pixel. The browser copy carries context the server does not have, and running both is the intended design, not a workaround.
None of this holds by itself. The site changes, a token expires, a queue backs up, and nothing announces it: events stop while the reports keep rendering. Put deduplication and match quality on a recurring check instead of trusting the setup to stay set up.
Do I still need the Facebook pixel if I have the Conversions API?
Yes, and Meta's guidance is to run both. The browser copy carries context the server does not have (page, referrer, the fbp and fbc cookies), and the server copy covers what the browser loses. Matching event_id values keep the overlap from inflating your numbers.
How does event_id deduplication work?
Send the same conversion from the browser and from the server with the same event_name and the same event_id on both. Meta keeps one copy and drops the other. The event_id can be any string, as long as both sides use the identical value.
Will my conversion numbers go up after I set it up?
If the browser was losing events, the server copy adds the ones that never arrived, so the reported count moves up. How far depends on your traffic: an audience heavy on iOS and Safari loses more in the browser. What changes is what the account can see, not what your customers did.
Is it safe to send customer emails and phone numbers to Meta?
The contact fields are hashed with SHA-256 before they leave your system, so Meta compares a fingerprint against a hash of its own rather than reading the address. You are still choosing to share customer data with an ad platform, and that decision belongs in your privacy policy and consent flow.
- Your Meta ads stopped delivering: what to check, in orderFacebook and Meta ads stopped spending? Check status, rejections, spend limits, billing, audience size, overlap, schedule and learning, in this exact order.
- The Meta Ads learning phase: what resets it and how to get outHow the Meta Ads learning phase works: the event threshold, which edits reset it, what learning limited actually means, and why frequent edits keep it there.
- Where Meta lead ads go missing between the form and the first callFacebook lead ads not showing up in your CRM? Where instant form leads actually sit, the four ways delivery breaks, and the daily counts that catch it early.
