dataLayer integration

If your site already pushes GA4 Enhanced Ecommerce events to window.dataLayer, AdsPing forwards them to every connected destination automatically. No extra tracking code needed — just keep your existing dataLayer pushes and pb.js handles the rest.

Already using GTM or GA4 Enhanced Ecommerce? You're done — pb.js auto-detects standard dataLayer.push() calls and forwards them. Skip ahead to Testing to verify.

How auto-bridging works

When pb.js loads, it wraps window.dataLayer.push(). Every time your code (or a plugin like Shopify's GTM tag, or Klaviyo, or a custom integration) pushes an event:

  1. The original dataLayer call still works exactly as before (GTM/GA4 still receives it).
  2. pb.js intercepts the call, checks if the event name matches a known ecommerce event, and if so:
  3. Translates the GA4 schema (or legacy UA schema) into the AdsPing internal event name.
  4. Extracts value, currency, items[], transaction_id, and anyuser_data fields.
  5. Forwards to all your configured destinations (Meta, TikTok, Google Ads, GA4) with proper field mappings + browser/server dedup via shared event_id.
You don't need to add pb.js calls separately. If your dataLayer is already wired correctly for GA4 Enhanced Ecommerce, AdsPing forwards the same data. The dataLayer is canonical — your developers maintain one tracking schema, AdsPing handles all the platform-specific translations.

Supported events

pb.js recognizes both snake_case (GA4 format) and camelCase (legacy UA format). Names are case- insensitive. Anything not in this table is ignored — push a custom event via pbq() instead (see Custom events).

dataLayer eventMaps to AdsPingUsed by
purchasePurchaseMeta, TikTok, Google Ads, GA4
add_to_cartAddToCartMeta, TikTok, GA4
view_item / view_contentViewContentMeta, TikTok, GA4
begin_checkoutInitiateCheckoutMeta, TikTok, GA4
generate_lead / leadLeadMeta, TikTok, Google Ads
sign_upCompleteRegistrationMeta, TikTok
searchSearchMeta, TikTok, GA4
add_payment_infoAddPaymentInfoMeta, TikTok
add_to_wishlistAddToWishlistMeta, TikTok

Purchase

Most important event — fire on order confirmation page (or after checkout webhook for headless setups). Includes value, currency, order ID, and the items purchased.

GA4 Enhanced Ecommerce schema (recommended)

javascript
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: "purchase",
  ecommerce: {
    transaction_id: "ORD-12345",
    value: 129.99,
    currency: "USD",
    tax: 8.50,
    shipping: 5.00,
    coupon: "SUMMER10",
    items: [
      {
        item_id: "SKU-42",
        item_name: "Wireless Headphones",
        item_category: "Electronics",
        item_brand: "Acme",
        price: 99.99,
        quantity: 1,
      },
      {
        item_id: "SKU-99",
        item_name: "USB-C Cable",
        price: 15.00,
        quantity: 2,
      },
    ],
  },
});

Legacy UA Enhanced Ecommerce (also supported)

javascript
window.dataLayer.push({
  event: "purchase",
  ecommerce: {
    purchase: {
      actionField: {
        id: "ORD-12345",
        revenue: "129.99",
        currency: "USD",
      },
      products: [
        {
          id: "SKU-42",
          name: "Wireless Headphones",
          price: "99.99",
          quantity: 1,
        },
      ],
    },
  },
});

What gets sent to each destination

  • Meta CAPI: Purchase event with value: 129.99, currency: "USD", content_ids: ["SKU-42", "SKU-99"], num_items: 3, order_id: "ORD-12345".
  • TikTok Events API: Same data, mapped to TikTok's CompletePayment event.
  • Google Ads: Conversion uploaded with conversion_value: 129.99, currency_code: "USD", order_id: "ORD-12345" (ID dedup window: 60 days).
  • GA4: purchase event with the full items array passed through (Measurement Protocol forwards the structure unchanged).

AddToCart

Fire when an item is added to cart — main click on add button:

javascript
window.dataLayer.push({
  event: "add_to_cart",
  ecommerce: {
    currency: "USD",
    value: 99.99,
    items: [
      {
        item_id: "SKU-42",
        item_name: "Wireless Headphones",
        item_category: "Electronics",
        price: 99.99,
        quantity: 1,
      },
    ],
  },
});
AddToCart is the most useful mid-funnel event for retargeting audiences. Even visitors who don't purchase but added something to cart get pixel-tagged for later remarketing campaigns.

ViewContent (view_item)

Fire on product detail page load. Both view_item (GA4) and view_content (Meta convention) work — pb.js accepts either.

javascript
window.dataLayer.push({
  event: "view_item",
  ecommerce: {
    currency: "USD",
    value: 99.99,
    items: [
      {
        item_id: "SKU-42",
        item_name: "Wireless Headphones",
        item_category: "Electronics",
        price: 99.99,
      },
    ],
  },
});

InitiateCheckout (begin_checkout)

Fire when the visitor lands on the checkout page:

javascript
window.dataLayer.push({
  event: "begin_checkout",
  ecommerce: {
    currency: "USD",
    value: 129.99,
    items: [
      { item_id: "SKU-42", item_name: "Wireless Headphones", price: 99.99, quantity: 1 },
      { item_id: "SKU-99", item_name: "USB-C Cable", price: 15.00, quantity: 2 },
    ],
  },
});

Lead

Fire on form submission for lead-gen sites (consult, quote request, appointment booking). pb.js's form auto-capture also fires this automatically when a <form> is submitted, so the manual push is only needed if you want extra control over when it fires.

javascript
window.dataLayer.push({
  event: "generate_lead",
  ecommerce: {
    value: 0,            // optional: estimated lead value
    currency: "USD",
  },
  user_data: {
    email_address: "[email protected]",
    phone_number: "+15551234567",
    first_name: "Jane",
    last_name: "Doe",
  },
});
Don't double-fire Lead. If you push generate_lead manually AND your <form> is captured by pb.js's auto form-capture, both fire and platforms count two leads. Either: (a) disable auto-capture for that form by adding data-pb-no-capture attribute, or (b) skip the manual push.

User identification (email/phone)

Match quality is largely determined by user_data fields. The more you push, the better Meta/TikTok can attribute. Standard locations:

javascript
window.dataLayer.push({
  event: "purchase",
  ecommerce: { /* ... */ },
  user_data: {
    email_address: "[email protected]",   // or "email"
    phone_number: "+15551234567",        // or "phone" — E.164 format
    first_name: "Jane",                   // or "firstName"
    last_name: "Doe",                     // or "lastName"
    address: {
      city: "Istanbul",
      region: "TR",
      postal_code: "34000",
      country: "TR",
    },
  },
});
  • email_address / email — both accepted.
  • phone_number / phone — E.164 format strongly preferred (+countrycodefullnumber with no spaces, e.g. +905321234567).
  • first_name / last_name — used for Meta's fn + ln Advanced Matching.
All hashing happens client-side. Email/phone are SHA-256 hashed by pb.js before leaving the browser. Raw PII never reaches AdsPing's backend or any platform — only the hash.

Platform-specific notes

Shopify

Shopify's built-in GTM integration auto-pushesview_item and add_to_cart if you have a GTM container loaded. For purchase events on non-Shopify-Plus stores, use the order status page custom JS:

liquid
{% comment %}
  Settings → Checkout → Order status page additional scripts.
  Runs once per successful order.
{% endcomment %}
<script>
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: "purchase",
    ecommerce: {
      transaction_id: "{{ order.order_number }}",
      value: {{ checkout.total_price | times: 0.01 }},
      currency: "{{ shop.currency }}",
      items: [
        {% for line_item in checkout.line_items %}
        {
          item_id: "{{ line_item.product_id }}",
          item_name: {{ line_item.title | json }},
          price: {{ line_item.price | times: 0.01 }},
          quantity: {{ line_item.quantity }},
        }{% if forloop.last == false %},{% endif %}
        {% endfor %}
      ],
    },
    user_data: {
      email_address: {{ checkout.email | json }},
      phone_number: {{ checkout.shipping_address.phone | json }},
    },
  });
</script>
On Shopify Plus / headless: install the AdsPing Shopify app instead. It registers webhooks on order create/refund and forwards directly server-side — no checkout-page script needed.

WooCommerce

Use the "GA4 Server-Side Tracking" or "GTM4WP" plugin — both push GA4-format dataLayer events. AdsPing picks them up automatically. For manual setup, hook into woocommerce_thankyou action and emit dataLayer push from PHP.

Custom React / Next.js

Push from your client-side checkout success handler — make sure pb.js has loaded first (check window.pbq):

tsx
useEffect(() => {
  if (orderConfirmed) {
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
      event: "purchase",
      ecommerce: {
        transaction_id: order.id,
        value: order.totalCents / 100,
        currency: order.currency,
        items: order.lineItems.map(li => ({
          item_id: li.productId,
          item_name: li.title,
          price: li.priceCents / 100,
          quantity: li.quantity,
        })),
      },
      user_data: {
        email_address: order.email,
        phone_number: order.phone,
      },
    });
  }
}, [orderConfirmed, order]);

Testing dataLayer events

In-browser quick test

  1. Open your site, open DevTools console.
  2. Paste a manual dataLayer push:
javascript
window.dataLayer.push({
  event: "purchase",
  ecommerce: {
    transaction_id: "TEST-001",
    value: 99.99,
    currency: "USD",
    items: [{ item_id: "SKU-42", item_name: "Test product", price: 99.99, quantity: 1 }],
  },
});
  • DevTools → Network tab → look for a POST to /api/v1/t/PIXEL_ID with status 200.
  • Inspect the request body — should contain "eventName": "Purchase", "value": 99.99, etc.

Verify in platform Test Events

Set a Test Event Code on the relevant pipeline (Meta or TikTok), push the event from console, and watch it appear in Meta's Test Events tab or TikTok's Test Events tab within seconds. See Test Event Code →

Debug logging

Enable pb.js debug mode by adding ?pb_debug=1 to your site URL or running localStorage.setItem("pb_debug", "1") in console. Then refresh — pb.js logs every captured dataLayer event to the console with the translated AdsPing payload right before posting.

Next

  • Standard event names — full list of events AdsPing recognizes + which destinations use which.
  • Custom events — when dataLayer doesn't fit, push directly via pbq().