Skip to main content

Forward events to Meta Conversions API

Send Snowplow events to Meta for ad measurement, attribution, and campaign optimization using the Conversions API. The Conversions API delivers events server-side, which complements the browser Pixel and improves measurement when browser signals are unavailable.

Prerequisites

Before setting up the forwarder in Console, you'll need the following from your Meta account:

  • Pixel ID: the ID of the Meta Pixel (or Dataset) that receives the events. Meta uses the Pixel ID and Dataset ID interchangeably for the Conversions API.
  • Access token: a system user access token with the ads_management permission. Generate it in Meta Events Manager or the Meta Business Suite.
  • Test event code (optional): a code from the Test events tab in Events Manager, used to validate your setup. Events sent with it appear only in Test events, not in your live data. Leave it blank in production.

Getting started

Set up a connection with your Meta credentials, create a forwarder, then validate that events arrive before you switch to live data.

Configure the destination

To create the connection and forwarder, follow the steps in Creating forwarders.

When configuring the connection, select Meta Conversions API for the connection type and enter your Pixel ID and access token. Add a test event code if you want to route events to Test events while you validate the setup.

Validate the integration

You can confirm events are reaching Meta using Events Manager:

  1. In Events Manager, open your dataset and select the Test events tab
  2. Send events with a test event code configured on the connection
  3. Confirm the events appear, and review the event details and match quality that Meta reports

Once you've validated the setup, remove the test event code so events flow to your live data.

Mapping events to Meta

The default mapping produces a standard Conversions API payload. The sections below explain how Snowplow populates user identifiers, event names, and custom data, and what you can change. See the schema reference at the end of this page for every field and its default expression.

User matching

Meta matches each event to a person using the identifiers in the user_data object. Every event must include at least one identifier, and Meta uses more identifiers to improve match quality. Personally identifiable fields such as email (em), phone (ph), and name (fn, ln) must be SHA256-hashed after normalization, so you supply the hash in your mapping expression. The client_ip_address, client_user_agent, fbc, and fbp fields must not be hashed.

The default mapping sets external_id to the Snowplow user_id. It derives the Meta click ID (fbc) and browser ID (fbp) from the _fbc and _fbp cookies. For these defaults to work, configure the cookie extractor enrichment to capture _fbc and _fbp, and the campaign attribution enrichment to capture fbclid as a fallback source for fbc.

IP anonymization breaks forwarding to Meta

If the IP anonymization enrichment is enabled, client_ip_address contains a truncated IP address. Meta treats a truncated IP as invalid and rejects the request, so the event is not forwarded. Do not enable IP anonymization on events you forward to Meta.

Event names

Meta expects a standard event name (such as Purchase, AddToCart, or ViewContent) or a custom event name in the event_name field. The default mapping maps a Snowplow ecommerce transaction to Purchase and page_view to ViewContent, and passes any other event name through unchanged. To map your own events to Meta standard events, edit the toMetaEventName function in the forwarder's custom functions.

Custom properties

You can send business data beyond the standard fields defined in the schema reference below. Event value, currency, order details, and product information are nested under the custom_data object (e.g., custom_data.value, custom_data.content_ids). Never place raw personal data in custom_data — customer identifiers belong in the hashed user_data fields.

See Meta's Conversions API parameters for details on supported fields and hashing requirements. See Creating forwarders for details on configuring field mappings.

Limitations

Keep the following constraints in mind when forwarding to Meta.

Event freshness

Meta rejects the entire request if any event's event_time is more than seven days in the past. Avoid forwarding events from a source that can replay or delay events beyond this window.

Batching

Snowplow sends one event per request to the Conversions API, so the API rate limit also functions as the event rate limit.

Schema reference

This section contains information on the fields you can send to Meta, including field names, data types, required fields, and default Snowplow mapping expressions.

FieldDetails
event_name
string

Required. A Meta standard event name (Purchase, AddToCart, PageView, ...) or a custom event name.

Default mapping: toMetaEventName(event)
event_time
integer

Required. Unix timestamp in seconds (GMT) when the event occurred. Must be no more than 7 days in the past; a single older event causes Meta to reject the entire request.

Default mapping: spTstampToEpochSecs(event.derived_tstamp)
action_source
string

Required. Where the conversion occurred. When 'website', event_source_url and user_data.client_user_agent are required. Must be one of: email, website, app, phone_call, chat, physical_store, system_generated, business_messaging, other

Default mapping: 'website'
user_data
object

Required. Customer information for matching. At least one identifier is required. PII fields must be SHA256-hashed after normalization.

Properties:
  • client_ip_address (string, required): The user's IPv4/IPv6 address. Do not hash. If the Snowplow IP anonymization enrichment is enabled, this field will contain a truncated IP, which Meta rejects as invalid, causing the request to fail. Do not enable IP anonymization on events forwarded to Meta.
    Default mapping: event.user_ipaddress
  • client_user_agent (string, required): The user's browser user agent. Do not hash. Required for website events.
    Default mapping: event.useragent
  • external_id (string, optional): Any unique advertiser user ID. Defaults to the raw Snowplow user_id. Meta recommends SHA256 hashing and also accepts raw values; if you hash, the format must be consistent with what you send on other channels. To hash, wrap the value yourself, e.g. hash(event.user_id, 'sha256'). To use a fallback identifier, coalesce: event.user_id || event.domain_userid.
    Default mapping: event.user_id
  • em (string, optional): Email, SHA256-hashed after trimming whitespace and lowercasing. No canonical Snowplow source; map from your own entity, e.g. hash(myEmail.trim().toLowerCase(), 'sha256').
  • ph (string, optional): Phone, SHA256-hashed after normalizing to digits only with country code, no leading zeros or symbols.
  • fn (string, optional): First name, SHA256-hashed after lowercasing, punctuation removed (UTF-8 for special characters).
  • ln (string, optional): Last name, SHA256-hashed, same normalization as fn.
  • ge (string, optional): Gender as single lowercase initial ('f'/'m'), SHA256-hashed.
  • db (string, optional): Date of birth as YYYYMMDD, SHA256-hashed.
  • ct (string, optional): City, lowercase with no punctuation or spaces, SHA256-hashed.
  • st (string, optional): State as 2-character lowercase ANSI code (US), SHA256-hashed.
  • zp (string, optional): Zip/postcode, lowercase, no spaces or dashes, first 5 digits for US, SHA256-hashed.
  • country (string, optional): Country as lowercase ISO 3166-1 alpha-2 code, SHA256-hashed.
  • fbc (string, optional): Meta click ID (format fb.1.{ms_timestamp}.{fbclid}). Do not hash. Default reads the _fbc cookie via the cookie extractor enrichment, falling back to deriving from fbclid via the campaign attribution enrichment. For the default to work, configure _fbc in the cookie extractor enrichment and fbclid in the campaign attribution enrichment.
    Default mapping: deriveFbc(event, event.mkt_network, event.mkt_clickid, event.derived_tstamp)
  • fbp (string, optional): Meta browser ID from the _fbp cookie. Do not hash. Default reads the _fbp cookie via the cookie extractor enrichment. For the default to work, configure _fbp in the cookie extractor enrichment.
    Default mapping: deriveFbp(event)
  • subscription_id (string, optional): Subscription ID for this user. Do not hash.
  • lead_id (integer, optional): Lead ID from Meta Lead Ads. Integer - do not string-coerce. Do not hash.
  • fb_login_id (integer, optional): App-scoped Facebook Login ID. Integer - do not string-coerce. Do not hash.
event_id
string

Optional. Advertiser-chosen ID used with event_name to deduplicate against browser Pixel events (48-hour window). Must equal the Pixel's eventID for dedup to occur.

Default mapping: event.event_id
event_source_url
string

Optional. The browser URL where the event happened. Required for website events.

Default mapping: event.page_url
opt_out
boolean

Optional. If true, the event is used for attribution only, not ads optimization.

referrer_url
string

Optional. HTTP referrer of the event page.

Default mapping: event.page_referrer
data_processing_options
array of string

Optional. Set to ['LDU'] to enable Limited Data Use for US privacy compliance; [] to disable.

data_processing_options_country
integer

Optional. 1 = US, 0 = let Meta geolocate. Required when LDU is set.

data_processing_options_state
integer

Optional. e.g. 1000 = California, 0 = geolocate. Required when LDU is set and no client_ip_address is provided.

custom_data
object

Optional. Additional business data. Must never carry raw PII - identifiers belong in (hashed) user_data.

Properties:
  • value (number, optional): Monetary value of the event. Required (with currency) for Purchase events.
    Default mapping: allContexts(event, 'com_snowplowanalytics_snowplow_ecommerce_transaction')[0]?.revenue
  • currency (string, optional): ISO 4217 currency code. Required with value for Purchase events.
    Default mapping: allContexts(event, 'com_snowplowanalytics_snowplow_ecommerce_transaction')[0]?.currency
  • order_id (string, optional): Order ID for the transaction.
    Default mapping: allContexts(event, 'com_snowplowanalytics_snowplow_ecommerce_transaction')[0]?.transaction_id
  • content_ids (array of string, optional): Product IDs associated with the event.
  • content_type (string, optional): Either 'product' or 'product_group', matching how content_ids are keyed in your catalog.
  • content_name (string, optional): Name of the page or product.
  • content_category (string, optional): Category of the page or product.
  • contents (array of object, optional): Per-item detail. Each entry requires an id; delivery_category must be one of in_store, curbside, home_delivery.
  • num_items (integer, optional): Number of items in a checkout/purchase.
  • search_string (string, optional): Search query string for Search events.