Meta Conversions API

Meta CAPI with maximum Event Match Quality

Self-generated _fbp, captured _fbc from fbclid, SHA-256 hashed PII, and direct Graph API delivery. Higher Event Match Quality means better ad optimisation, lower CPA, and higher ROAS.

EMQ 9-10 territory

Most server-side implementations stall at EMQ 5-6 because they’re missing browser identifiers. Datafly Signal sends the complete identity parameter set on every event — fbp, fbc, em, ph, fn, ln, ct, st, zp, external_id, client_ip_address, client_user_agent, and fb_login_id. The result: match quality that lets Meta’s algorithm actually optimise.

Why Event Match Quality matters

Higher EMQ

Better ad optimisation

More identity signals per event means Meta can match conversions to ad impressions more accurately.

Lower CPA

More efficient spend

Better attribution data lets Meta's algorithm optimise delivery to users most likely to convert.

Higher ROAS

Better return on ad investment

Accurate conversion data feeds the optimisation loop, improving return on every pound spent.

Event Match Quality (EMQ) is Meta's score for how well your server events can be matched back to Meta users. It ranges from 0 to 10, and directly impacts how effectively Meta can optimise your ad delivery. Every additional identity parameter you send — fbp, fbc, em, ph — increases your match rate and improves ad performance.

Most server-side implementations struggle to reach EMQ 6 because they lack browser identifiers. Datafly Signal self-generates _fbp and captures _fbc from the fbclid URL parameter, closing the identity gap that other server-side solutions leave open.

Every identity signal, every event

Datafly Signal sends the complete set of identity parameters to Meta Conversions API on every event. Here is exactly what gets sent.

fbp
Source: Self-generated
Format: fb.1.{timestamp_ms}.{random_10_digit}
Description: Browser identifier. Generated server-side in the exact format Meta expects. Set as 400-day server cookie.
fbc
Source: fbclid URL param
Format: fb.1.{timestamp_ms}.{fbclid}
Description: Click identifier. Automatically captured from the fbclid query parameter when a user arrives from a Meta ad.
external_id
Source: Hashed user_id
Format: SHA-256
Description: Your internal user identifier, SHA-256 hashed. Enables Advanced Matching for logged-in users.
em
Source: traits.email
Format: SHA-256
Description: Email address, normalised (lowercase, trimmed) and SHA-256 hashed before transmission.
ph
Source: traits.phone
Format: SHA-256
Description: Phone number, normalised to E.164 format and SHA-256 hashed before transmission.
fn
Source: traits.first_name
Format: SHA-256
Description: First name, normalised (lowercase, trimmed) and SHA-256 hashed.
ln
Source: traits.last_name
Format: SHA-256
Description: Last name, normalised (lowercase, trimmed) and SHA-256 hashed.
ct / st / zp
Source: traits.city / state / zip
Format: SHA-256
Description: Location data, normalised and SHA-256 hashed. Improves match rates for geo-targeted campaigns.
client_ip_address
Source: context.ip
Format: Plain text
Description: Client IP address forwarded from the original request. Required by Meta for event deduplication.
client_user_agent
Source: context.userAgent
Format: Plain text
Description: Browser user agent string from the original request. Used by Meta for device-level matching.
fb_login_id
Source: Facebook Login
Format: Plain text
Description: If your site uses Facebook Login, the user's Facebook ID is forwarded for direct identity matching.

All PII is automatically SHA-256 hashed as required by Meta. Email, phone, names, and location data are normalised (lowercase, trimmed, formatted) and hashed before leaving your server. Raw PII never reaches the Meta API.

Pipeline as Code

Purpose-built Meta CAPI transformation

This pipeline config transforms an Order Completed track event into a Meta Conversions API purchase event. User data is automatically hashed, vendor IDs are enriched from cookies, and product data is mapped to Meta's content format.

  • user_data block with em, ph, fbp, fbc, external_id, IP, and user agent
  • custom_data block with content_ids extracted from product array
  • Automatic SHA-256 normalisation for all PII fields
  • Vendor ID enrichment from server-set _fbp and _fbc cookies
  • Output validation against Meta's API schema before delivery
meta-capi-purchase.yamlYAML
# meta-capi-purchase.yaml — Purchase event to Meta Conversions API
name: meta_capi_purchase
integration: meta-conversions-api
trigger:
  event: track
  conditions:
    - field: event
      operator: equals
      value: Order Completed

transform:
  # Event metadata
  static:
    - target: event_name
      value: Purchase
    - target: action_source
      value: website

  mapping:
    - source: timestamp
      target: event_time
      transform: unix_epoch

  # User data — auto-hashed PII
  user_data:
    - source: traits.email
      target: em
      transform: sha256_normalise
    - source: traits.phone
      target: ph
      transform: sha256_normalise
    - source: traits.first_name
      target: fn
      transform: sha256_normalise
    - source: traits.last_name
      target: ln
      transform: sha256_normalise
    - source: context.ip
      target: client_ip_address
    - source: context.userAgent
      target: client_user_agent

  enrichments:
    - type: vendor_id
      vendor: meta
      cookies: [_fbp, _fbc]
    - type: identity
      source: user_id
      target: external_id
      transform: sha256

  # Custom data — purchase details
  custom_data:
    - source: properties.products
      target: content_ids
      transform: pluck
      field: product_id
    - source: properties.products
      target: content_type
      value: product
    - source: properties.revenue
      target: value
    - source: properties.currency
      target: currency
      default: USD

output:
  format: meta_conversions_api
  endpoint: https://graph.facebook.com/v25.0/{pixel_id}/events
  auth: access_token
  validate: true

No Meta Pixel required

Datafly Signal delivers events directly to the Meta Conversions API via the Graph API. There is no Meta JavaScript in the browser at all.

Self-generated _fbp

Generated server-side in the exact Meta format (fb.1.{timestamp_ms}.{random_10_digit}) and set as a server-set cookie with 400-day expiry. Fully ITP-exempt.

Captured _fbc from fbclid

When a user arrives from a Meta ad, the fbclid query parameter is automatically captured and formatted as _fbc (fb.1.{timestamp_ms}.{fbclid}). Set as a 90-day server cookie.

ITP-exempt server cookies

Both _fbp (400-day) and _fbc (90-day) are set via Set-Cookie headers from your first-party subdomain. Safari ITP does not restrict server-set cookies on genuine first-party domains.

Direct Graph API v25.0 delivery

Events are delivered directly to graph.facebook.com/v25.0/{pixel_id}/events with your access token. Purpose-built delivery worker with exponential backoff retry.

Zero Meta JavaScript

No fbevents.js, no Meta Pixel, no Facebook SDK. The only JavaScript in the browser is your 5.2KB Datafly.js collector.

Event deduplication

Each event includes an event_id for server-to-server deduplication. If you run a hybrid setup during migration, Meta will automatically deduplicate overlapping events.

Enterprise Meta CAPI, the way it should be done

Plenty of options exist for sending events to Meta CAPI. SMB-grade tools, server-side proxies, Pixel-plus-CAPI hybrid setups. They get conversion data into Meta. They don’t get it into Meta the way an enterprise advertiser actually needs.

No Meta JavaScript anywhere in your browser

Meta CAPI events flow server-to-server from your infrastructure to the Graph API. Your pages get faster. Your ad-blocker exposure goes to zero. Your PageSpeed scores climb.

Every event stays inside your VPC until delivery

Full audit, PII handling, and governance happen in your environment before any data crosses to Meta. Your CISO sees the full event flow. Your compliance team has the audit trail.

The same event is delivered to every vendor that needs it

Meta CAPI, Google Enhanced Conversions, TikTok Events API, Snowflake, BigQuery, your CDP — each receives exactly the payload format it expects, simultaneously. One transformation pipeline, every destination.

Organisation-wide governance applies before vendor-specific logic

Schema validation, consent enforcement, PII handling, bot filtering — all run once, for every event, before the Meta-specific transformation kicks in. Enterprise-grade data quality, by default.

This is what Meta CAPI looks like when it’s part of your data infrastructure rather than a tactical fix.

Frequently asked questions

What is Meta Event Match Quality (EMQ) and why does it matter?
Event Match Quality is Meta's 0-10 score measuring how well it can match a CAPI event to a real Facebook or Instagram user. Higher EMQ means better attribution, better lookalike audiences, and lower CPA. Most teams plateau at EMQ 5-6 because they send only a couple of identifiers (email + IP). Datafly Signal sends the full identifier set (_fbp, _fbc, hashed email, hashed phone, hashed first/last name, IP, user agent) on every event, lifting EMQ into the 8-9 range.
How does server-side _fbp generation work without the Meta Pixel?
The _fbp cookie is a first-party browser cookie containing a randomly-generated identifier. The Meta Pixel sets it client-side. Datafly's gateway generates an _fbp value server-side on first visit and sets it via a Set-Cookie response header from your own subdomain. The format matches Meta's spec (fb.1.{timestamp}.{random}) so Meta's identity graph treats it identically to a Pixel-set _fbp.
How is _fbc captured from fbclid?
When a user lands from a Meta ad, the URL contains fbclid. Datafly.js extracts it on landing, the gateway formats it into the _fbc cookie value (fb.1.{timestamp}.{fbclid}), and stores it in the same 400-day server-set cookie as _fbp. Conversions weeks or months later still carry the _fbc, which is the signal Meta uses for click attribution.
Can I deduplicate against my existing Meta Pixel during migration?
Yes. Datafly Signal generates a deterministic event_id for every event, and emits both server-side via CAPI and (optionally) client-side via the Pixel during transition. Meta deduplicates on event_id, so you can run both in parallel for as long as needed and compare event counts between client-only and server+client modes before fully removing the Pixel.
What about iOS 14+ ATT and Aggregated Event Measurement?
Server-side CAPI sidesteps the in-browser tracking restrictions that ATT targets, since events are sent from your infrastructure to Meta's API. AEM still applies for impressions on iOS, but conversion attribution from CAPI events with hashed PII is not affected by ATT. This is one of the main reasons Meta themselves recommend CAPI as the priority delivery channel.

Improve your Event Match Quality

See how Datafly Signal sends the complete set of identity parameters on every Meta CAPI event. Higher EMQ, better optimisation, lower CPA.