Meta’s Conversions API accepts structured event data, but the field names and formats differ from GA4’s event parameters. When you send a GA4 purchase event to Meta via CAPI, you need to translate GA4’s schema into Meta’s required format. Incorrect mapping results in low Event Match Quality (EMQ) scores, poor attribution, and wasted ad spend. This guide covers exact field mappings, required vs optional fields, and common mistakes. Learn more in our guide on TikTok Pixel Matching Quality.

Meta Conversions API GA4 Purchase Events: Field Mapping Requirements for Maximum Match Quality

Understanding Meta’s Event Match Quality (EMQ)

EMQ measures how accurately Meta can match your conversion events to Meta accounts. A higher score means better attribution, lower cost per acquisition, and more accurate audience building for remarketing. EMQ is scored 0-10 based on the quality and quantity of customer information fields you provide. Learn more in our guide on GA4 Consent Mode v2.

EMQ fields in priority order:

  • Email (em): Highest weight. Hashed SHA256 email address
  • Phone (ph): High weight. Hashed SHA256 phone in E.164 format
  • Name (fn, ln): Medium weight. Hashed first and last name
  • Country (country): Medium weight. 2-letter country code, hashed
  • External ID (external_id): Medium weight. Your internal user/customer ID, hashed
  • City/State/Zip (ct, st, zp): Lower weight. Hashed location data
  • Browser ID (fbp), Click ID (fbc): Pixel-based identifiers, not hashed

To score 8+ EMQ, you need at minimum: email or phone, plus external_id or fbp/fbc. Sending only fbp without email or phone typically gives EMQ 3-5.

GA4 Purchase Event Fields vs Meta CAPI Required Fields

GA4’s standard purchase event includes these parameters:

  • transaction_id
  • value (purchase value)
  • currency
  • items (array of item objects)
  • coupon
  • affiliation

Meta CAPI’s Purchase event requires:

  • event_name: “Purchase”
  • event_time: Unix timestamp
  • event_source_url: The page URL where the purchase occurred
  • user_data: Object containing em, ph, fbp, fbc, external_id, etc.
  • custom_data: Object containing value, currency, content_ids, content_type, num_items

Notice the structural difference: GA4 flattens parameters (value, currency) while Meta nests them under custom_data. GA4 doesn’t have a user_data structure — you need to populate this from your backend or CRM.

Complete Field Mapping: GA4 to Meta CAPI

// GA4 purchase event (client-side)
window.dataLayer.push({
  event: 'purchase',
  transaction_id: 'T12345',
  value: 99.99,
  currency: 'USD',
  items: [{ item_id: 'SKU123', item_name: 'Product A', price: 99.99, quantity: 1 }]
});

// Meta CAPI equivalent (server-side)
const metaPayload = {
  data: [{
    event_name: 'Purchase',
    event_time: Math.floor(Date.now() / 1000), // Unix timestamp
    event_source_url: 'https://yoursite.com/thank-you',
    action_source: 'website',
    user_data: {
      em: hashSHA256(userEmail.toLowerCase().trim()),
      ph: hashSHA256(userPhone.replace(/[^0-9]/g, '')), // E.164 format
      fn: hashSHA256(firstName.toLowerCase().trim()),
      ln: hashSHA256(lastName.toLowerCase().trim()),
      external_id: hashSHA256(userId.toString()),
      fbp: getCookie('_fbp'),  // Facebook pixel browser ID (NOT hashed)
      fbc: getCookie('_fbc'),  // Facebook click ID (NOT hashed)
      client_ip_address: request.ip,  // NOT hashed
      client_user_agent: request.headers['user-agent']  // NOT hashed
    },
    custom_data: {
      value: 99.99,  // maps from GA4's 'value'
      currency: 'USD',  // maps from GA4's 'currency'
      content_ids: ['SKU123'],  // maps from GA4 items[].item_id
      content_type: 'product',
      num_items: 1,  // maps from GA4 items length or quantity
      order_id: 'T12345'  // maps from GA4's transaction_id
    }
  }]
};

Hashing Requirements: What to Hash vs Not Hash

Meta requires specific fields to be hashed with SHA256 before sending:

Meta Conversions API GA4 Purchase Events: Field Mapping Requirements for Maximum Match Quality implementation guide
  • Must hash: em, ph, fn, ln, ct, st, zp, country, external_id, ge (gender), db (date of birth)
  • Must NOT hash: fbp, fbc, client_ip_address, client_user_agent

Hashing rules:

  • Email: lowercase, trim whitespace, then SHA256
  • Phone: remove all non-numeric characters, include country code (e.g., 14155551234), then SHA256
  • Name: lowercase, trim whitespace, then SHA256
  • External ID: convert to string, then SHA256
  • City: lowercase, remove spaces, then SHA256

Server-side GTM handles hashing automatically if you use Meta’s CAPI tag and configure it correctly. If building a custom integration, implement SHA256 hashing in your server code.

Capturing fbp and fbc Cookies Server-Side

The _fbp cookie is set by Meta’s pixel on the client side. The _fbc cookie is set when a user clicks a Meta ad (contains the fbclid parameter). Both are critical for matching but tricky to capture server-side:

  • Read _fbp from the HTTP request cookies header on your server
  • Read _fbc from request cookies, or extract from the fbclid URL parameter and build it: fbc=fb.1.{timestamp}.{fbclid}
  • Pass both to your server-side GTM data layer or CAPI payload
  • If _fbp is missing (ad blockers, iOS 14+ restrictions), fall back to your external_id

Deduplication: Preventing Double-Counting from Pixel + CAPI

If you’re running both Meta Pixel (client-side) and CAPI (server-side), Meta requires deduplication to prevent counting the same purchase twice. Use the event_id field:

// Client-side pixel event
fbq('track', 'Purchase', {
  value: 99.99,
  currency: 'USD'
}, {
  eventID: 'purchase_T12345'  // Unique identifier for this specific event
});

// Server-side CAPI event
const metaPayload = {
  data: [{
    event_name: 'Purchase',
    event_id: 'purchase_T12345',  // Same ID as pixel event
    // ... rest of payload
  }]
};

Meta uses the event_id to identify duplicates. When it receives the same event_id from both pixel and CAPI within 48 hours, it counts the conversion once. Use transaction_id or order_id as the basis for event_id to ensure uniqueness.

Testing Your Field Mapping with Meta’s Events Manager

After implementing, validate in Meta Events Manager:

  • Go to Events Manager and select your Pixel
  • Click “Test Events” tab to send test events and see how they appear
  • Check EMQ score shown for each event
  • Review which user_data fields were received and matched
  • Use the Payload Helper tool to validate your JSON payload format before sending live

Aim for EMQ 7+ before going live. Below 7, attribution quality degrades significantly and your audience building suffers. Proper field mapping from the start prevents weeks of troubleshooting poor ROAS numbers later.

Leave a Comment