Privacy-First Measurement: Server-Side Tagging, Consent Mode and Conversion APIsConversion APIs: Meta, Google, TikTok and LinkedIn · Lesson 7 of 14
Meta Conversions API: payloads, matching and deduplication
Video lecture
Meta Conversions API: payloads, matching and deduplication
The narrated lecture is in production
Every chapter is scripted and ready. Browse the chapters and read the full transcript now — the video will appear here when it’s published.
Chapters
Transcript of the narration, chapter by chapter.
0:00 Meta Conversions API
If your Meta ads report far fewer purchases than your store actually made, you're not just losing reporting. You're starving the algorithm. In this lecture you'll learn how the Meta Conversions API fills that gap: the implementation routes, the anatomy of an event, how deduplication really works, and how to use Event Match Quality and diagnostics to prove it's working.
0:26 Why it matters
Why does this matter? Because Meta's delivery system learns from the conversions it receives, and if it only sees part of your sales, it learns a partial lesson. Here's an analogy. Imagine coaching a sprinter while only seeing some of their races. You'd give advice based on an incomplete picture. The Pixel is watching from the stands, and sometimes the view is blocked. The Conversions API is the official race results sent straight from the timing system. Use both, make sure each race is only counted once, and the coach finally sees the whole season.
1:07 Pixel + CAPI
The Conversions API sends events from your server straight to Meta. Meta recommends running it alongside the Pixel, not instead of it, with deduplication. The browser Pixel captures rich context. The server fills gaps when browsers block the Pixel, and it can carry stronger matching data from your order system. Together, more of your real conversions reach Meta, and they're easier to match to the people who saw your ads.
1:37 Four routes
There are four ways to implement it. Partner integrations, like Shopify's, are the fastest, but check which events and parameters they actually send. The Conversions API Gateway is a Meta-provided, self-hosted option. Server-side Tag Manager can run Meta's Conversions API tag template. Or you integrate directly from your backend through the Graph API. The lesson shows the direct route in Python, because understanding it makes every other route easier to debug.
2:08 Event anatomy
Let's look at an event. Event name, like purchase. Event time, a Unix timestamp in seconds. An event ID, ideally your order ID. The action source, for example website or physical store. The page URL. Then user data: email, phone and your customer ID, all normalized and hashed with SHA two fifty-six, plus IP address, user agent and Meta's own browser identifiers, f b p and f b c, which are sent unhashed. Finally custom data: currency, value and order ID.
2:43 Simple example: order 1042
Here's a simple worked example of deduplication. Order number ten forty-two is placed at 7:15 in the evening. The browser Pixel fires Purchase with event ID order underscore ten forty-two. Two seconds later, the server sends Purchase through the Conversions API with the same event ID, plus hashed email and phone. Meta sees two events with the same name and ID, keeps one, and enriches its matching with the server's data. Now imagine the developer had used a random ID in the browser. Meta would count two purchases, cost per purchase would look half as high as reality, and the algorithm would scale the wrong things.
3:29 Deduplication
Deduplication is where most setups go wrong. When the Pixel and the server both send the same purchase, Meta removes the duplicate only if the event name matches and the server's event ID equals the browser's event ID. So generate one ID per real conversion, the order ID is perfect, and pass it to both. If the IDs differ, Meta counts two purchases, your cost per purchase looks half what it really is, and the algorithm scales the wrong things.
4:04 Direct integration in Python
Now the code. Read the pixel ID, access token and Graph API version from environment variables, never hard-coded. Check advertising consent first, and if the user refused, don't send. Build the event, hash the email, phone and customer ID, forward IP, user agent, f b p and f b c, and remove any empty fields. While testing, include a test event code. Post to the events endpoint, and raise an error with the response body if it fails, so problems are visible.
4:40 Verify and improve
How do you know it's working? Events Manager gives you three tools. The Test Events tab shows events arriving in real time when you use the test code. Diagnostics flags problems like missing deduplication keys or invalid parameters. And Event Match Quality scores how well your customer information can be matched. Improve it by adding hashed email and phone, your customer ID, and the browser identifiers, wherever that's lawful.
5:10 Example: Jeddah abaya brand (illustrative)
Here's an illustrative example. A Jeddah abaya brand ran the Pixel alone, which was blocked for a meaningful share of Safari and in-app browser traffic, and their match quality was poor. They added the Conversions API from their order system, using order IDs for deduplication, hashed email and phone captured at checkout, and the browser identifiers forwarded. Match quality improved, reported purchases moved closer to real orders, and they verified deduplication by comparing Events Manager counts with their backend.
5:44 Pitfalls
Four pitfalls to avoid. Different IDs in browser and server events. Hashing the IP address or user agent, which must be sent as they are. Sending events for users who refused advertising consent. And sending sensitive data, like health conditions or financial details, in custom data or URLs, which Meta's terms prohibit and regulators punish.
6:08 Mistakes + try this now
Common Conversions API mistakes. Different IDs in browser and server events. Hashing the IP address or user agent, which must be sent as they are. Using the server's own IP instead of the customer's original IP. Leaving the test event code in production. And sending events for users who declined advertising consent. Try this now: open Events Manager, go to your purchase event, and check the deduplication and match quality indicators. Write down the score and the top recommendation Meta gives. That recommendation is usually your quickest win.
6:46 Watch me do it: testing CAPI (illustrative)
Watch me do it. Let's test a Conversions API integration for an illustrative Riyadh bookstore before going live. Step one, in Events Manager I copy the test event code and set it as an environment variable in staging. Step two, I place a test order. In Test Events, two purchase events appear within seconds: one from the browser and one from the server, both with event ID order underscore five five one two. The server one shows as deduplicated, so the IDs match. Step three, I open the server event's details and check parameters: hashed email present, hashed phone present, external ID present, client IP looks like a real user address, not our server's, and f b p is present, but f b c is missing. Why? This order didn't come from an ad click, so there was no f b c l i d. That's expected. Step four, I place an order through a URL with a test f b c l i d, and now f b c appears. Step five, I remove the test code, deploy to production, and after a few days check Event Match Quality and the dedup indicator. Only then do I compare Meta's purchases with backend orders.
8:15 Recap and next step
Recap. Run the Conversions API alongside the Pixel. Deduplicate with a shared event ID. Hash personal identifiers, send the technical ones unhashed. Verify with Test Events, Diagnostics and match quality. And always respect consent. Your next step: map your purchase flow, from where the order ID is created, to how it reaches both the Pixel and the server event, which identifiers you can lawfully send, and where consent is checked.
Why the Conversions API
The Meta Conversions API (CAPI) sends web, app and offline events from your server directly to Meta. Meta recommends using it alongside the Meta Pixel, with deduplication, so that events blocked or lost in the browser still reach Meta and events carry stronger matching data. Better event coverage and matching generally improve optimization and measurement.
Implementation routes:
- Partner integrations (Shopify, WooCommerce, other platforms) — quickest; check which events and parameters they send.
- Conversions API Gateway — a Meta-provided, self-hosted solution for web events.
- Server-side GTM with Meta's Conversions API tag template.
- Direct integration via the Graph API from your backend.
Anatomy of an event
{
"data": [{
"event_name": "Purchase",
"event_time": 1758787200,
"event_id": "order_10042",
"action_source": "website",
"event_source_url": "https://shop.example.ae/checkout/thank-you",
"user_data": {
"em": ["<sha256 of normalized email>"],
"ph": ["<sha256 of normalized phone>"],
"external_id": ["<sha256 of your customer id>"],
"client_ip_address": "<from request>",
"client_user_agent": "<from request>",
"fbp": "fb.1.1758700000000.123456789",
"fbc": "fb.1.1758700000000.IwAR..."
},
"custom_data": {"currency": "AED", "value": 425.50, "order_id": "10042"}
}]
}- event_time is a Unix timestamp in seconds; send events promptly (Meta limits how old website events can be — check the current window).
- action_source describes where the conversion happened (
website,app,physical_store,system_generated, etc.). - user_data hashed fields (em, ph, fn, ln, ct, st, zp, country, external_id) must be normalized and SHA-256 hashed;
client_ip_address,client_user_agent,fbpandfbcare sent unhashed. - fbp is the
_fbpbrowser cookie; fbc is the_fbccookie or built from thefbclidURL parameter (fb.1.<timestamp>.<fbclid>).
Deduplication
When both the Pixel and CAPI send the same event, Meta deduplicates if event_name matches and event_id (server) equals eventID (browser). Generate one ID per real conversion (the order ID is ideal) and pass it to both:
// Browser (Pixel), only after advertising consent
fbq('track', 'Purchase', {value: 425.50, currency: 'AED'}, {eventID: 'order_10042'});Hands-on: direct server integration (Python)
import os, time, hashlib, requests
PIXEL_ID = os.environ["META_PIXEL_ID"]
TOKEN = os.environ["META_CAPI_TOKEN"]
API_VERSION = os.environ.get("META_GRAPH_VERSION", "v23.0") # set to a currently supported version
TEST_CODE = os.environ.get("META_TEST_EVENT_CODE") # only while testing
h = lambda v: hashlib.sha256(v.strip().lower().encode()).hexdigest()
def send_purchase(order, req, consent_ads: bool):
if not consent_ads:
return None # respect the user's choice for advertising
event = {
"event_name": "Purchase",
"event_time": int(time.time()),
"event_id": f"order_{order['id']}",
"action_source": "website",
"event_source_url": order["thank_you_url"],
"user_data": {
"em": [h(order["email"])] if order.get("email") else [],
"ph": [h(order["phone_e164"].lstrip('+'))] if order.get("phone_e164") else [],
"external_id": [h(str(order["customer_id"]))],
"client_ip_address": req["ip"],
"client_user_agent": req["user_agent"],
"fbp": req["cookies"].get("_fbp"),
"fbc": req["cookies"].get("_fbc"),
},
"custom_data": {"currency": order["currency"], "value": order["value"], "order_id": str(order["id"])},
}
event["user_data"] = {k: v for k, v in event["user_data"].items() if v}
body = {"data": [event]}
if TEST_CODE:
body["test_event_code"] = TEST_CODE
r = requests.post(f"https://graph.facebook.com/{API_VERSION}/{PIXEL_ID}/events",
params={"access_token": TOKEN}, json=body, timeout=10)
if r.status_code >= 400:
raise RuntimeError(f"CAPI error {r.status_code}: {r.text}")
return r.json()Check the Graph API changelog for the current version and the Conversions API parameter reference for normalization rules (e.g., phone digits with country code, no leading zeros).
Offline and CRM events
CAPI is not only for websites. With action_source set to physical_store, phone_call, system_generated or similar, you can send store purchases, phone orders and CRM stages (for example a lead that became a qualified customer). Match them on hashed email, phone and external_id, and for leads captured by Meta instant forms, include the Meta lead ID where supported so the outcome links back to the original lead. This lets lead-gen campaigns optimize toward qualified outcomes instead of raw form submissions.
Event Match Quality and diagnostics
In Events Manager, Event Match Quality (EMQ) scores how well your events' customer information can be matched. Improve it by adding hashed email/phone, external_id, fbc/fbp, IP and user agent where lawful. The Test Events tab shows events in real time (use the test code), and Diagnostics flags issues such as missing deduplication keys, invalid parameters or low coverage.
Worked example: a Jeddah abaya brand
Initially: Pixel only, blocked for a meaningful share of Safari and in-app browser traffic, EMQ "poor". After adding CAPI from the order system (with order IDs for dedup, hashed email and phone captured at checkout, fbc/fbp forwarded), EMQ improved and reported purchases moved closer to backend orders. The brand verified dedup by comparing Events Manager's "deduplicated" counts with orders.
Pitfalls
- Different IDs in browser and server events (double counting).
- Hashing IP address or user agent (they must not be hashed).
- Sending events for users who refused advertising consent.
- Sending sensitive data (health conditions, financial details) in custom_data or URLs — Meta's terms prohibit it.
How to measure success
Deduplication working (no inflated counts), EMQ trending up, reported purchases within an expected band of backend orders, and zero policy warnings about sensitive data.
Key takeaways
- Run Meta CAPI alongside the Pixel with deduplication for better coverage and matching.
- Dedup requires the same event_name and matching event_id/eventID — use the order ID.
- Hash identifiers (em, ph, external_id) with SHA-256; send IP, user agent, fbp and fbc unhashed.
- Use Test Events, Diagnostics and Event Match Quality to verify and improve.
- Respect advertising consent and never send sensitive data.
Check your understanding
Quick questions to lock in the lesson. They don’t count towards your certificate.
Put it into practice
Map your purchase flow: where the order ID is created, how it reaches the Pixel eventID and the CAPI event_id, which identifiers you can lawfully send, and how consent is checked.
Enrol for free to save your progress
Reading is always free. Enrol to keep your place, take the final assessment and earn a verifiable certificate.