- The Meta Conversions API sends events such as Purchase from your server, so they reach Meta even when the browser pixel is blocked.
- Run it next to the pixel and give both copies the same event name and event_id; Meta then counts the event once if both arrive within 48 hours.
- Website events need action_source, event_source_url and the shopper's user agent; hashed email and phone, IP address, fbp and fbc decide how well Meta can match them.
- Test with the Test events tab in Events Manager, then remove the test code, because test events are not dropped.
- Most problems come from mismatched event ids, the server's own IP address, a lost fbclid or contact data that was hashed without normalizing.
The Meta Conversions API (CAPI) lets your server send events such as Purchase directly to Meta. The Meta pixel sends the same events from the shopper's browser. CAPI sends them from your server, so they still arrive when an ad blocker stops the pixel, a cookie is gone or the thank-you page never loads.
This guide covers what a Conversions API event contains, how to run it next to the pixel with one event_id, which parameters Meta requires and recommends, how to test with Test events, and the errors that come up most often.
What is the Meta Conversions API?
The Conversions API is part of Meta's Graph API. Your server sends an HTTPS POST request to graph.facebook.com/VERSION/PIXEL_ID/events with an access token and a data list of up to 1,000 events. Each event describes one action, such as a purchase, in three parts: what happened, who did it, and the details.
| Field | What it holds |
|---|---|
event_name | The action, for example Purchase, AddToCart or InitiateCheckout |
event_time | When it happened, as a Unix timestamp in seconds |
event_id | A unique id for this event, used to deduplicate it against the pixel |
action_source | Where it happened: website for store purchases |
event_source_url | The page URL where the event happened |
user_data | Customer information for matching: hashed email and phone, IP address, user agent, fbp and fbc |
custom_data | Details such as value, currency and content_ids |
A trimmed Purchase event looks like this:
{
"data": [{
"event_name": "Purchase",
"event_time": 1792929600,
"event_id": "order-1042",
"action_source": "website",
"event_source_url": "https://yourstore.com/checkouts/thank-you",
"user_data": {
"em": ["<SHA-256 of the normalized email>"],
"ph": ["<SHA-256 of the normalized phone>"],
"client_ip_address": "203.0.113.24",
"client_user_agent": "Mozilla/5.0 (iPhone; ...)",
"fbp": "fb.1.1792928400000.1234567890",
"fbc": "fb.1.1792928400000.AbCdEf123"
},
"custom_data": { "value": 74.00, "currency": "USD" }
}]
}Contact fields such as email and phone are normalized and hashed with SHA-256 before they leave your server. The IP address, user agent, fbp and fbc are sent as they are.
Why run the Conversions API next to the pixel?
Meta recommends running the Conversions API alongside the pixel and sending the same events through both. Each side sees something the other does not, and together they give Meta more complete data.
- Sets the _fbp cookie and stores the fbclid of an ad click in the _fbc cookie
- Sees the page and the browser while the visit happens
- Is lost when the browser blocks it or the page does not load
- Sends the paid order from your shop data
- Can add hashed email, phone and address from the order
- Does not depend on the browser, so ad blockers do not stop it
The cost of running both is that Meta now receives two copies of each event. The next section shows how Meta keeps only one.
How does deduplication work with one event_id?
Meta treats a browser event and a server event as the same event when two things match: the event name and the event id. In the pixel, the id goes in the eventID option. In the Conversions API, the same value goes in event_id.
fbq('track', 'Purchase', { value: 74.00, currency: 'USD' }, { eventID: 'order-1042' });Meta deduplicates a matching pair only when the two copies arrive within 48 hours of each other. A few rules make this work in practice:
- Create the id once. Build it from something both sides know, such as the order number, and pass it to the browser and the server. Two systems that each make their own id will not match.
- Use one format.
order-1042and1042are different ids. - Match the event name exactly.
Purchaseandpurchaseare different events. - Send the server event promptly. A server event that arrives more than 48 hours after the browser event is counted a second time.
Meta also describes a second method that pairs events by fbp or external_id. Meta says it generally only works when the browser event arrives before the server event, so a shared event_id is the more reliable choice. If Meta still reports more purchases than your shop had, our guide to duplicate purchase events lists the usual causes.
Which parameters are required, and which are recommended?
The required fields make an event valid. The recommended fields decide how many of your events Meta can match to a person, and only matched events can be used for attribution and ad delivery.
| Parameter | Website events | What to send |
|---|---|---|
event_name | Required | A standard event such as Purchase, or a custom event name |
event_time | Required | Unix time in seconds, at most 7 days in the past |
action_source | Required | website for events on your store |
event_source_url | Required | The page URL where the event happened |
client_user_agent | Required | The shopper's browser string, not the one of your server |
user_data | Required | At least one customer information parameter |
event_id | Recommended | The same id the pixel uses, for deduplication |
em, ph | Recommended | Email and phone, normalized and hashed with SHA-256 |
client_ip_address | Recommended | The shopper's IP address, not hashed |
fbp, fbc | Recommended | The browser id and click id cookies, not hashed |
external_id | Recommended | Your own customer id, the same on browser and server events |
value, currency | Send with Purchase | The order value and a three-letter currency code |
Three details cause most of the problems:
- Normalize before you hash. Meta expects email trimmed and in lowercase, and phone numbers as digits with the country code.
Anna@Example.comandanna@example.comgive different hashes, and only the second one can match. - Do not hash browser identifiers.
fbp,fbc, the IP address and the user agent go in as plain values. - Keep the click id exactly as it is. The
fbcvalue isfb.1., the creation time in milliseconds, a dot, and thefbclidfrom the landing page URL. Thefbclidis case sensitive. Save it when the visitor lands, because it is no longer in the URL at checkout.
How well these fields match is what Meta's Event Match Quality score measures. Our guide to Event Match Quality covers each parameter, the hashing rules and the score to aim for.
How do you test events with Test events?
Events Manager has a Test events tab that shows events as they arrive. Use it before you rely on a new setup.
- Open Test events
In Events Manager, select your dataset (pixel) and open the Test events tab. Copy the test code it shows.
- Add the code to your server events
Send it as
test_event_codein the request. In ROASaurus, paste it into the Test event code field of the Meta pixel. - Place a test order
Visit the store, add a product and pay, so that both the pixel and the server send a Purchase.
- Compare the two copies
Both copies should show the same event name, event id, value and currency.
- Check the customer information
The server event should carry hashed email and phone, the IP address, the user agent and fbp, plus fbc if the visit started with an ad click.
- Remove the test code
Meta says the field is for testing only, so remove it before you rely on the events.
Purchase browser order-1042 74.00 USDFrom the pixelPurchase server order-1042 74.00 USDFrom the Conversions APIevent_name + event_id matchCounted as one purchaseem ph fbp fbc client_ip_address client_user_agentCustomer information on the server eventCommon Conversions API errors and how to fix them
| What you see | Likely cause | Fix |
|---|---|---|
| The whole request fails and no events are processed | One event in the batch has an event_time more than 7 days old | Send events when they happen. Fix or drop old events before you retry. |
| Meta reports more purchases than your shop had | Different event ids, a pixel event without eventID, or a second app that sends the same pixel | Use one id for both copies and one server sender per pixel. |
| Low match quality on server events | Your server sends its own IP address and user agent | Pass on the IP address and user agent recorded from the shopper's browser or order. |
| Few events with fbc | The fbclid was not saved on the landing page, or it was changed | Store the fbclid exactly as it arrives and build fbc from it. |
| Email and phone do not match | Values hashed without normalizing, or sent without hashing | Trim and lowercase the email, keep the digits and country code of the phone, then hash with SHA-256. |
| Requests fail with an expired token error | The access token came from a Facebook login, and login tokens expire | Reconnect, or use a System User token from Business Manager, which you can create without an expiry date. |
After a few days of live traffic, open the Diagnostics tab in Events Manager. Meta lists issues there with recommendations on how to fix them. Then compare the daily Purchase count in Events Manager with the paid orders in your shop for the same days. If Meta is clearly higher, our help page on preventing double counting lists the settings to check.
How to set up the Conversions API with ROASaurus
ROASaurus sends Conversions API events from your shop's order data, so you do not have to build the server side yourself. In Tracking & platforms, click Connect with Facebook and pick your ad account and pixel, or paste the pixel (dataset) id and a Conversions API token. The Meta setup guide walks through both options, and the Meta integration page lists every field that is sent.
- One id on both sides. Browser and server events share one event id. For a purchase it is
order-followed by the order id. - A short hold before the purchase. The server Purchase waits a short moment after the order arrives, so the browser purchase event can be joined first. Its IP address, user agent and page URL then go out with the server event, together with the
fbpandfbcsaved for the visitor. - Customer information from the order. Email, phone, name and address are normalized and hashed with SHA-256. The shop's customer id and the ROASaurus visitor id go in hashed as
external_id. - Events Meta cannot match are skipped. An event with no
fbc,fbp, email, phone or IP address is not sent.
The Event log shows each server delivery with the request and Meta's response. If your margins differ a lot between products, you can also send a profit value next to each purchase: our guide to Meta value optimization for profit explains how. For the full data path from click to order, see server-side tracking.
Sources
- Meta for Developers: Handling Duplicate Pixel and Conversions API Events
- Meta for Developers: Server Event Parameters
- Meta for Developers: Customer Information Parameters
- Meta for Developers: Using the API - Conversions API
- Meta for Developers: ClickID and the fbp and fbc Parameters