Meta Ads Setup & Implementation | OpsBlu Docs

Meta Ads Setup & Implementation

How to implement Meta Ads with Facebook Pixel and Conversions API (CAPI). Covers pixel installation, server-side event tracking, Aggregated Event.

Meta Ads conversion tracking has two parallel systems: the Facebook Pixel (client-side browser JavaScript) and the Conversions API (server-side HTTP calls). Running only one of these is a mistake. The Pixel alone loses events to ad blockers, ITP cookie restrictions, and browser crashes. The Conversions API alone misses real-time behavioral signals like scroll depth and time on page. A proper implementation runs both in parallel with event deduplication, giving Meta's delivery system the maximum signal to optimize campaign performance.

Why Proper Implementation Matters

The iOS 14+ Attribution Gap

Apple's App Tracking Transparency (ATT) framework fundamentally changed Meta Ads measurement:

  • Users who opt out of tracking (approximately 75-85% on iOS) lose deterministic attribution
  • Meta's Aggregated Event Measurement (AEM) limits you to 8 prioritized conversion events per domain
  • Attribution windows shrink from 28-day click / 1-day view to 7-day click / 1-day view for opted-out users
  • Conversions API data helps Meta model the conversions it can no longer directly observe

Without CAPI, you are giving Meta roughly 50% less data than it needs for accurate optimization.

The Ad Blocker Problem

Browser-based ad blockers affect 25-40% of desktop users:

  • The Facebook Pixel is blocked by uBlock Origin, Brave browser, Firefox Enhanced Tracking Protection, and others
  • Blocked pixels mean zero conversion data from a significant portion of your traffic
  • Conversions API bypasses ad blockers entirely because it sends data server-to-server
  • The combination gives you maximum coverage across all user segments

Event Match Quality Determines Ad Delivery

Meta's Event Match Quality (EMQ) score (1-10) directly affects:

  • Delivery optimization: Higher EMQ means Meta can better identify who converted, improving lookalike audiences
  • Cost efficiency: Better matching reduces wasted impressions on users who already converted
  • Attribution accuracy: More matched events means fewer "unknown" conversions in reporting
  • Custom audience quality: Retargeting audiences are more complete with higher match rates

Implementing advanced matching (hashed email, phone, name, address) alongside CAPI typically lifts EMQ from 3-4 to 7-9.

Pre-Implementation Planning

Access and Permissions

Business Manager Setup:

  1. Go to business.facebook.com and verify your business (if not already verified)
  2. Business verification is required for CAPI, domain verification, and AEM configuration
  3. Verification requires a business phone number, legal name, and government documents

Required Access:

Platform Role Purpose
Business Manager Admin Domain verification, pixel ownership
Events Manager Full Control Pixel configuration, CAPI setup, diagnostics
Google Tag Manager Publish Deploy pixel tags
Server environment Deploy Set up CAPI endpoint

Key IDs to Collect:

  • Pixel ID: Found in Events Manager > Data Sources > Your Pixel > Settings (format: 15-digit number)
  • Access Token: Generated in Events Manager > Settings > Generate Access Token (used for CAPI)
  • Business Manager ID: In Business Settings > Business Info
  • Domain: Must be verified in Business Manager > Brand Safety > Domains

Aggregated Event Measurement Configuration

Before deploying any tracking, configure your 8 prioritized events:

  1. In Events Manager, navigate to Aggregated Event Measurement tab
  2. Select your verified domain
  3. Prioritize up to 8 conversion events in order of business importance:
Priority Event Example Use
1 (highest) Purchase E-commerce revenue tracking
2 InitiateCheckout Checkout funnel optimization
3 AddToCart Mid-funnel signal
4 CompleteRegistration Account creation
5 Lead Form submissions
6 ViewContent Product page views
7 AddPaymentInfo Payment intent signal
8 Search Search behavior

Important: After changing event priorities, there is a 72-hour cooldown before events optimize normally. Plan changes during low-traffic periods.

Conversion Value Strategy

Business Type Value Approach Implementation
E-commerce Actual transaction value Pass value and currency with Purchase event
SaaS Estimated LTV by plan Map plan tier to value (Free=$0, Pro=$50, Enterprise=$200)
Lead gen Estimated close value Assign value based on lead score or form type
Media/Publishing Pageview value Use RPM-based calculation for content value

Implementation Walkthrough

Step 1: Deploy Facebook Pixel Base Code

The base pixel code goes on every page of your website. It fires a PageView event automatically.

Direct Installation:

<!-- Facebook Pixel Code -->
<script>
  !function(f,b,e,v,n,t,s)
  {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
  n.callMethod.apply(n,arguments):n.queue.push(arguments)};
  if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
  n.queue=[];t=b.createElement(e);t.async=!0;
  t.src=v;s=b.getElementsByTagName(e)[0];
  s.parentNode.insertBefore(t,s)}(window, document,'script',
  'https://connect.facebook.net/en_US/fbevents.js');
  fbq('init', 'YOUR_PIXEL_ID');
  fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
  src="https://www.facebook.com/tr?id=YOUR_PIXEL_ID&ev=PageView&noscript=1"/>
</noscript>
<!-- End Facebook Pixel Code -->

Via Google Tag Manager:

  1. Create a new tag: Tag Type > Meta Pixel (or Custom HTML)
  2. If using the native Meta Pixel tag type:
    • Enter your Pixel ID
    • Select "PageView" as the event
    • Trigger: All Pages
  3. If using Custom HTML, paste the pixel code above
  4. Set the trigger to All Pages with appropriate consent conditions

Step 2: Implement Standard Events with Parameters

Fire standard events on conversion pages with full parameters for maximum signal:

// Product Page View
fbq('track', 'ViewContent', {
  content_name: 'Premium Widget',
  content_ids: ['SKU-12345'],
  content_type: 'product',
  value: 49.99,
  currency: 'USD'
});

// Add to Cart
fbq('track', 'AddToCart', {
  content_ids: ['SKU-12345'],
  content_type: 'product',
  value: 49.99,
  currency: 'USD',
  contents: [{ id: 'SKU-12345', quantity: 1 }]
});

// Initiate Checkout
fbq('track', 'InitiateCheckout', {
  content_ids: ['SKU-12345', 'SKU-67890'],
  content_type: 'product',
  value: 129.98,
  currency: 'USD',
  num_items: 2
});

// Purchase (most critical event)
fbq('track', 'Purchase', {
  content_ids: ['SKU-12345', 'SKU-67890'],
  content_type: 'product',
  value: 129.98,
  currency: 'USD',
  contents: [
    { id: 'SKU-12345', quantity: 1 },
    { id: 'SKU-67890', quantity: 1 }
  ],
  order_id: 'ORD-2024-12345'  // Required for CAPI deduplication
});

// Lead Form Submission
fbq('track', 'Lead', {
  content_name: 'Contact Form',
  value: 50.00,
  currency: 'USD'
});

Step 3: Enable Advanced Matching

Advanced matching sends hashed user data with pixel events, dramatically improving Event Match Quality.

Automatic Advanced Matching (simplest):

fbq('init', 'YOUR_PIXEL_ID', {
  em: 'customer@example.com',        // Email (auto-hashed by pixel)
  ph: '15551234567',                  // Phone (auto-hashed)
  fn: 'john',                         // First name (auto-hashed)
  ln: 'doe',                          // Last name (auto-hashed)
  ct: 'new york',                     // City
  st: 'ny',                           // State (2-letter code)
  zp: '10001',                        // Zip code
  country: 'us',                      // Country (2-letter code)
  external_id: 'USER-12345'           // Your internal user ID
});

Manual Advanced Matching (more control):

// Initialize without user data
fbq('init', 'YOUR_PIXEL_ID');

// Set user data when available (e.g., after login or form fill)
fbq('init', 'YOUR_PIXEL_ID', {
  em: document.getElementById('email').value.toLowerCase().trim(),
  fn: document.getElementById('first-name').value.toLowerCase().trim(),
  ln: document.getElementById('last-name').value.toLowerCase().trim()
});

Also enable in Events Manager:

  1. Go to Events Manager > Your Pixel > Settings
  2. Scroll to "Automatic Advanced Matching"
  3. Toggle ON and select which fields to match

Step 4: Implement Conversions API (CAPI)

CAPI sends events server-to-server, bypassing ad blockers and browser restrictions.

Server-Side Implementation (Node.js):

const crypto = require('crypto');
const https = require('https');

const PIXEL_ID = 'YOUR_PIXEL_ID';
const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';
const API_VERSION = 'v19.0';

function hashData(value) {
  if (!value) return null;
  return crypto.createHash('sha256')
    .update(value.toLowerCase().trim())
    .digest('hex');
}

async function sendConversionEvent(eventData) {
  const payload = {
    data: [{
      event_name: eventData.event_name,
      event_time: Math.floor(Date.now() / 1000),
      event_id: eventData.event_id,  // Must match pixel event_id for dedup
      event_source_url: eventData.source_url,
      action_source: 'website',
      user_data: {
        em: [hashData(eventData.email)],
        ph: [hashData(eventData.phone)],
        fn: [hashData(eventData.first_name)],
        ln: [hashData(eventData.last_name)],
        ct: [hashData(eventData.city)],
        st: [hashData(eventData.state)],
        zp: [hashData(eventData.zip)],
        country: [hashData(eventData.country)],
        client_ip_address: eventData.ip_address,
        client_user_agent: eventData.user_agent,
        fbc: eventData.fbc,   // _fbc cookie value
        fbp: eventData.fbp,   // _fbp cookie value
        external_id: [hashData(eventData.user_id)]
      },
      custom_data: {
        value: eventData.value,
        currency: eventData.currency || 'USD',
        content_ids: eventData.content_ids,
        content_type: eventData.content_type,
        order_id: eventData.order_id
      }
    }]
  };

  const url = `https://graph.facebook.com/${API_VERSION}/${PIXEL_ID}/events?access_token=${ACCESS_TOKEN}`;

  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  });

  return response.json();
}

// Example: Send purchase event from your order confirmation handler
sendConversionEvent({
  event_name: 'Purchase',
  event_id: 'purchase_ORD-2024-12345',  // Same ID sent via pixel
  source_url: 'https://yoursite.com/order-confirmation',
  email: 'customer@example.com',
  phone: '+15551234567',
  first_name: 'John',
  last_name: 'Doe',
  ip_address: req.ip,
  user_agent: req.headers['user-agent'],
  fbc: req.cookies._fbc,
  fbp: req.cookies._fbp,
  value: 129.98,
  currency: 'USD',
  content_ids: ['SKU-12345', 'SKU-67890'],
  content_type: 'product',
  order_id: 'ORD-2024-12345',
  user_id: 'USER-12345'
});

Step 5: Event Deduplication

Both the Pixel and CAPI will send the same events. Meta deduplicates using event_id:

// On the client (pixel), generate a unique event ID
const eventId = 'purchase_' + orderId + '_' + Date.now();

// Send via pixel
fbq('track', 'Purchase', {
  value: 129.98,
  currency: 'USD',
  content_ids: ['SKU-12345'],
  order_id: 'ORD-2024-12345'
}, { eventID: eventId });

// Send the SAME event_id to your server for CAPI
fetch('/api/track-conversion', {
  method: 'POST',
  body: JSON.stringify({
    event_name: 'Purchase',
    event_id: eventId,  // SAME ID
    value: 129.98,
    order_id: 'ORD-2024-12345'
  })
});

Deduplication rules:

  • Events with the same event_id AND event_name within 48 hours are deduplicated
  • If event_id is missing, Meta uses fbp + event_name + event_time (less reliable)
  • Always send event_id from both Pixel and CAPI

Step 6: Verify Domain and Configure Events

  1. Domain Verification:

    • In Business Manager, go to Brand Safety > Domains
    • Add your domain and verify via DNS TXT record or meta tag
    • Domain verification is required for AEM configuration
  2. Configure Aggregated Event Measurement:

    • In Events Manager, go to the Aggregated Event Measurement tab
    • Select your verified domain
    • Set your 8 event priorities (see planning section above)
    • Wait 72 hours for changes to take effect

Verification and QA

Facebook Pixel Helper

Install the Meta Pixel Helper Chrome extension:

  1. Navigate to each page in your conversion funnel
  2. Click the Pixel Helper icon
  3. For each page, verify:
    • Pixel ID is correct
    • Events fire with correct names
    • Parameters are populated (value, content_ids, currency)
    • Advanced matching data is present (shown as "Matched Parameters")
    • No errors or warnings

Events Manager Test Events

  1. In Events Manager, click Test Events tab
  2. Enter your website URL
  3. Open the URL in a new tab
  4. Complete conversion actions
  5. Events appear in real-time in the Test Events panel
  6. Verify event names, parameters, and deduplication status

Event Match Quality Score

  1. In Events Manager, go to Overview
  2. Click on each event to see its Event Match Quality score
  3. Target: EMQ of 6.0 or higher (7.0+ is excellent)
  4. If EMQ is low:
    • Add more advanced matching parameters (especially email)
    • Ensure fbc and fbp cookies are being passed via CAPI
    • Add client_ip_address and client_user_agent to CAPI payloads

CAPI Diagnostics

  1. In Events Manager, go to Diagnostics tab
  2. Check for:
    • Event deduplication rate: Should be 5-20% (too high means mostly duplicate, too low means CAPI not matching pixel)
    • Parameter issues: Missing required fields
    • Server errors: Failed API calls
    • Data freshness: Events should arrive within seconds

Common Issues

Issue Cause Fix
Events not appearing Pixel blocked or consent gate Check Pixel Helper, verify consent flow
Duplicate events Missing event_id in pixel or CAPI Add matching event_id to both
Low EMQ score Missing user data Add email, phone, and fbc/fbp cookies
CAPI events rejected Invalid access token or payload format Regenerate token, validate JSON schema
AEM events not optimizing Wrong priority order or 72-hour cooldown Review priorities, wait for cooldown
Value showing as $0 value parameter missing or not a number Check data layer variable type

Deployment Artifacts

  • Pixel ID and Access Token: Store securely (access token is equivalent to API credentials)
  • Tracking plan: All events with parameters, deduplication IDs, and pixel/CAPI source
  • GTM container documentation: Tag names, triggers, variables, version history
  • CAPI endpoint documentation: Server endpoint URL, authentication, and payload schema
  • Advanced matching fields: Which user data fields are collected and how they are hashed
  • AEM configuration: Domain, 8 prioritized events with rationale
  • Environment matrix: Pixel ID, access token, and CAPI endpoint per environment
  • Consent implementation: CMP integration, consent gates for pixel and CAPI
  • Business Manager verification: Status, verified domain, and pixel ownership documentation

Linked Runbooks

Change Log and Owners

  • Maintain a changelog with date, deployer, pixel updates, and event changes
  • Record AEM priority changes with 72-hour cooldown dates
  • Document Business Manager verification status and domain ownership
  • Track CAPI access token rotation schedule (tokens do not expire but should be rotated)
  • Review monthly: EMQ scores, deduplication rates, diagnostic alerts