Meta CAPI (Conversions API) Setup Guide
Founder at Adship

The Meta Pixel alone is no longer sufficient for accurate conversion tracking. iOS privacy changes, ad blockers, and browser cookie restrictions have degraded pixel accuracy to 40–70% of actual events for most advertisers.
Meta Conversions API (CAPI) solves this by moving conversion data from the browser to your server, bypassing the privacy restrictions that break pixel tracking. This guide walks you through the complete CAPI setup — from Events Manager configuration through testing and validation.
What You'll Need Before Starting
Before configuring CAPI, confirm you have:
- Meta Business Manager access — Admin or developer role
- Ad account — Active account linked to your Business Manager
- Facebook Page — Associated with your business
- Server access — Ability to add code to your web server or ecommerce platform
- Pixel installed — Existing browser pixel recommended (for dual-tracking with deduplication)
- Access token — System user token or page token (covered in setup steps below)
Step 1: Create or Locate Your Dataset in Events Manager
Meta's Conversions API sends events to a dataset (previously called a pixel). If you have an existing pixel, your CAPI events should use the same dataset ID to enable deduplication between browser and server events.
- Go to Events Manager at business.facebook.com/events_manager
- Select your ad account from the top-left dropdown
- Click + Connect Data Sources if creating new, or select your existing pixel/dataset
- If creating new: choose Web → Conversions API → name your dataset
- Note the Dataset ID (also called Pixel ID) — you'll need it for all API calls
Step 2: Generate a System User Access Token
CAPI requires a long-lived access token. System user tokens are the recommended approach — they don't expire when users change passwords or revoke app permissions.
Create a System User
- In Business Manager, go to Business Settings → Users → System Users
- Click Add → name the system user (e.g., "CAPI Integration") → set role to Employee
- Click Add Assets → select your ad account → grant Advertiser access
- Click Add Assets → select your pixel/dataset → grant Analyze and Upload access
Generate the Token
- On the System User page, click Generate New Token
- Select your app (or create one at developers.facebook.com)
- Required permissions:
ads_management,ads_read,business_management - Set expiration: Never (for server-side automation)
- Copy and securely store the token — you won't be able to see it again
Step 3: Understand the CAPI Event Structure
Before implementing, understand what you're sending. Each CAPI event is a JSON payload sent to:
POST https://graph.facebook.com/v26.0/{dataset-id}/events
Minimum required fields:
{
"data": [
{
"event_name": "Purchase",
"event_time": 1741478400,
"action_source": "website",
"event_id": "order_12345_1678901234",
"user_data": {
"em": ["a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"],
"ph": ["7c4a8d09ca3762af61e59520943dc26494f8941b"],
"client_ip_address": "192.168.1.1",
"client_user_agent": "Mozilla/5.0..."
},
"custom_data": {
"value": 59.99,
"currency": "USD",
"order_id": "12345",
"content_ids": ["SKU-001", "SKU-002"],
"content_type": "product"
}
}
],
"access_token": "YOUR_ACCESS_TOKEN"
}
Key fields explained:
| Field | Required | Description |
|---|---|---|
event_name | Yes | Standard event name (Purchase, Lead, etc.) |
event_time | Yes | Unix timestamp when event occurred |
action_source | Yes | website, app, phone_call, email, other |
event_id | Dedup | Unique ID — must match pixel eventID for deduplication |
user_data.em | Recommended | SHA-256 hashed email |
user_data.ph | Recommended | SHA-256 hashed phone |
client_ip_address | Recommended | User's IP address (from request headers) |
client_user_agent | Recommended | User's browser agent string |
Step 4: Hash User Data Correctly
Meta requires PII to be SHA-256 hashed. Incorrect hashing is the most common setup error.
Hashing rules:
- Lowercase before hashing
- Remove whitespace before hashing
- Phone numbers: E.164 format without + (e.g.,
14155551234) - Email:
user@example.com→ lowercase → hash - Names: lowercase, no leading/trailing spaces
Python example:
import hashlib
def hash_data(value):
return hashlib.sha256(value.lower().strip().encode()).hexdigest()
hashed_email = hash_data("User@Example.com")
# Result: correct lowercase hash
Node.js example:
const crypto = require('crypto')
function hashData(value) {
return crypto.createHash('sha256')
.update(value.toLowerCase().trim())
.digest('hex')
}
Never send unhashed PII. Meta will reject events that appear to contain plain-text email addresses or phone numbers.
Step 5: Generate Event IDs for Deduplication
If you're running both pixel and CAPI (recommended), deduplication prevents Meta from counting the same conversion twice.
How deduplication works:
- Your browser pixel fires with
eventID: "order_12345_ts_1678901234" - Your server sends the same event with
event_id: "order_12345_ts_1678901234" - Meta sees matching IDs → counts as one event
Event ID generation strategy:
// Generate a stable, unique event ID for each conversion
function generateEventId(orderId) {
const timestamp = Math.floor(Date.now() / 1000)
return `order_${orderId}_${timestamp}`
}
// Pass to both pixel and CAPI:
const eventId = generateEventId(order.id)
// Pixel (browser):
fbq('track', 'Purchase', { value: 59.99, currency: 'USD' }, { eventID: eventId })
// CAPI (server):
// Send event_id: eventId in your API call
Important: Generate the event ID server-side and pass it to the browser for pixel use, not the other way around. This ensures consistency even if the browser is slow or blocks the pixel.
Step 6: Implement CAPI Events
Option A: Direct API Integration (Any Platform)
Send events directly from your server using HTTP:
// Node.js example
async function sendCapiEvent(eventName, orderData, userData) {
const DATASET_ID = process.env.META_PIXEL_ID
const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN
const payload = {
data: [{
event_name: eventName,
event_time: Math.floor(Date.now() / 1000),
action_source: 'website',
event_id: generateEventId(orderData.id),
user_data: {
em: [hashData(userData.email)],
ph: userData.phone ? [hashData(userData.phone)] : [],
fn: [hashData(userData.firstName)],
ln: [hashData(userData.lastName)],
ct: [hashData(userData.city)],
st: [hashData(userData.state)],
zp: [hashData(userData.zip)],
country: [hashData(userData.country)],
client_ip_address: userData.ipAddress,
client_user_agent: userData.userAgent,
external_id: [hashData(userData.userId)]
},
custom_data: {
value: orderData.total,
currency: orderData.currency,
order_id: orderData.id,
content_ids: orderData.items.map(i => i.sku),
content_type: 'product',
num_items: orderData.items.length
}
}],
access_token: ACCESS_TOKEN
}
const response = await fetch(
`https://graph.facebook.com/v26.0/${DATASET_ID}/events`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}
)
if (!response.ok) {
const error = await response.text()
throw new Error(`CAPI error: ${error}`)
}
return response.json()
}
Option B: Shopify (Native Integration)
- In Shopify Admin → Apps → Facebook & Instagram
- Under Data Sharing, enable Maximum level
- This activates Shopify's native analytics integration for purchase and checkout events
Note: Shopify's native integration sends purchase events but may miss other conversion events (add-to-cart, view content). For full coverage, supplement with a custom integration.
Option C: WooCommerce
- Install Official Meta for WooCommerce plugin (free from WordPress.org)
- Go to WooCommerce → Settings → Integration → Facebook
- Connect your Business Manager and enable CAPI
- Configure which events to send server-side
Step 7: Set Up Test Events
Before going live, verify your implementation sends correctly using Meta's Test Events tool.
- In Events Manager, select your dataset
- Click Test Events tab
- Copy the Test Event Code (format:
TEST12345) - Add
test_event_code: "TEST12345"to your API payload temporarily:
{
"data": [...],
"access_token": "YOUR_TOKEN",
"test_event_code": "TEST12345"
}
- Trigger test conversions on your website
- In Test Events, you should see events appear within 30–60 seconds
- Verify: event name, event parameters, user data fields received, deduplication working
What to check in test results:
- ✅ Event appears with correct name
- ✅ Custom data (value, currency) shows correctly
- ✅ Match quality indicator — should show at least 3–4 matching parameters
- ✅ If pixel is also firing: deduplication count shows > 0
- ⚠️ If events don't appear after 2 minutes: check your access token and dataset ID
Step 8: Monitor Event Match Quality
After going live, track your Event Match Quality (EMQ) score in Events Manager.
Where to find it: Events Manager → Select dataset → Overview tab → Event Match Quality column
Score interpretation:
- 6.0–7.0 — Excellent. Maximum attribution accuracy.
- 4.0–5.9 — Good. Solid attribution, room for improvement.
- 2.0–3.9 — Fair. Missing key match parameters.
- Below 2.0 — Poor. Attribution significantly degraded.
How to improve low EMQ:
| Missing parameter | Impact | Fix |
|---|---|---|
| High | Ensure you're capturing and hashing email from checkout | |
| Phone | Medium | Add phone field to checkout, hash before sending |
| First/last name | Medium | Pass from order data |
| City/state/zip | Low-Medium | Include from shipping address |
| External ID | Medium | Pass your internal user ID (hashed) |
Step 9: Validate Deduplication
In Events Manager, check that deduplication is working between your pixel and CAPI:
- Go to Events Manager → select your dataset
- Click Overview → find the Purchase event row
- Look at the Deduplicated column — this should show a percentage > 0% if both pixel and CAPI are sending the same events
Deduplication rate benchmarks:
- 60–80% — Normal for dual-tracking setup (some pixel events block, some don't)
- 90–100% — Both systems working perfectly with matching event IDs
- 0% — Event IDs don't match or only one system is sending
If deduplication shows 0%, your event IDs are not matching. Check that:
- Both pixel and server use the same event ID generation logic
- The pixel receives the server-generated event ID before firing
- Event IDs are unique per conversion (not reused)
Common Errors and Fixes
Error: "Invalid access token"
Cause: Token expired, permissions insufficient, or wrong token type. Fix: Regenerate system user token. Verify the system user has dataset access with "Upload" permission.
Error: "Invalid pixel ID" / "Dataset not found"
Cause: Wrong dataset ID, or system user doesn't have access to the dataset. Fix: Verify dataset ID in Events Manager URL. Add dataset to system user's assets.
Error: Events not appearing in Events Manager
Cause: Test event code not set (for test mode), events sent > 7 days ago, or API errors swallowed silently. Fix: Use test_event_code during testing. Log API responses in your server code. Check event_time is current Unix timestamp (not milliseconds).
Error: Low event match quality despite sending parameters
Cause: Incorrect hashing format (not lowercase, wrong encoding). Fix: Verify hashing: email must be lowercase before SHA-256. Phone must be digits only in E.164 format.
Error: Duplicate conversions in reporting
Cause: Deduplication not configured — both pixel and CAPI counting same event. Fix: Implement event_id on both pixel and CAPI calls. Confirm matching IDs using Test Events tool.
How Adship Simplifies CAPI Setup
Adship's tracking integration handles CAPI configuration without custom development:
- No-code CAPI setup — Connect your store in the Tracking page and Adship handles the server-side event pipeline automatically
- Automatic hashing — All PII is SHA-256 hashed before transmission; you never expose raw customer data
- Deduplication built-in — Event IDs are generated server-side and passed to both pixel and CAPI automatically
- EMQ optimization — All available match parameters collected and sent to maximize attribution quality
- Real-time monitoring — Event Match Quality scores and event volume visible in your Adship dashboard
- Multi-platform support — Same tracking infrastructure for Meta CAPI, TikTok Events API, and Google enhanced conversions
For advertisers without dedicated engineering resources, Adship eliminates the implementation complexity while delivering the same accuracy as a custom CAPI integration.
Next Steps After CAPI Setup
Once your implementation is live and validated:
- Monitor for 48–72 hours — Watch event volumes and EMQ scores in Events Manager
- Compare pixel vs CAPI volumes — CAPI should capture significantly more events than pixel alone
- Update campaign optimization — If using value-based bidding, expect ROAS reporting to improve as more conversions are attributed
- Expand to other events — Add CAPI for Lead, ViewContent, AddToCart after Purchase is working
- Review attribution windows — With accurate server data, you may be able to use shorter attribution windows confidently
Meet the AI Ad Operating System
Scan, spy, create, and launch Meta and TikTok ads with guarded actions taken with your approval.
Start FreeRecommended Resources
Related Articles
View allMeta Pixel Helper: Install, Read, and Fix Errors (2026)
Install the official Meta Pixel Helper, read Pixel and event statuses, fix common errors, and verify conversion tracking before campaign launch.
How to Manage Facebook and TikTok Ads Together (2026 Guide)
Running Facebook and TikTok ads from two separate dashboards costs you time and money. Here's how to manage both platforms without the chaos.
How to Block Meta Ad Enhancements in 2026
Meta keeps adding AI-powered "enhancements" to your ads, music, 3D motion, text overlays, and more. Here's how to disable them all and keep your creatives exactly as you designed them.