Meta CAPI server-side setup inside GHL — full guide
The Pixel alone hasn’t been enough since iOS 14.5 dropped in 2021 and ATT (App Tracking Transparency) cut tracked-event volume by 40-60% on most accounts. Server-side Conversions API (CAPI) recovers most of that. Here’s the full setup inside GHL.
Why CAPI matters
The browser-side Pixel relies on the user’s browser to fire events. If the user blocks third-party cookies, opts out of ATT on iOS, or uses a privacy-focused browser, the events don’t fire. Meta’s optimization algorithms get fewer signals → worse ad performance.
Server-side CAPI sends events directly from your server to Meta’s API. The user can’t block them. Meta deduplicates against the Pixel events using event_id (we’ll cover that).
The combo of Pixel + CAPI typically recovers 25-40% of the events that ATT was eating, depending on your audience’s iOS share.
What you need
- A Meta Business Manager account
- A Meta Pixel ID
- A CAPI access token (generate in Events Manager → Data Sources → your Pixel → Settings → Generate Access Token)
- GHL with workflow access on the location you’re tracking
Step 1 — Pixel events firing client-side
Standard Pixel install on every page that matters. In GHL:
- Location-level settings → Tracking & SEO → Add the base Pixel snippet (Meta provides this).
- For specific events (Lead, CompleteRegistration, Purchase), use GHL’s built-in tracking config OR fire them via a small inline script tied to form submissions / button clicks.
For each event, generate an event_id (UUID). Pass the same event_id to both Pixel (client-side) and CAPI (server-side) — that’s how Meta deduplicates.
Example client-side event:
const eventId = crypto.randomUUID();
fbq('track', 'Lead', {
value: 0,
currency: 'USD',
}, { eventID: eventId });
// also send the eventId to your backend so it can fire CAPI with the same ID
Step 2 — CAPI events firing server-side
GHL doesn’t have a native “send to Meta CAPI” action. You have two paths:
Path A: GHL Webhook → middleware → Meta CAPI. Use a Make.com or Zapier scenario as the middleware. Trigger when a contact is created, custom field is updated, or pipeline stage moves.
Path B: GHL Webhook → custom endpoint you control → Meta CAPI. More flexible, requires hosting (a Cloudflare Worker is ~$0/mo at this volume).
The CAPI payload looks like:
{
"data": [{
"event_name": "Lead",
"event_time": 1715600000,
"event_id": "the-same-uuid-from-pixel",
"action_source": "website",
"event_source_url": "https://yourclient.com/contact",
"user_data": {
"em": ["sha256-of-email"],
"ph": ["sha256-of-phone"],
"client_ip_address": "1.2.3.4",
"client_user_agent": "Mozilla/...",
"fbp": "fb.1.1715600000.1234567890",
"fbc": "fb.1.1715600000.AbCdEfGh"
},
"custom_data": { "value": 0, "currency": "USD" }
}],
"access_token": "EAA..."
}
POST to https://graph.facebook.com/v19.0/{PIXEL_ID}/events.
Step 3 — Hashing PII
em (email), ph (phone), fn (first name), ln (last name) — all must be SHA-256 hashed before sending. Lowercase first, then hash:
const hash = await crypto.subtle.digest('SHA-256',
new TextEncoder().encode(email.toLowerCase().trim())
);
If you’re on Make.com, they have a built-in SHA-256 module. If you’re on a Cloudflare Worker, use the WebCrypto API as above.
Step 4 — Event prioritization (Aggregated Event Measurement)
iOS users running ATT see only your top 8 events. You configure the priority order in Events Manager → Data Sources → your Pixel → Aggregated Event Measurement → Configure Web Events.
Order matters. Your highest-value event (Purchase) should be #1. Lead should be #2 or #3. Page-level “ViewContent” events should be lowest priority — they get dropped first.
Step 5 — Verify the dedup is working
In Events Manager → Data Sources → your Pixel → Test Events:
- Trigger a test event (submit a form on your site)
- You should see the event arrive twice — once from Pixel (browser), once from Server (CAPI)
- After ~20 minutes, the deduplication report should show them as deduplicated (1 unique event with 2 sources)
If they’re NOT deduplicating, the event_id isn’t matching between Pixel and CAPI. That’s the most common bug.
Step 6 — Attribution validation
Wait 24-48 hours, then in Ads Manager:
- “Performance” breakdown → Compare conversions before vs after CAPI was added
- “Attribution Setting” → Set to 7-day click, 1-day view (default)
- Look at “Total Conversions” vs “Pixel-only Conversions”
You should see CAPI contributing 25-40% of total conversions on accounts with meaningful iOS traffic. If you see 5% or less, dedup is broken or events aren’t firing.
TL;DR
CAPI is the difference between Meta seeing your Lead events as “200 leads” vs “320 leads” on iOS-heavy audiences. The lift on Smart Bidding optimization is meaningful — usually 15-25% better cost-per-lead on a 30-day window after proper CAPI setup.
The setup is doable in 4-6 hours if you’ve done it before. If you haven’t, allow a full day plus debugging the dedup loop.
If you’d rather skip the dedup-debugging marathon, book the intro call. Meta Pixel + CAPI server-side is included in the Snapboard $1,295/mo retainer. We’ve shipped this dozens of times — first-pass dedup typically works because we have the patterns memorized.
Want this built for you?
Snapboard handles every part of GHL for marketing agencies. Flat $1,295/mo, 24-hour turnaround, pause anytime.
Book a 15-min intro call →