Tracking & Attribution

How Do You Know If Your Meta CAPI Is Working?

Your Meta CAPI works when events send, Meta accepts them, and Meta matches them. Here's how to verify all three — and the failures that look like success.

Quick answer

Your Meta Conversions API (CAPI) setup is working when three separate things are true: events leave your server, Meta accepts them, and Meta matches them to real people. Most verification advice only checks the first. Confirm all three by firing a test event with a `test_event_code`, watching it appear in Events Manager's Test Events tab, then reconciling your own order count against dispatched events over the same window.

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Your Meta Conversions API (CAPI) setup is working when three separate things are true: events leave your server, Meta accepts them, and Meta matches them to real people. Most verification advice checks only the first, which is why so many setups look healthy and still under-report.

The gap matters because every one of those three can fail independently, and two of them fail quietly — with a successful HTTP response and no error anywhere. This article covers how to check each layer, what Meta’s own tools do and don’t tell you, and the specific failures that look exactly like success.


What does “working” actually mean for CAPI?

It means three things, and they are not the same question:

1. Dispatch — did the event leave your server? This is the only layer you fully control. It either fired or it didn’t, and your own logs are authoritative.

2. Acceptance — did Meta take it? Meta returns an HTTP status. A 2xx means the request was well-formed enough to accept. It does not mean the event was processed, and it does not mean the payload was complete.

3. Matching — did Meta tie it to a person? An accepted event that Meta can’t resolve to a user contributes nothing to optimisation. This is measured by Event Match Quality, not by any success code.

Most “is my CAPI working” advice stops at layer one — the events are firing, so it’s working. But an integration can dispatch perfectly, get a 200 on every call, and still deliver almost no usable signal, because the payload carries an email and nothing else. All three layers have to be checked separately, because a green light on one says nothing about the next.


How do you check it in Meta’s own tools?

Meta gives you three surfaces, and they answer different questions.

Test Events is the fastest and the most under-used. In Events Manager, open your dataset, go to the Test Events tab, and copy the test event code it shows you. Attach that code to a server event as a top-level test_event_code field in the payload, then fire it. A working integration shows the event in that tab within seconds, along with the parameters it carried.

This is the single most useful check in the whole process, because it shows you the received payload — not what you think you sent. If you believe you’re sending a hashed phone number and the Test Events view shows no phone parameter, you’ve just found a bug that no status code would have revealed.

Events Manager overview shows event volume over time by source — browser, server, or both. Use it for one question only: are server events arriving at all, and at roughly the volume you expect? A flat line where you expect traffic is unambiguous. Anything subtler than that needs a different tool.

The Event Match Quality score is Meta’s rating, from 0 to 10, of how well your events match real accounts. It refreshes roughly every 48 hours over a rolling window, so it is a lagging indicator — useful for judging the health of an established setup, useless for confirming a change you made ten minutes ago.


What does Events Manager not tell you?

It doesn’t tell you what didn’t arrive.

This is the structural blind spot in platform-side verification, and it’s worth being precise about it. Events Manager is a view of events Meta received. If your server dropped an event, mis-mapped it, or never fired it, that event is simply absent — and absence looks identical to a quiet day. There’s no error, no gap marker, nothing to notice.

The only way to detect a missing event is to compare against a count Meta doesn’t have. That means reconciliation: take the number of orders in your own admin over a window, take the number of Purchase events dispatched over the same window, and compare them.

If your store admin shows 180 orders and you dispatched 174 Purchase events, six conversions went missing somewhere in your own stack — and no Meta-side dashboard would ever have told you. If the numbers match, layer one is genuinely healthy, and you can move on to asking whether the events were any good.

Run this reconciliation before you touch anything else. It’s the only check that can prove a negative.

Three separate checks in sequence — events leaving the server, the platform accepting them, and the platform matching them to people


How do you tell deduplication is actually working?

Compare your reported conversion count against your real one. If Meta reports materially more Purchases than your admin recorded, deduplication is failing and you are counting the same sale twice.

Deduplication works when the browser Pixel event and the server CAPI event carry the same event_id and the same event name. Meta then keeps the richer of the pair and discards the other. When the IDs don’t match, Meta has no way to know they’re the same conversion, so both are counted.

The specific check: fire a test purchase with both the Pixel and CAPI active, then look at the event in Test Events. A correctly deduplicated pair shows as one event with both sources attributed, not two separate entries. If you see two, your event_id values differ — usually because the browser is generating a random ID while the server uses an order ID, or because one path sends Purchase while the other sends purchase.

The failure is expensive rather than merely untidy: inflated conversion counts inflate reported ROAS, and campaigns get scaled on numbers that were never real. There’s a fuller diagnostic walkthrough in why your Meta CAPI isn’t deduplicating.


What are the failures that look like success?

Four, in rough order of how often they catch people out.

1. HTTP 200 with an unprocessed event. Meta’s response body carries an events_received count. A malformed event can return a 2xx status while that count comes back lower than what you sent. If your monitoring only checks the status code — and most monitoring does — this is invisible. Read the response body, not just the status.

2. Events arriving with almost no match data. A payload carrying only an IP address and user agent is technically a valid event. Meta accepts it, it appears in Events Manager, and it contributes close to nothing, because there’s nothing in it to match a person on. Match quality, not event count, is the measure here. The causes of a low EMQ score are almost always collection problems rather than transport problems.

3. Timestamps outside the accepted window. Meta rejects events whose event_time is more than seven days old, and clock skew on a server can push timestamps into the future, which also fails. A backfill of historical conversions frequently dies here, and the error is specific enough that it’s easy to miss in a generic error handler.

4. Consent and regional parameters missing. Without the right data-processing options, traffic from some jurisdictions is accepted and then silently discarded on Meta’s side. California traffic is the common case. Nothing in your logs will show a failure, because from your server’s point of view the send succeeded.

The pattern across all four: the thing that failed returned a success. Which is precisely why status-code monitoring alone is not verification.

An accepted response showing a green success status while most of the payload's match-data fields sit empty and a counter row flags fewer events received than were sent


How does PartialLeads show you it’s working?

By making each of the three layers directly inspectable, rather than asking you to infer health from a platform dashboard that only shows what arrived.

A 7-day health strip on the Meta CAPI page: sends over the trailing seven days, a per-day sparkline, delivery rate as a whole percent, and a failed-send count drawn from real HTTP failures. Test sends are excluded from the volume figures, so a round of testing doesn’t flatter the numbers. When no real sends exist yet, the delivery rate reads as empty rather than as a misleading zero.

A per-event activity log with the actual request and response bodies retained — the most recent 200 dispatch attempts, filterable per configuration, each carrying its event name, HTTP status code, any error, and the timestamp. Because the full request body is stored, you can open a specific event and see exactly which match parameters it carried. The access token is redacted before anything is written, so the payload is inspectable without exposing the credential. Each entry is also flagged for whether it carried a Meta click ID, which is the parameter that most affects whether the event ties back to an ad.

A per-lead dispatch indicator. On a lead’s detail view you can see whether a CAPI event was sent for that specific person and when. The leads list carries a per-platform column showing which destinations received events across the whole journey, not just the converting session.

A test send with test_event_code support, so a synthetic event can be fired from the dashboard and watched arriving in Meta’s own Test Events tab. Test sends don’t write a deduplication ledger row and don’t consume trial quota — a test isn’t a real send, and it isn’t counted as one.

Order-count and dispatch-count in the same view. The ecommerce summary shows order totals, matched and unmatched counts, and Meta fires broken out per event name — so the reconciliation described earlier can be read off one screen instead of assembled by hand from two systems.

Honest boundaries. Three things this does not do. The per-lead icon means a dispatch was attempted and not queued or skipped — it is not proof Meta accepted the event, and the activity log’s status code remains the authoritative answer for any specific lead. Failures are classified into three buckets — accepted, API error, and network error — rather than a finer-grained taxonomy. And while the raw Meta response is retained and readable per event, the events_received count inside it is not parsed into an automatic alert, so the HTTP-200-but-unprocessed case is inspectable rather than detected for you. Event timestamps are clamped to Meta’s seven-day window automatically, which prevents that particular rejection but does not resurrect the original timestamp.

Verification question PartialLeads mechanism Where you see it working
Are events leaving at all? 7-day health strip — sends, sparkline, delivery rate, failures Meta CAPI page, test sends excluded from volume
Did Meta accept this specific event? Per-event activity log with HTTP status and raw response Recent Activity, filterable per configuration
What match data did it carry? Full sanitised request body retained per dispatch Activity log entry, token redacted
Did it carry an ad click ID? Per-entry click-ID flag Activity log column
Was an event sent for this lead? Per-lead dispatch flag and timestamp Lead detail, plus per-platform column on the leads list
Does my setup reach Meta at all? Test send with test_event_code Meta’s own Test Events tab
Is anything missing entirely? Order count and dispatched-event count side by side Ecommerce summary, fires broken out per event name

What should you check, and how often?

Three checks on three different cadences.

Once, at setup: fire a test event with a test event code and confirm it appears in Test Events with the parameters you expect. Then fire a real test purchase with both Pixel and CAPI live, and confirm it appears as one deduplicated event rather than two.

Weekly: reconcile your admin order count against dispatched Purchase events for the week. This is the check that catches silent drops, and it’s the one almost nobody runs.

Monthly, or after any form change: look at Event Match Quality. It moves slowly and it responds to what your form collects far more than to how your tracking is plumbed, so it’s a review-cadence metric rather than a debugging one.


Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Sources

  1. Meta for Developers — Conversions API documentation: https://developers.facebook.com/docs/marketing-api/conversions-api
  2. Meta for Developers — Conversions API best practices: https://developers.facebook.com/docs/marketing-api/conversions-api/best-practices
  3. Meta for Developers — Conversions API payload helper: https://developers.facebook.com/docs/marketing-api/conversions-api/payload-helper
  4. Meta for Developers — fbp and fbc parameters: https://developers.facebook.com/documentation/ads-commerce/conversions-api/parameters/fbp-and-fbc
  5. Meta Business Help — About the Conversions API: https://www.facebook.com/business/help/353532912433684

Frequently asked questions

QHow long does it take for CAPI events to show up in Events Manager?
Test events appear in the Test Events tab within seconds — that's what makes it the right tool for confirming a change. The main Events Manager overview lags by up to 20 minutes for aggregate counts, and Event Match Quality refreshes roughly every 48 hours over a rolling window. If you're checking a fix you just deployed, use Test Events; anything else will have you staring at stale numbers.
QMy CAPI events are sending successfully but my conversions didn't go up. Why?
Almost always because deduplication is working correctly and you were expecting it not to. If the Pixel was already reporting those conversions, adding CAPI shouldn't increase the count — it should increase the *match quality* of the same count, and pick up the conversions the browser missed. A large jump in reported conversions right after adding CAPI is usually a deduplication failure, not a win.
QWhat's a normal delivery rate for CAPI?
Effectively 100%, and anything meaningfully below that is a bug rather than a fact of life. Unlike match rate or EMQ, delivery is entirely within your control — the request either reaches Meta or it doesn't. A delivery rate of 95% means one in twenty conversions is being dropped by your own stack, and it's worth finding out which one.
QCan I verify CAPI is working without making a real purchase?
Yes. A test send with a `test_event_code` builds a synthetic event with placeholder identity data and fires it at Meta, where it appears in the Test Events tab without touching your real conversion data. This confirms the transport, the credentials, and the payload shape. What it can't confirm is whether your *real* events carry good match data, since the test identity is fabricated.
QDoes a 200 response mean Meta processed my event?
No, and this is the most common false positive in CAPI monitoring. A 2xx means the request was well-formed enough to accept. Meta's response body carries an `events_received` count that can come back lower than what you sent, and events can also be discarded later for missing consent parameters. Read the response body, not just the status line.
QHow do I know if my events are actually being matched to people?
Event Match Quality is the only direct measure, and it's reported per event type in Events Manager. Match quality depends on what identifiers your payload carries — hashed email and hashed phone are the two highest-weight parameters — so it's usually a reflection of what your form collects rather than how your server sends. A perfectly engineered integration on an email-only form will sit near its ceiling around 6 or 7.
QWhy do my server events show a different count than my browser events?
They should differ, and the direction tells you something. Server events exceeding browser events is normal and expected — the server sees conversions the browser missed to ad blockers, iOS tracking restrictions, and abandoned thank-you pages. Browser events substantially exceeding server events means your server-side path is dropping conversions, and reconciliation against your own order records will show you how many.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.