Systems Library / Marketing Automation / How to Set Up Conversion API (CAPI) for Meta Ads
Marketing Automation paid advertising

How to Set Up Conversion API (CAPI) for Meta Ads

Implement server-side tracking with CAPI to recover lost conversions.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

This meta ads conversion API CAPI setup guide walks through server-side event tracking from scratch. Browser-based pixels miss 20-30% of conversions due to ad blockers, cookie restrictions, and iOS privacy changes. CAPI sends events directly from your server to Meta, recovering that lost data.

I set this up for every ad account I manage. The difference in reported conversions is immediate and significant.

What You Need Before Starting

Step 1: Get Your CAPI Credentials

Go to Meta Events Manager. Select your pixel. Go to Settings. Generate a Conversions API access token. Store it:

META_PIXEL_ID=123456789
META_CAPI_TOKEN=your_capi_token_here

Step 2: Build the Event Sender

import requests
import hashlib
import time
import os
from dotenv import load_dotenv

load_dotenv()

PIXEL_ID = os.getenv("META_PIXEL_ID")
CAPI_TOKEN = os.getenv("META_CAPI_TOKEN")

def hash_value(value):
    if not value:
        return None
    return hashlib.sha256(value.strip().lower().encode()).hexdigest()

def send_event(event_name, email, phone=None, first_name=None, last_name=None,
               source_url=None, fbc=None, fbp=None, value=None, currency="USD"):
    
    user_data = {
        "em": [hash_value(email)] if email else None,
        "ph": [hash_value(phone)] if phone else None,
        "fn": [hash_value(first_name)] if first_name else None,
        "ln": [hash_value(last_name)] if last_name else None,
        "client_user_agent": "server-side",
    }
    
    if fbc:
        user_data["fbc"] = fbc
    if fbp:
        user_data["fbp"] = fbp
    
    # Remove None values
    user_data = {k: v for k, v in user_data.items() if v is not None}
    
    event = {
        "event_name": event_name,
        "event_time": int(time.time()),
        "action_source": "website",
        "event_source_url": source_url or "https://yoursite.com",
        "user_data": user_data,
    }
    
    if value:
        event["custom_data"] = {"value": value, "currency": currency}
    
    payload = {"data": [event]}
    
    url = f"https://graph.facebook.com/v19.0/{PIXEL_ID}/events"
    resp = requests.post(url, params={"access_token": CAPI_TOKEN}, json=payload)
    
    return resp.json()

Step 3: Send Lead Events

For form submissions and lead generation:

def track_lead(email, phone=None, first_name=None, source_url=None, fbc=None, fbp=None):
    result = send_event(
        event_name="Lead",
        email=email,
        phone=phone,
        first_name=first_name,
        source_url=source_url,
        fbc=fbc,
        fbp=fbp,
    )
    print(f"Lead event sent for {email[:3]}***: {result}")
    return result

Step 4: Send Purchase Events

For ecommerce or course sales:

def track_purchase(email, amount, currency="USD", phone=None, source_url=None, fbc=None, fbp=None):
    result = send_event(
        event_name="Purchase",
        email=email,
        phone=phone,
        value=amount,
        currency=currency,
        source_url=source_url,
        fbc=fbc,
        fbp=fbp,
    )
    print(f"Purchase event sent: ${amount} {currency}: {result}")
    return result

Step 5: Integrate with Your Form Handler

If you use Express (Node.js) for your form:

const express = require('express');
const app = express();

app.post('/form-submit', async (req, res) => {
    const { email, phone, firstName, lastName } = req.body;
    
    // Get Facebook click ID from cookies
    const fbc = req.cookies._fbc || null;
    const fbp = req.cookies._fbp || null;
    
    // Send to CAPI
    await fetch(`https://graph.facebook.com/v19.0/${process.env.META_PIXEL_ID}/events`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            data: [{
                event_name: 'Lead',
                event_time: Math.floor(Date.now() / 1000),
                action_source: 'website',
                event_source_url: req.headers.referer,
                user_data: {
                    em: [hashSha256(email.toLowerCase())],
                    ph: phone ? [hashSha256(phone)] : undefined,
                    fn: firstName ? [hashSha256(firstName.toLowerCase())] : undefined,
                    fbc: fbc,
                    fbp: fbp,
                },
            }],
            access_token: process.env.META_CAPI_TOKEN,
        }),
    });
    
    res.json({ success: true });
});

Step 6: Verify in Events Manager

Go to Meta Events Manager. Click "Test Events." Send a test submission from your site. You should see the event appear with "Server" as the source. If you have both pixel and CAPI running, Meta deduplicates automatically using the event ID.

Check the Event Match Quality score. Aim for 6.0 or higher. Adding more user data parameters (phone, name, city) improves match quality.

What to Build Next

Add event deduplication by passing a shared event ID between your browser pixel and CAPI calls. Then build a monitoring script that checks event delivery rates daily and alerts if CAPI events drop.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems