Data layer contract
The full data-layer contract, event catalogue, and GTM variable/trigger reference.
Data layer contract
This project uses a Shopify Custom Web Pixel to load Google Tag Manager and forward customer events into dataLayer.
Pixel source: web-pixel.js
GTM container: GTM-T7Z4P3GQ
The contents of web-pixel.js should be pasted into Shopify admin:
Settings > Customer events > Add custom pixel
DataLayer Contract
Every tracked event is pushed with the same top-level object shape:
{
event: 'cbp_link_click',
event_source: 'shopify_web_pixel',
event_group: 'cbp_custom',
source_event_name: 'cbp:link_click',
event_id: '123',
client_id: '2cabc5d8-e728-4359-9173-4b31265cbac0',
event_timestamp: '2026-05-25T01:23:45.000Z',
page: {
url: 'https://example.com/products/example-product',
referrer: 'https://example.com/',
title: 'Example Product'
},
page_location: 'https://example.com/products/example-product',
page_referrer: 'https://example.com/',
page_title: 'Example Product',
search_term: 'brake pads',
currency: 'AUD',
value: 249,
transaction_id: '1234',
items: [
{
item_id: 'SKU-123',
item_name: 'Example Product',
item_brand: 'Example Brand',
item_variant: 'DIN65LH',
price: 249,
quantity: 1
}
],
event_data: {}
}Top-Level Fields
| Field | Type | Description |
|---|---|---|
event | string | GTM custom event name. This is normalized from the Shopify event name by replacing non-alphanumeric characters with underscores. |
event_source | string | Always shopify_web_pixel. |
event_group | string | cbp_custom for cbp:* events, otherwise shopify_standard. |
source_event_name | string | Original Shopify event name before GTM normalization. |
event_id | string | Shopify Web Pixel event ID when available. |
client_id | string | Shopify Web Pixel client ID when available. |
event_timestamp | string | Shopify event timestamp when available, otherwise an ISO timestamp generated by the pixel. |
page | object | Current page context from the Shopify Web Pixel event. |
event_data | object | Event-specific payload. |
Standard Fields
buildDataLayerEvent() keeps the raw payload in event_data, then tries to promote recognizable values into standard analytics fields at the top level.
| Field | Type | Source examples |
|---|---|---|
page_location | string | event.context.document.location.href |
page_referrer | string | event.context.document.referrer |
page_title | string | event.context.document.title |
search_term | string | event_data.search_term, event_data.query, Shopify search result query |
link_text | string | event_data.label, event_data.link_text |
content_type | string | event_data.lead_type, event_data.drawer_id, event_data.filter_type, event_data.tab_value |
content_id | string | event_data.orderId, event_data.variantId, event_data.sku, event_data.drawer_id, event_data.section_id |
method | string | event_data.source, event_data.tab |
currency | string | event_data.currency, Shopify product/cart/checkout currency |
value | number | event_data.value, Shopify product/cart/checkout totals |
transaction_id | string | event_data.transaction_id, event_data.orderId, Shopify checkout order ID/name/token |
items | array | Mapped from Shopify product/cart/checkout objects or item-like custom payloads |
The original payload is always available under event_data, even when fields are promoted.
Page Object
{
url: 'https://example.com/products/example-product',
referrer: 'https://example.com/',
title: 'Example Product'
}GTM Variables
Create Data Layer Variables in GTM for the fields you need. Recommended variables:
| GTM variable name | Data Layer Variable Name |
|---|---|
DLV - Event Source | event_source |
DLV - Event Group | event_group |
DLV - Source Event Name | source_event_name |
DLV - Event ID | event_id |
DLV - Client ID | client_id |
DLV - Event Timestamp | event_timestamp |
DLV - Page URL | page.url |
DLV - Page Referrer | page.referrer |
DLV - Page Title | page.title |
DLV - Page Location | page_location |
DLV - Search Term | search_term |
DLV - Link Text | link_text |
DLV - Content Type | content_type |
DLV - Content ID | content_id |
DLV - Method | method |
DLV - Currency | currency |
DLV - Value | value |
DLV - Transaction ID | transaction_id |
DLV - Items | items |
DLV - Event Data | event_data |
Create more specific variables as needed, such as event_data.query, event_data.product, event_data.cartLine, or event_data.checkout.
GTM Triggers
Use GTM Custom Event triggers. The trigger event name should match the normalized event value, not source_event_name.
Examples:
| Shopify source event | GTM custom event |
|---|---|
cbp:link_click | cbp_link_click |
cbp:generate_lead | cbp_generate_lead |
page_viewed | page_viewed |
product_viewed | product_viewed |
product_added_to_cart | product_added_to_cart |
checkout_started | checkout_started |
checkout_completed | checkout_completed |
For a broad trigger that catches all CBP custom events, use a Custom Event trigger with regex enabled:
^cbp_.+Then filter or route tags using event_group, source_event_name, or fields inside event_data.
CBP Custom Events
These events are published from theme code through Shopify.analytics.publish(...) and subscribed to by the Web Pixel.
| Shopify source event | GTM custom event | event_group | event_data shape |
|---|---|---|---|
cbp:link_click | cbp_link_click | cbp_custom | { label } |
cbp:rego_lookup_open | cbp_rego_lookup_open | cbp_custom | { source } |
cbp:rego_lookup_no_results | cbp_rego_lookup_no_results | cbp_custom | { rego, state } |
cbp:rego_lookup_abandon | cbp_rego_lookup_abandon | cbp_custom | { step, had_results } |
cbp:postcode_select | cbp_postcode_select | cbp_custom | { postcode, suburb, state, region } |
cbp:product_vehicle_check | cbp_product_vehicle_check | cbp_custom | { sku, compatible, vehicle_make, vehicle_model } |
cbp:schedule_cta_click | cbp_schedule_cta_click | cbp_custom | { sku, has_vehicle } |
cbp:installation_step_complete | cbp_installation_step_complete | cbp_custom | { step_name, step_index } |
cbp:installation_step_back | cbp_installation_step_back | cbp_custom | { step_name } |
cbp:installation_details_started | cbp_installation_details_started | cbp_custom | {} |
cbp:installation_details_field_filled | cbp_installation_details_field_filled | cbp_custom | { field_name } |
cbp:installation_date_change | cbp_installation_date_change | cbp_custom | { date } |
cbp:installation_schedule_tab_change | cbp_installation_schedule_tab_change | cbp_custom | { tab } |
cbp:installation_slot_select | cbp_installation_slot_select | cbp_custom | { date, label } |
cbp:cart_quantity_change | cbp_cart_quantity_change | cbp_custom | { variantId, delta, new_qty } |
cbp:filter_apply | cbp_filter_apply | cbp_custom | { filter_type, filter_value, result_count } |
cbp:sort_apply | cbp_sort_apply | cbp_custom | { sort_value, result_count } |
cbp:filter_clear | cbp_filter_clear | cbp_custom | {} |
cbp:tab_select | cbp_tab_select | cbp_custom | { tab_value, section_id } |
cbp:drawer_open | cbp_drawer_open | cbp_custom | { drawer_id } |
cbp:select_item | cbp_select_item | cbp_custom | { item_list_name, item_id, item_brand, item_variant, item_name, price, index, recommended } |
cbp:generate_lead | cbp_generate_lead | cbp_custom | { currency, value, lead_type, orderId } |
Example cbp:drawer_open push:
{
event: 'cbp_drawer_open',
event_source: 'shopify_web_pixel',
event_group: 'cbp_custom',
source_event_name: 'cbp:drawer_open',
page_location: 'https://car-battery.com.au/',
page_referrer: '',
page_title: 'Car Battery Pro',
content_type: 'postcode-entry',
content_id: 'postcode-entry',
event_data: {
drawer_id: 'postcode-entry'
}
}Shopify Standard Events
These events are emitted by Shopify and normalized by the Web Pixel before being pushed to GTM.
page_viewed
{
event: 'page_viewed',
event_group: 'shopify_standard',
source_event_name: 'page_viewed',
event_data: {
page: {
url: 'https://example.com/products/example-product',
referrer: 'https://example.com/',
title: 'Example Product'
}
}
}product_viewed
{
event: 'product_viewed',
event_group: 'shopify_standard',
source_event_name: 'product_viewed',
event_data: {
product: {}
}
}event_data.product is the Shopify productVariant object from the Web Pixel event.
collection_viewed
{
event: 'collection_viewed',
event_group: 'shopify_standard',
source_event_name: 'collection_viewed',
event_data: {
collection: {}
}
}search_submitted
{
event: 'search_submitted',
event_group: 'shopify_standard',
source_event_name: 'search_submitted',
event_data: {
query: 'brake pads'
}
}product_added_to_cart
{
event: 'product_added_to_cart',
event_group: 'shopify_standard',
source_event_name: 'product_added_to_cart',
event_data: {
cartLine: {}
}
}product_removed_from_cart
{
event: 'product_removed_from_cart',
event_group: 'shopify_standard',
source_event_name: 'product_removed_from_cart',
event_data: {
cartLine: {}
}
}cart_viewed
{
event: 'cart_viewed',
event_group: 'shopify_standard',
source_event_name: 'cart_viewed',
event_data: {
cart: {}
}
}checkout_started
{
event: 'checkout_started',
event_group: 'shopify_standard',
source_event_name: 'checkout_started',
event_data: {
checkout: {}
}
}checkout_completed
{
event: 'checkout_completed',
event_group: 'shopify_standard',
source_event_name: 'checkout_completed',
event_data: {
checkout: {}
}
}payment_info_submitted
{
event: 'payment_info_submitted',
event_group: 'shopify_standard',
source_event_name: 'payment_info_submitted',
event_data: {
checkout: {}
}
}Notes
- The GTM
noscriptiframe is not used in this Web Pixel setup. The Web Pixel requires JavaScript, so a no-JavaScript fallback cannot run through it. - This GTM instance runs inside Shopify's Web Pixel environment. Prefer event-based tags triggered from these
dataLayerpushes. - Do not rely on GTM DOM triggers, form listeners, or click listeners from this pixel setup.