How to send Meta conversions direct from your app without Zapier
Posted by
Latest Posts
Jun 25, 2026
Nov 18, 2025

If you run Facebook ads, Meta is grading your data right now. It calls the grade your event match quality, and decides how well Meta can link an event back to the ad.
Ours scored 2.2 out of 10. After we changed how we send conversions, it hit 8.4.
Meta optimizes ad delivery from the data you report back to it. When the data quality is poor, Meta can't tell which clicks turned into buyers, so it spends your budget on the wrong people. Better data in, cheaper results out.
Here is why our score was low, what we changed, and how to check your own.
The Pixel misses a real chunk of your Customers
The Facebook Pixel runs in the user’s browser so you can’t control it.
Ad blockers strip it out. iOS and Safari limit what it can store. Privacy settings shut it off. When the Pixel is blocked, the conversion still happens, but it’s never reported to Meta never hears about it. The ad that earned it gets 0 credit.
So Meta is optimizing against a partial picture. It under-counts your real conversions and over-charges for the ones it can see.
Why Zapier and the Stripe app didn't cut it
The common fixes both have real downsides.
- Zapier (Stripe to Meta): billed per task, runs on a delay, and the field mapping is fiddly to set up and easy to get wrong. It is one more tool to maintain, and when it breaks it fails quietly.
- Stripe's built-in Meta app: it sends its own events with its own IDs. Those IDs don't match your Pixel's, so Meta can't dedupe them — you end up double-counting the same purchase and muddying the data you were trying to clean up.
What we built: Direct reporting from app to Meta API
We send conversions server-side, directly to Meta's Conversions API — no middleman, no per-task fees, and no marketing partner. A server reports the event from our own backend server which keeps you in control.
For our own community app we track three events this way:
- Lead — someone joins the email list
- StartTrial — someone starts the free trial
- Purchase — the trial converts to a paid subscription
Every server event also shares one ID with the matching browser Pixel event. Meta sees the shared ID and treats them as one conversion instead of two. The browser still reports what it can; the server fills in everything the browser missed.
Quality tripled from 2.2 to 8.4 out of 10
Meta now matches our conversions to real people. The ad and click that drove each conversion gets credited, and the Purchase event reports real revenue.
That means every dollar of ad spend is leveraging better data which helps Meta find more buyers at a lower cost per result.
How we did it (the technical part)
Here’s how to implement… but you can just share this article with your favorite LLM.
-
One shared helper,
sendCapiEvent(), POSTs to the Graph API:https://graph.facebook.com/v21.0/./events -
Hash email and name with SHA-256 before they leave your server. Send
fbc,fbp, IP, and user agent as-is. -
Generate one
event_idper action and use it for both the browser Pixel event and the server event. That shared ID is what lets Meta dedupe. - Lead and StartTrial fire from our API routes the moment they happen direct to our CRM, ActiveCampaign
-
Purchase fires from the Stripe webhook on the first paid invoice, reusing the
fbc/fbpwe stored at checkout. No browser is open at that moment, but we still attribute the revenue to the original ad click.
POST https://graph.facebook.com/v21.0/<PIXEL_ID>/events?access_token=<TOKEN>
{
"data": [{
"event_name": "Purchase",
"event_id": "<same-id-the-pixel-used>",
"user_data": { "em": "<sha256-email>", "fbc": "<unmodified-click-id>" },
"custom_data": { "value": 24, "currency": "USD" }
}]
}
All you need to start: your Pixel ID and a Conversions API access token, generated in Events Manager. No partner approval needed.
How to check your own ads
- Open Events Manager, pick your dataset, and look at the event match quality score. Under about 5 out of 10 means you are losing signal.
- If you rely only on the browser Pixel, you are missing every blocked visitor — and that is more of them than you would guess.
- Confirm your click ID is clean with Meta's Payload Helper. If it has been re-encoded, your match quality is paying for it.
This is the kind of plumbing we build. We did it for our own community app, and we set it up for the founders we work with. If your match quality is low, or you are stuck wiring conversions through Zapier, book a call and we'll take a look at your setup.