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.
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:
- The original dataLayer call still works exactly as before (GTM/GA4 still receives it).
- pb.js intercepts the call, checks if the
eventname matches a known ecommerce event, and if so: - Translates the GA4 schema (or legacy UA schema) into the AdsPing internal event name.
- Extracts
value,currency,items[],transaction_id, and anyuser_datafields. - Forwards to all your configured destinations (Meta, TikTok, Google Ads, GA4) with proper field mappings + browser/server dedup via shared
event_id.
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 event | Maps to AdsPing | Used by |
|---|---|---|
purchase | Purchase | Meta, TikTok, Google Ads, GA4 |
add_to_cart | AddToCart | Meta, TikTok, GA4 |
view_item / view_content | ViewContent | Meta, TikTok, GA4 |
begin_checkout | InitiateCheckout | Meta, TikTok, GA4 |
generate_lead / lead | Lead | Meta, TikTok, Google Ads |
sign_up | CompleteRegistration | Meta, TikTok |
search | Search | Meta, TikTok, GA4 |
add_payment_info | AddPaymentInfo | Meta, TikTok |
add_to_wishlist | AddToWishlist | Meta, 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)
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)
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:
Purchaseevent withvalue: 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
CompletePaymentevent. - Google Ads: Conversion uploaded with
conversion_value: 129.99,currency_code: "USD",order_id: "ORD-12345"(ID dedup window: 60 days). - GA4:
purchaseevent 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:
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,
},
],
},
});ViewContent (view_item)
Fire on product detail page load. Both view_item (GA4) and view_content (Meta convention) work — pb.js accepts either.
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:
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.
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",
},
});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:
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 (
+countrycodefullnumberwith no spaces, e.g.+905321234567). - first_name / last_name — used for Meta's
fn+lnAdvanced Matching.
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:
{% 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>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):
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
- Open your site, open DevTools console.
- Paste a manual dataLayer push:
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_IDwith 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().