Dan Antony
Automation & Ops

Meta CAPI: A Grounded Guide to the Part Nobody Writes Down

I have been sending events through Meta's Conversions API for three years now, across two brands, two currencies, two CRMs. I have built it from scratch, debugged it at midnight, and watched cost per qualified lead drop fifteen to twenty-five percent once the algorithm actually learns from real outcomes instead of form fills. I have also lost half a day to event names that Meta accepts and ignores, conflated the Ads Manager lead count with actual CAPI feedback, and assumed a sixty-two day backfill window that turned out to be seven. Every single one of those mistakes was avoidable. None of the guides I read caught me before I fell.

This post is the guide I wish had existed. Not a tutorial. Not a pitch for why CAPI matters. You already know it matters. This is the grounded, practical stuff that lives in the gap between the official Meta documentation and the vendor integration guides, written from a live integration that has been running in production for a real pixel.

What CAPI actually does

The Meta Pixel is the JavaScript on your website that tells Facebook "this person just submitted a form" the moment it happens in their browser. The Conversions API is the same signal, except it travels from your server instead of the user's browser. Your CRM tells Meta "this lead became an MQL three days later." Your sales pipeline tells Meta "this lead got transferred to sales last week." The pixel sees the form fill. CAPI sees what happens after.

Here is the full chain in practice. Someone clicks your ad and fills your form. The pixel fires a Lead event. Your sales team works the lead. Three days later they mark it qualified. Your backend sends Meta a QualifiedLead event for the same person. A week later they book a meeting. You send Schedule. Eventually they sign. You send Purchase with the actual contract value. Meta now knows, for that one person, the full journey from click to revenue. Not an attribution model. A fact you reported.

Once Meta has enough of those facts, three things happen. Cost per qualified lead drops, usually fifteen to twenty-five percent within the first month. You can switch from minimising cost per lead to maximising the value of qualified leads. And you can build lookalike audiences of your actual customers instead of lookalikes of anyone who filled a form, including the junk.

That is what CAPI does. The rest of this post is about what every guide I have read gets wrong, glosses over, or never mentions at all.

Why the pixel is no longer enough

CAPI was always useful. Since iOS 14.5 and App Tracking Transparency, it became essential.

Here is the problem in one number. A browser pixel, working alone, captures about sixty-five percent of actual conversions. The other thirty-five percent disappear into iOS opt-outs, Safari's Intelligent Tracking Prevention, ad blockers, and cookie consent banners. The pixel only fires when the browser cooperates, and browsers increasingly do not.

CAPI does not depend on the browser. It sends the event from your server, using identifiers your CRM already has: email, phone, a click ID if you captured it. Pixel plus CAPI together recover about ninety-five percent of conversions. That thirty point gap is the difference between Meta's algorithm training on most of your data and training on two thirds of it while guessing about the rest.

That is why CAPI is table stakes in 2026, not optional. If you are still relying on the pixel alone, you are flying blind on a third of your funnel.

What you actually need to set this up

Before the war stories, the basic pieces. You need four things working together.

A Meta Pixel, configured in Events Manager. Meta now calls this a "Dataset" in parts of the interface, but it is the same thing. The Pixel ID and the Dataset ID are identical. If you are looking for your Dataset ID and only see a Pixel ID, use that number. It is where all events land, whether they come from the browser or from CAPI.

A CAPI access token, generated inside Events Manager. This is not the same token you use for the Marketing API or for Business Manager. It is a long-lived token specific to Conversions API, tied to one pixel. You generate it once and store it securely.

A way to read your CRM or sales data and send it to Meta. This is the integration piece. It can be a vendor connector, a custom script, an iPaaS tool like Zapier, or even Apps Script running inside a Google Sheet. What matters is that it can detect when a lead's stage changes, map that stage to a Meta standard event name, hash the lead's identifiers, and POST the event to Meta's endpoint.

An event_id for deduplication. When the pixel fires Lead in the browser and your backend also sends Lead through CAPI for the same form submission, Meta needs to know they are the same event, not two separate conversions. You handle this by sending the same event_id in both places. Meta deduplicates on the pair of event_id plus event_name. If either value differs, Meta counts it twice.

None of that is complicated. What is complicated is everything that sits between those four pieces: the vocabulary gaps, the vendor assumptions, the quiet failure modes where events arrive but do nothing.

The guide I followed was not a guide

The first time I built CAPI from scratch, I read every guide I could find. One of them walked me through the payload, the hashing, the event names, the fields you include and the fields you leave out. It looked canonical. It used all-caps labels with underscores. INITIAL_LEAD. QUALIFIED_LEAD. The kind of names you would write down and use as your event_name without thinking twice.

I used them. The code ran. Meta accepted every POST. The Events Manager dashboard sat at zero.

What that guide never said, because it was written for customers of that specific CRM, not for someone building from scratch, is that those all-caps labels are the vendor's internal names for stages inside their own UI. When that vendor sends data to Meta, somewhere inside their integration, those labels get translated into Meta's actual standard event names. Their docs describe what their customer sees. Not what Meta receives. I was sending names Meta did not recognise, and Meta was politely accepting them and doing nothing with them.

The fix was five characters. The cost was half a day.

I started seeing the same shape everywhere. Every public CAPI guide I read was integration documentation for one specific vendor's wrapper around CAPI. They look like Meta documentation. They are not. The moment you step outside that vendor's product, the names, the mappings, and the assumptions all break. The ecosystem is a hall of mirrors. Every surface reflects a different vendor's reality, and none of them is Meta's.

Meta has exactly seventeen standard event names. Lead. QualifiedLead. Schedule. StartTrial. Purchase. That is the entire list. Anything else Meta accepts, but the algorithm does not know what to do with it. The vendor guides almost never lead with this fact, because their job is to document their own integration, not to teach you Meta's vocabulary.

Four words that mean four different things

Once events were actually arriving, I tried to make them optimise something. That was the next half day, because there are four separate concepts in a CAPI conversation and every guide I read used the same word for all of them.

Lead status is the stage in your CRM or your sheet. New Lead. Qualified. SQL. Customer. That vocabulary is whatever your sales team agreed on. Meta has no opinion on it.

Event name is the value in the payload you send to Meta. Meta has those seventeen standard names. Lead. QualifiedLead. Schedule. StartTrial. Purchase. Only these names can be used as optimisation targets for Conversion Leads campaigns.

Custom event is a name you invent yourself. Meta records it. The algorithm has no built-in understanding of what it means. You cannot optimise a Conversion Leads campaign against it.

Custom conversion is a rule you build inside Events Manager. It says "count every Lead event where the lead_status parameter equals SQL as a conversion called SQL." That is what makes a stage like SQL show up in your ad set's optimisation dropdown.

I had been saying "we are sending the SQL stage" while shipping a custom event name, while not having a custom conversion configured, while my CRM column said something else entirely. All four concepts were moving in different directions and I was calling them by the same name. The events arrived. The bidding model could not see them as anything it could optimise. The dashboard was full of events the algorithm did not recognise, which is worse than zero because it looks like progress.

Here is the mapping nobody prints on a single page. MQL maps to QualifiedLead. SQL maps to Schedule. Opportunity maps to StartTrial. Customer maps to Purchase. Those are not names I invented. They are what the integration ecosystem settled on years ago. Schedule is Meta's name for the SQL stage. StartTrial is Meta's name for an opportunity. None of that is on any Meta page I can find in a form a first-time builder will notice.

The lead count went up. The algorithm learned nothing.

There are two ways a Meta lead enters your world. In the first way, someone clicks your ad, lands on your website, fills your form. The pixel fires Lead in the browser. Your backend later tells Meta about the higher stages. This is the comfortable path.

In the second way, someone clicks your ad, a native form opens inside Facebook or Instagram, they fill it without ever visiting your site, and Meta stores the lead. No pixel fires. No browser session on your side. No UTM parameters. Just a row landing somewhere with the lead's details and a fifteen-digit leadgen_id that uniquely identifies that submission.

I set up that side. I watched the lead count in Ads Manager tick up. I watched the form submissions arrive. I assumed CAPI was firing.

It was not. Meta does not automatically fire a CAPI event when an instant form is submitted. The lead count in Ads Manager is internal tracking, completely separate from the Conversions API. It happens because Meta owns the form. It has nothing to do with what your bidding algorithm learns about lead quality later. I conflated the two for the better part of a week because every guide I read showed the lead count going up and called the integration "wired up."

The lead count going up tells you the form is collecting leads. It does not tell you that anything is teaching the algorithm what those leads turned into. If you want Meta to learn that two thirds of those leads were junk and only five percent became real opportunities, you have to send those events yourself. Meta will not. Most public guides do not say this. Some imply the opposite.

Here is the part that costs you everything if you miss it. If you capture that fifteen-digit leadgen_id from Meta and send it back through CAPI, your match rate is ninety-five percent or better. Meta already knows exactly which lead you are talking about. If you do not capture it, you are matching on email and phone alone, and you are at fifty to sixty-five percent. That gap is the difference between CAPI being a meaningful feedback loop and CAPI being expensive decoration that the algorithm half-trusts.

The docs said sixty-two days. The reality was seven.

I had leads from the past few weeks that had been progressing through the funnel before CAPI was on. I wanted to backfill them so the algorithm had a starting context.

Meta's documentation says you can send events up to sixty-two days in the past. I queued thirteen events and ran them. Three came back rejected. The rejected ones were eight to fourteen days old. The accepted ones were inside the last seven.

Meta's documentation says you can send events up to sixty-two days in the past. What it does not say clearly is that the sixty-two-day window applies only to offline events with action_source: physical_store. For web events and system-generated CRM events, the limit is seven days.

I learned this the hard way. Our backend events use action_source: system_generated, which falls under the seven-day rule. I queued thirteen events and ran them. Three came back rejected. The rejected ones were eight to fourteen days old. The accepted ones were inside the last seven. Meta returned an explicit "event_time too old" rejection, error subcode 2804003, on the older rows.

Third-party implementers who have hit this at scale document the same split: Weld's CAPI integration guide notes that event_time can be at most seven days in the past for web events, while offline and physical store events can go up to sixty-two days. A Meta Performance Marketing Summit PDF confirms it: advertisers must send post-conversion events "within the latest 7 days after the event happened (the latter is based on a requirement of Conversions API)."

If you are turning CAPI on for the first time, plan to send events in close to real time from the day you switch it on. Do not assume you can catch up on last quarter's leads. You will lose less by starting fresh than by assuming sixty-two days and watching half your backfill silently fail.

What to actually do once the plumbing works

Most teams set up CAPI, then keep running campaigns exactly the same way and wonder why nothing improved. Here is how to capture the benefit.

Optimise on the right event. Meta's algorithm needs about fifty conversion events per ad set per week to exit the learning phase and bid efficiently. Start with Lead if you need volume. Once you have fifty QualifiedLead events per week per ad set, switch to that. Once you have fifty Schedule events, switch to that. Do not rush it. If you optimise on Schedule while only getting ten per week, the algorithm starves and your performance tanks.

Send value with every event. A raw lead might be worth a hundred rupees. An SQL might be worth fifty thousand. The ratio matters more than the exact number. Once values are flowing, switch your bid strategy from lowest cost to highest value. Now Meta is not trying to get you more leads. It is trying to get you more valuable leads. That is where the fifteen to twenty-five percent improvement comes from.

Build a junk lookalike and exclude it. Take your last ninety days of disqualified leads. Upload them as a custom audience. Build a one to five percent lookalike. Exclude it in your ad sets. Meta proactively avoids people who look like your bad leads. This is cheaper than letting them click and filtering them out later.

Configure the Sales Funnel in Events Manager. After seven days of production data and at least two hundred leads per month, a Sales Funnel panel unlocks. Categorise each event as either a positive stage or an "other" stage. Order the positive stages from top to bottom of your funnel. This tells Meta's algorithm which events represent progress and which represent failure. Without this step, the algorithm sees your events but does not know what to optimise for.

Watch your Event Match Quality. Meta scores every CAPI event zero to ten based on how well it matches a Facebook user. Six is okay. Eight or above is great. To hit eight, send clean email and phone in every event, plus IP address and user agent. Email alone is worth up to four points. Phone is worth about three. Those two fields are the highest-impact identifiers you control.

None of that is in the official Meta documentation in a form a first-time builder will notice. All of it is in this post because I paid the cost of finding it out the slow way.

What I would tell myself before the next build

If I were writing a CAPI guide for someone starting today, the whole guide would be one page long. It would say: the event names you read in a vendor's CAPI guide are almost never the names Meta is waiting for. Use Meta's seventeen standard names. The lead count you see going up in Ads Manager for instant-form ads is not CAPI. If you want the algorithm to learn from what your leads actually become, you have to send those events yourself. The lookback window for new CAPI accounts is closer to seven days than the documented sixty-two. Plan backfill accordingly. On instant-form leads, the leadgen_id is the difference between a ninety-five percent match rate and a fifty percent one. If you do not have it captured before you start, you are about to pay for the integration and get half its value.

None of those is in the official Meta documentation in a form a first-time builder will notice. All five are in this post because I paid the cost of finding them out the slow way. If you are about to build CAPI, build it knowing them. The official docs and the vendor guides will fill in the rest, but they will not catch you when you fall, and these five are where you fall.