Ad platforms and webshops

Meta Conversions API (CAPI): a practical guide

A practical guide to the Meta Conversions API: run it next to the pixel with one event_id, send the right parameters, test events and fix common errors.

·Updated ·9 min read·By the ROASaurus team

Key takeaways
  • 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.

FieldWhat it holds
event_nameThe action, for example Purchase, AddToCart or InitiateCheckout
event_timeWhen it happened, as a Unix timestamp in seconds
event_idA unique id for this event, used to deduplicate it against the pixel
action_sourceWhere it happened: website for store purchases
event_source_urlThe page URL where the event happened
user_dataCustomer information for matching: hashed email and phone, IP address, user agent, fbp and fbc
custom_dataDetails such as value, currency and content_ids
Every Conversions API event has the same shape: the action, the customer information and the details.

A trimmed Purchase event looks like this:

Conversions API: a Purchase event (trimmed)
{
  "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.

Meta pixel (browser)
  • 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
Conversions API (server)
  • 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 pixel brings the browser identifiers and the server brings the order. Each one alone misses part of the picture.

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.

Meta pixel: the same Purchase with eventID
fbq('track', 'Purchase', { value: 74.00, currency: 'USD' }, { eventID: 'order-1042' });
Shopper paysOrder 1042, $74.00
Pixel sends PurchaseeventID order-1042, from the browser
Server sends Purchaseevent_id order-1042, from the order
Meta counts oneSame name and id within 48 hours
Both copies carry the same event name and id, so Meta keeps one purchase instead of two.

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-1042 and 1042 are different ids.
  • Match the event name exactly. Purchase and purchase are 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.

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.

ParameterWebsite eventsWhat to send
event_nameRequiredA standard event such as Purchase, or a custom event name
event_timeRequiredUnix time in seconds, at most 7 days in the past
action_sourceRequiredwebsite for events on your store
event_source_urlRequiredThe page URL where the event happened
client_user_agentRequiredThe shopper's browser string, not the one of your server
user_dataRequiredAt least one customer information parameter
event_idRecommendedThe same id the pixel uses, for deduplication
em, phRecommendedEmail and phone, normalized and hashed with SHA-256
client_ip_addressRecommendedThe shopper's IP address, not hashed
fbp, fbcRecommendedThe browser id and click id cookies, not hashed
external_idRecommendedYour own customer id, the same on browser and server events
value, currencySend with PurchaseThe order value and a three-letter currency code
Meta lists action_source, event_source_url and client_user_agent as required for website events sent through the Conversions API.

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.com and anna@example.com give 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 fbc value is fb.1., the creation time in milliseconds, a dot, and the fbclid from the landing page URL. The fbclid is 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.

  1. Open Test events

    In Events Manager, select your dataset (pixel) and open the Test events tab. Copy the test code it shows.

  2. Add the code to your server events

    Send it as test_event_code in the request. In ROASaurus, paste it into the Test event code field of the Meta pixel.

  3. Place a test order

    Visit the store, add a product and pay, so that both the pixel and the server send a Purchase.

  4. Compare the two copies

    Both copies should show the same event name, event id, value and currency.

  5. 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.

  6. 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 pixel
Purchase server order-1042 74.00 USDFrom the Conversions API
event_name + event_id matchCounted as one purchase
em ph fbp fbc client_ip_address client_user_agentCustomer information on the server event
What a good test order shows (example values): two copies, one id and full customer information.

Common Conversions API errors and how to fix them

What you seeLikely causeFix
The whole request fails and no events are processedOne event in the batch has an event_time more than 7 days oldSend events when they happen. Fix or drop old events before you retry.
Meta reports more purchases than your shop hadDifferent event ids, a pixel event without eventID, or a second app that sends the same pixelUse one id for both copies and one server sender per pixel.
Low match quality on server eventsYour server sends its own IP address and user agentPass on the IP address and user agent recorded from the shopper's browser or order.
Few events with fbcThe fbclid was not saved on the landing page, or it was changedStore the fbclid exactly as it arrives and build fbc from it.
Email and phone do not matchValues hashed without normalizing, or sent without hashingTrim and lowercase the email, keep the digits and country code of the phone, then hash with SHA-256.
Requests fail with an expired token errorThe access token came from a Facebook login, and login tokens expireReconnect, or use a System User token from Business Manager, which you can create without an expiry date.
Most Conversions API problems show up as rejected requests, double counts or low match quality.

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 fbp and fbc saved 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

  1. Meta for Developers: Handling Duplicate Pixel and Conversions API Events
  2. Meta for Developers: Server Event Parameters
  3. Meta for Developers: Customer Information Parameters
  4. Meta for Developers: Using the API - Conversions API
  5. Meta for Developers: ClickID and the fbp and fbc Parameters

In ROASaurus

Keep reading

Ad platforms and webshopsCash on delivery conversion tracking and external checkoutsCash on delivery conversion tracking: why pixels miss COD and external checkout orders, when to send the purchase, and how to handle refused orders.Ad platforms and webshopsCCV Shop conversion tracking: a setup guideCCV Shop conversion tracking: send paid orders to Meta and TikTok with a signed webhook, link them to ad clicks, set up, test and handle late payments.Ad platforms and webshopsGoogle Ads enhanced conversions on ShopifyEnhanced conversions add hashed customer data to Google Ads purchases on Shopify. How they work, how they differ from offline imports, and the setup.
FAQ

Questions, answered

Do I need both the Meta pixel and the Conversions API?

Meta recommends using both. The pixel adds browser data such as the fbp cookie, and the Conversions API delivers events the browser misses. Give both copies the same event name and event id so Meta counts each event once.

How long does Meta wait to deduplicate a browser and a server event?

Meta deduplicates a browser event and a server event with the same event name and event id when they arrive within 48 hours of each other. A copy that arrives later is counted again.

Does the Conversions API need customer data to be hashed?

Yes, for contact data. Email, phone, name and address fields must be normalized and hashed with SHA-256. The IP address, user agent, fbp and fbc are sent without hashing.

Which fields are required for a website event?

Every event needs event_name, event_time, action_source and at least one customer information parameter. For website events, Meta also requires event_source_url and client_user_agent.

Can I send old orders through the Conversions API?

Only recent ones. The event_time can be at most 7 days in the past, and if one event in a request is older, Meta rejects the whole request.

Every sale, traced to the ad that earned it

Server-side tracking, profit and lifetime value in one app. 14-day free trial, no credit card.

Start your free trial →