e-commerce event spec

The TracerKit data layer

A standardized, typed event schema. Push events onto window.tracerkitLayer and TracerKit consumes them for purchase and custom triggers, verification, and server-side forwarding to ad platforms. One implementation, every destination.

The contract
A plain array with GTM-dataLayer-compatible push semantics.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
</script>
  • window.tracerkitLayer is a plain array with GTM-dataLayer-compatible push semantics. Initialize it with window.tracerkitLayer = window.tracerkitLayer || [] — order relative to the TracerKit snippet doesn't matter: pushes made before the loader boots are drained on boot; later pushes are processed as they happen.
  • Push events at the moment they happen, on the page where they happen. In SPAs, push after the route settles.
  • Numbers are JSON numbers. "129.97", "$129.97", and "1.299,97" are all invalid — value and price are decimals, quantity is an integer.
  • currency is an uppercase ISO 4217 code and is required whenever value is present.
  • Push purchase exactly once per order. TracerKit dedupes on order_id, but ad platforms are less forgiving — don't re-push on confirmation-page reloads.
  • Unknown extra fields are ignored, so you can share one push with an existing GTM dataLayer implementation.

The shared Item shape used by every commerce event:

type Item = {
  id: string;       // SKU or product ID — stable across events
  name: string;
  price: number;    // unit price, decimal
  quantity: number; // integer ≥ 1
};

the events

Five events, one funnel

Implement all five for a complete funnel; purchase alone is the minimum for revenue verification.

page_view
On every page load and SPA route change (after the route settles).
FieldTypeRequiredNotes
eventstringyesAlways "page_view".
page_locationstringnoFull URL. Defaults to location.href when omitted.
page_titlestringnoDefaults to document.title when omitted.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
  window.tracerkitLayer.push({
    event: "page_view"
  });
</script>
view_item
When a product detail page (or quick-view) renders.
FieldTypeRequiredNotes
eventstringyesAlways "view_item".
itemsItem[]yesThe product being viewed — usually a single item.
valuenumbernoPrice of the viewed item.
currencystringnoISO 4217 code, uppercase (USD, EUR, GBP…). Required whenever value is present.
items[].idstringyesSKU or product ID. Keep it stable across events so the funnel joins up.
items[].namestringyesHuman-readable product name.
items[].pricenumberyesUnit price as a decimal number — no currency symbols, never a string.
items[].quantitynumberyesInteger ≥ 1.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
  window.tracerkitLayer.push({
    event: "view_item",
    value: 39.99,
    currency: "USD",
    items: [{ id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 1 }]
  });
</script>
add_to_cart
When an item is added to the cart (not when the cart page opens).
FieldTypeRequiredNotes
eventstringyesAlways "add_to_cart".
itemsItem[]yesThe items just added; quantity is the amount added, not the cart total.
valuenumbernoValue of the items added (price × quantity).
currencystringnoISO 4217 code, uppercase (USD, EUR, GBP…). Required whenever value is present.
items[].idstringyesSKU or product ID. Keep it stable across events so the funnel joins up.
items[].namestringyesHuman-readable product name.
items[].pricenumberyesUnit price as a decimal number — no currency symbols, never a string.
items[].quantitynumberyesInteger ≥ 1.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
  window.tracerkitLayer.push({
    event: "add_to_cart",
    value: 79.98,
    currency: "USD",
    items: [{ id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 2 }]
  });
</script>
begin_checkout
When the customer enters checkout (first checkout step renders).
FieldTypeRequiredNotes
eventstringyesAlways "begin_checkout".
itemsItem[]yesThe full cart at checkout start.
valuenumbernoCart total at checkout start.
currencystringnoISO 4217 code, uppercase (USD, EUR, GBP…). Required whenever value is present.
items[].idstringyesSKU or product ID. Keep it stable across events so the funnel joins up.
items[].namestringyesHuman-readable product name.
items[].pricenumberyesUnit price as a decimal number — no currency symbols, never a string.
items[].quantitynumberyesInteger ≥ 1.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
  window.tracerkitLayer.push({
    event: "begin_checkout",
    value: 129.97,
    currency: "USD",
    items: [
      { id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 2 },
      { id: "SKU-456", name: "Wool Beanie", price: 49.99, quantity: 1 }
    ]
  });
</script>
purchase
Exactly once per order, on the order-confirmation page.
FieldTypeRequiredNotes
eventstringyesAlways "purchase".
order_idstringyesUnique per order — the dedup key. Never reuse across orders.
valuenumberyesOrder total as a decimal number — never a string, no symbols or separators.
currencystringyesISO 4217 code, uppercase (USD, EUR, GBP…).
itemsItem[]yesEvery line item in the order.
items[].idstringyesSKU or product ID. Keep it stable across events so the funnel joins up.
items[].namestringyesHuman-readable product name.
items[].pricenumberyesUnit price as a decimal number — no currency symbols, never a string.
items[].quantitynumberyesInteger ≥ 1.
emailstringnoOPTIONAL — enhanced matching only. Hashed in-browser (SHA-256) before use; the raw address never leaves the page.
phonestringnoOPTIONAL — enhanced matching only. E.164 format recommended (+15551234567). Hashed in-browser (SHA-256) before use.
<script>
  window.tracerkitLayer = window.tracerkitLayer || [];
  window.tracerkitLayer.push({
    event: "purchase",
    order_id: "1001",
    value: 129.97,
    currency: "USD",
    items: [
      { id: "SKU-123", name: "Canvas Tote", price: 39.99, quantity: 2 },
      { id: "SKU-456", name: "Wool Beanie", price: 49.99, quantity: 1 }
    ],
    email: "jane@example.com",  // optional — hashed in-browser
    phone: "+15551234567"       // optional — hashed in-browser
  });
</script>
Enhanced matching (email & phone)

email and phone on purchaseare optional. When provided they are consumed for enhanced matching only: hashed in-browser with SHA-256 before any transmission — the raw values never leave the page and never transit TracerKit's servers.

Provide them only under a consent state that permits marketing use.

Mapping to platforms
Once TracerKit forwards events server-side, the schema maps 1:1 onto each platform's conversion API — this is why one data layer implementation is enough.

Event names

TracerKit eventMeta CAPIGA4TikTok
page_viewPageViewpage_viewPageview
view_itemViewContentview_itemViewContent
add_to_cartAddToCartadd_to_cartAddToCart
begin_checkoutInitiateCheckoutbegin_checkoutInitiateCheckout
purchasePurchasepurchaseCompletePayment

Fields (purchase)

TracerKit fieldMeta CAPIGA4TikTok
valuecustom_data.valueparams.valueproperties.value
currencycustom_data.currencyparams.currencyproperties.currency
order_idcustom_data.order_id (dedup basis)params.transaction_idproperties.order_id
items[].idcustom_data.contents[].iditems[].item_idproperties.contents[].content_id
items[].namecustom_data.content_nameitems[].item_nameproperties.contents[].content_name
items[].pricecustom_data.contents[].item_priceitems[].priceproperties.contents[].price
items[].quantitycustom_data.contents[].quantityitems[].quantityproperties.contents[].quantity
email (hashed)user_data.emuser_data.sha256_email_addressuser.email
phone (hashed)user_data.phuser_data.sha256_phone_numberuser.phone

Prefer typed calls over hand-written pushes? The JS/React SDK (@tracerkit/js, @tracerkit/react) wraps this spec field-for-field — pushEvent, pushPurchase, identify, consent, with autocomplete.

Agents can read this spec as markdown at /docs/data-layer.md. The data layer is consumed by the TracerKit loader — install it first.