Pinterest Ads Data Layer Setup | OpsBlu Docs

Pinterest Ads Data Layer Setup

How data is structured and prepared before Pinterest Tag and Conversions API receive events.

Required Fields

  • Persist event-specific parameters: product_id, product_name, product_category, product_price, product_quantity, currency, value for e-commerce events.
  • Include user matching data (hashed email, phone, external_id) for improved Enhanced Match coverage.
  • Capture _epik (Pinterest click ID cookie) from the browser to pass to Conversions API.
  • Normalize e-commerce objects: currency (ISO 4217 code), value (decimal), product_quantity (integer), and order_id.
  • Attach campaign attribution data (utm_source, utm_medium, utm_campaign, epik parameter) for proper ad performance tracking.
  • Include event_id and event_time for deduplication between tag and Conversions API events.

Data Layer Structure for GTM

Use a standard dataLayer push format to trigger Pinterest Tag events in Google Tag Manager:

dataLayer.push({
  'event': 'pinterest_checkout',
  'ecommerce': {
    'currency': 'USD',
    'value': 79.99,
    'order_id': 'ORDER_12345',
    'items': [
      {
        'item_id': 'SKU_12345',
        'item_name': 'Organic Cotton T-Shirt',
        'item_category': 'Apparel/Shirts',
        'quantity': 2,
        'price': 39.99
      }
    ]
  },
  'user_data': {
    'email_hash': 'hashed_email_sha256',
    'phone_hash': 'hashed_phone_sha256',
    'external_id': 'user_12345'
  }
});

Map dataLayer variables to Pinterest Tag event parameters in GTM:

  • ecommerce.currency → currency
  • ecommerce.value → value
  • ecommerce.order_id → order_id and event_id
  • ecommerce.items[].item_id → product_id (for single product) or product_ids (for multiple)
  • ecommerce.items[].item_name → product_name
  • ecommerce.items[].item_category → product_category
  • ecommerce.items[].quantity → product_quantity
  • ecommerce.items[].price → product_price
  • user_data.email_hash → em (Enhanced Match, array format)
  • user_data.phone_hash → ph (Enhanced Match, array format)

User Data Hashing

Hash personally identifiable information (PII) before adding to the dataLayer or sending to Conversions API. Use SHA-256 hashing and normalize data before hashing:

  • Email: Lowercase, trim whitespace, hash with SHA-256.
  • Phone: Remove spaces, dashes, parentheses; use E.164 format (+1234567890); hash with SHA-256.
  • Name fields: Lowercase, remove special characters, trim whitespace, hash with SHA-256.
  • Geographic fields: Lowercase, use standard 2-letter codes for state/country, hash with SHA-256.

Example hashing function (JavaScript):

async function hashSHA256(value) {
  const normalized = value.toLowerCase().trim();
  const encoder = new TextEncoder();
  const data = encoder.encode(normalized);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Pinterest requires Enhanced Match in array format
async function prepareEnhancedMatch(email, phone) {
  return {
    em: [await hashSHA256(email)],
    ph: [await hashSHA256(phone)]
  };
}

Conversions API Server-Side Data

When sending events from your server to Conversions API, structure the payload to include:

  • event_name: Standard or custom event name (e.g., "checkout", "signup", "lead").
  • event_time: Unix timestamp in seconds when the event occurred.
  • event_id: Unique identifier matching the tag event for deduplication.
  • event_source_url: Full URL where the event occurred.
  • action_source: "web", "app_ios", "app_android", "offline", etc.
  • user_data: Object containing hashed user information and browser data.
    • em, ph, ge, db, ln, fn, ct, st, zp, country (all hashed, array format)
    • client_ip_address, client_user_agent (not hashed, string format)
    • click_id (_epik cookie value, not hashed, string format)
    • partner_id (optional, for agencies)
  • custom_data: Event-specific parameters (currency, value, product_id, order_id, etc.).

Example Conversions API payload:

{
  "data": [
    {
      "event_name": "checkout",
      "action_source": "web",
      "event_time": 1640000000,
      "event_id": "order_12345",
      "event_source_url": "https://example.com/checkout",
      "user_data": {
        "em": ["a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"],
        "ph": ["+12125551234"],
        "client_ip_address": "192.0.2.1",
        "client_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
        "click_id": "epik.dj0yJnU9cEFxOTdBMGNlRnBSMHRBQWF5"
      },
      "custom_data": {
        "currency": "USD",
        "value": "79.99",
        "order_id": "order_12345",
        "order_quantity": 2,
        "product_ids": ["SKU_12345", "SKU_67890"]
      }
    }
  ]
}

Pinterest Click ID (_epik) Handling

Pinterest uses the _epik cookie to track ad clicks and improve attribution. When implementing Conversions API:

  1. Client-Side: Pinterest Tag automatically sets the _epik cookie when users click Pinterest ads.
  2. Server-Side: Read the _epik cookie value from the user's browser and pass it in the click_id field of your Conversions API payload.
  3. Cookie Lifetime: The _epik cookie has a 30-day lifetime and should be included in all server-side events for proper attribution.

Example of reading _epik cookie (JavaScript):

function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}

const epikValue = getCookie('_epik');
// Send epikValue to your server for inclusion in Conversions API calls

Governance Notes

  • Document how consent modifies the dataLayer structure (e.g., do not send hashed PII if user rejects marketing cookies).
  • Version the dataLayer schema to keep GTM variables, tag events, and API payloads aligned after code releases.
  • Maintain a mapping document between your internal dataLayer and Pinterest's required parameters.
  • Establish data retention policies for event_id and event_time to support deduplication lookups.
  • Store _epik cookie values securely when passing from client to server for API calls.

Validation Steps

  • Check Pinterest Tag Helper to confirm parameters are populated correctly for each event.
  • Review Ads Manager Event History for both tag and API events to verify parameter completeness and accuracy.
  • Validate Enhanced Match coverage percentage by checking Ads Manager diagnostics.
  • Use GTM Preview mode to inspect dataLayer contents before and after event triggers.
  • Screenshot dataLayer snapshots and Event History payloads for compliance and audit documentation.
  • Test hashing functions with known inputs to confirm SHA-256 output matches expected values.
  • Verify _epik cookie is being captured and sent correctly in Conversions API payloads.
  • Confirm all Enhanced Match fields are sent as arrays, even for single values.