Meta Conversions API
Server-side conversions for Facebook and Instagram ads, deduplicated against the Meta pixel by event id.
Verified against the Meta documentation on 2026-09-03: Using the API, Server Event, Customer Information Parameters, Custom Data, Deduplication.
Prerequisites
- A Meta Business account with an ad account.
- A dataset (formerly "pixel") in Events Manager.
- Permission to generate a Conversions API access token for that dataset.
What to collect
| Value | Where to find it | Stored as |
|---|---|---|
| Dataset (pixel) ID | Events Manager → Data Sources → your dataset → Settings. A 15–16 digit number, also shown in the URL. | Config |
| Conversions API access token | Events Manager → your dataset → Settings → Conversions API → Generate access token. Copy it once; Meta does not show it again. | Vault |
| Test event code (optional) | Events Manager → your dataset → Test events tab. A short code like TEST12345. |
Config |
Also available:
- Graph API version — defaults to
v26.0. Conversions API versions are supported for at least two years, longer than the rest of the Graph API, so there is rarely a reason to change this. Bump it when you want a newer field. - Action source —
websiteunless the conversion genuinely happened somewhere else (app,phone_call,physical_store, …).
What SaaS Pro Max sends
POST https://graph.facebook.com/v26.0/{datasetId}/events?access_token=…
Content-Type: application/json
{
"data": [{
"event_name": "Purchase",
"event_time": 1786… ,
"event_id": "<the SaaS Pro Max event id>",
"action_source": "website",
"event_source_url": "https://example.com/checkout",
"user_data": {
"em": "<sha256 of the lowercased, trimmed email>",
"ph": "<sha256 of the digits, country code included, no leading +>",
"fn": "<sha256>", "ln": "<sha256>",
"external_id": "<sha256 of the distinct id>",
"ct": "<sha256 of the lowercased city with punctuation removed>",
"st": "<sha256>", "country": "<sha256 of the ISO alpha-2 code>",
"fbc": "fb.1.<ms>.<fbclid>",
"fbp": "<the _fbp cookie>",
"client_user_agent": "…"
},
"custom_data": {
"value": 49, "currency": "USD",
"contents": [{ "id": "SKU-1", "quantity": 2, "item_price": 20 }],
"content_ids": ["SKU-1"], "content_type": "product",
"num_items": 2, "order_id": "…"
}
}]
}
Notes that matter:
- Everything in
user_datais SHA-256 hashed exceptfbc,fbpandclient_user_agent. Meta rejects a hashed click or browser identifier. - The phone is hashed as digits with the country code and no leading
+(16505551212). This is the opposite of TikTok, which wants the+. The two adapters therefore produce different hashes from the same number, by design. - The email is hashed as typed after case folding. Meta does not fold Gmail dots or plus-addressing — Google Ads does, so those hashes differ too.
fbcis the_fbccookie when the SDK captured one, and is otherwise rebuilt from the capturedfbclidasfb.1.<event time in ms>.<fbclid>.client_ip_addressis not sent. SaaS Pro Max hashes IPs at ingest and never stores them, so there is nothing truthful to put there.
Standard event names
Use these in the mapping editor's "Meta standard event" column, spelled exactly:
AddPaymentInfo, AddToCart, AddToWishlist, CompleteRegistration,
Contact, CustomizeProduct, Donate, FindLocation, InitiateCheckout,
Lead, Purchase, Schedule, Search, StartTrial, SubmitApplication,
Subscribe, ViewContent.
Any other name is forwarded as a custom event: it works for reporting and audiences, but not for conversion optimisation.
Verifying
- Add your test event code to the destination configuration.
- Open Events Manager → your dataset → Test events.
- Press Send test event on the destination page in SaaS Pro Max.
- The event appears in the Test events tab within a few seconds, labelled "Server".
- Check the Event Match Quality score on the dataset overview after real traffic has flowed for a day.
Remove the test event code afterwards. Meta stores events sent with one and uses them for targeting and measurement, so leaving it in place is not harmless — it just makes them harder to find.
Deduplication with the pixel
Meta keeps the first copy of a given (event_id, event_name) pair for 48
hours. Send the SaaS Pro Max event id as the pixel's eventID and the same
event name in both places:
fbq("track", "Purchase", { value: 49, currency: "USD" }, { eventID: spmEventId });
If you cannot wire that up, use one source only.
Limitations
- No
client_ip_addressand, unless a server SDK supplies$user_agent, noclient_user_agent. Expect a slightly lower match quality than a vendor SDK running inside your request handler. event_timemay be at most 7 days in the past. An older conversion is rejected — for a long sales cycle, forward the event when it happens rather than backfilling.- One event per request. Meta accepts up to 1,000, but batching would tie unrelated conversions' fates together for no gain at SaaS Pro Max's volumes.
- A rejected payload is not retried: it would be rejected identically.