Frontend dataLayer

A neutral, versioned in-browser contract for partner web tracking

Alongside the REST API, every Eshop-rychle store publishes a neutral frontend dataLayer — structured data and events available directly in the visitor's browser. You connect a small JavaScript loader (deployed as a measuring code through the API), read the data and map it to your own tracking format. It covers visitor activity, cart contents, customer identification and completed orders. The data lives in its own global, window.eshopDataLayer, so the contract stays stable and is versioned through the version field.

How it works

  1. On every page the store renders a snapshot of the current state into window.eshopDataLayer.eshop and fires the EshopDataLayerUpdated event on document.
  2. State changes (cart add / remove / update, consent change, order completion) are pushed as events onto the window.eshopDataLayer array and the snapshot is refreshed.
  3. Your loader reads the snapshot, subscribes to the events and forwards whatever it needs to your own endpoint. The platform ships no per-partner code — you own the mapping.

Getting started

  • Register the store connection through the API and deploy your loader as a measuring code. It is injected into every page automatically and removed when your add-on is deactivated.
  • Partner measuring codes are always present regardless of the store's cookie-bar settings — so respecting consent is your responsibility (see Consent & self-gating).
  • Everything you need is client-side; no server callbacks are required to read the dataLayer.

Accessing the data

  • Current page snapshot: window.eshopDataLayer.eshop
  • Helper: window.getEshopDataLayer(key) (or without an argument for the whole snapshot)
  • Ready signal: the EshopDataLayerUpdated event on document (e.detail is the snapshot)

Events

Events are published as entries in the window.eshopDataLayer array. An event is only a signal — read the details from the snapshot. Some events (pageVisit, loggedUser, categoryView, productView, orderSubmitted, the initial cookieConsent) are queued at page load, before your loader runs, so iterate the existing array first and then wrap push to catch later ones — the loader skeleton below does both.

EventWhenPayload
cookieConsentInitial load and on every consent change{ event, cookieConsent: { marketing, analytics } }
pageVisitEvery page load{ event, pageType }
loggedUserPage load for a signed-in customer{ event, customer }
categoryViewCategory / listing page load{ event, category }
productViewProduct detail page load{ event, product }
cartUpdatedItem added / removed / quantity changed{ event, action: 'add' | 'remove' | 'update', cart, product }
orderSubmittedThank-you page (completed order){ event, order }

Snapshot schema

Fields marked PII are present only with granted consent (see below). The order block is present on the thank-you page only, category on category pages and product on product detail pages.

Note on types: prices, totals, orderNumber and all product ids are strings; orderId and quantities are numbers.

window.eshopDataLayer.eshop = { version: "1.0", pageType: "homepage" | "category" | "productDetail" | "cart" | "checkout" | "thankYou", currency: "CZK", // ISO currency code language: "cs", // cs | sk cart: { items: [{ id, name, price /* excl. VAT */, priceWithVat, quantity, variant, category, brand }], totalWithVat, totalWithoutVat, coupon }, customer: { isLoggedIn, group, registered, city, countryCode, email*, name* }, category: { // category / listing pages only name, path: [/* breadcrumb category names */], products: [{ id, name, price /* excl. VAT */, position }] }, product: { // product detail pages only id, name, price /* excl. VAT */, priceWithVat, currency, availability: "InStock" | "BackOrder" | "OutOfStock", description, brand, imageUrl, category, variant }, order: { // thankYou only orderId, orderNumber, priceWithVat, priceWithoutVat, tax, shipping, coupon, currency, items: [{ id, name, price /* excl. VAT */, quantity, category, brand }], customer: { group, registered, city, countryCode, email*, name*, street*, zip* } }, cookieConsent: { marketing: "granted" | "denied", analytics: "granted" | "denied" } } // * PII — present in the snapshot only with granted marketing/analytics consent

pageType values

ValuePage
homepageStore homepage
categoryCategory / product listing
productDetailProduct detail
cartCart
checkoutCheckout steps
thankYouOrder confirmation — carries the order block

Cart fields

FieldTypeDescription
items[].idstringProduct id
items[].namestringProduct name
items[].pricestringUnit price excl. VAT
items[].priceWithVatstringUnit price incl. VAT
items[].quantitynumberQuantity in the cart
items[].variantstring | nullSelected variant label
items[].categorystring | nullProduct category
items[].brandstring | nullProduct brand
totalWithVatstringCart total incl. VAT
totalWithoutVatstringCart total excl. VAT
couponstringApplied coupon code ("" if none)

Customer fields

FieldTypeDescription
isLoggedInbooleanWhether a customer is signed in
groupstring | nullCustomer pricing / loyalty group
registeredbooleanWhether the customer has an account
citystring | nullCustomer city
countryCodestring | nullISO country code
email PIIstring | nullOnly with granted consent
name PIIstring | nullOnly with granted consent

Category fields category only

FieldTypeDescription
namestring | nullViewed category name (last breadcrumb node)
pathstring[]Breadcrumb category names, root first
products[].idstringProduct id
products[].namestring | nullProduct name
products[].pricestringUnit price excl. VAT
products[].positionnumber1-based position in the listing

Product fields productDetail only

FieldTypeDescription
idstringProduct id
namestringProduct name
pricestringUnit price excl. VAT
priceWithVatstringUnit price incl. VAT
currencystringISO currency code
availabilitystringInStock | BackOrder | OutOfStock
descriptionstring | nullShort plain-text description
brandstring | nullProduct brand
imageUrlstring | nullAbsolute URL of the main product image
categorystring | nullProduct category
variantstring | nullSelected variant label

cartUpdated product field

On add and remove the cartUpdated event carries a product object for the specific item changed: { id, name, price /* excl. VAT */, quantity, variant, category, brand }. On a quantity update there is no single changed item, so product is null. The full cart is always in cart.

Order fields thankYou only

FieldTypeDescription
orderIdnumberInternal order id
orderNumberstringHuman-readable order number
priceWithVat / priceWithoutVatstringOrder total incl. / excl. VAT
taxstringVAT amount
shippingstringShipping price
couponstringApplied coupon code ("" if none)
currencystringISO currency code
items[]arrayLine items: id, name, price (excl. VAT), quantity, category, brand
customerobjectgroup, registered, city, countryCode, and PII email, name, street, zip

Loader skeleton

(function () { // 1) Current state — read the snapshot (available as soon as the page renders it). function read() { var eshop = window.getEshopDataLayer && window.getEshopDataLayer(); if (eshop) { /* map eshop.* to your format */ } } if (window.getEshopDataLayer) { read(); } else { document.addEventListener('EshopDataLayerUpdated', read, { once: true }); } // 2) Events — handle those already queued at page load, then catch every later push. window.eshopDataLayer = window.eshopDataLayer || []; function handle(entry) { if (entry && entry.event) { // entry.event: cookieConsent | pageVisit | loggedUser | categoryView | productView | cartUpdated | orderSubmitted // the entry carries its own payload; the full snapshot is at window.getEshopDataLayer() } } window.eshopDataLayer.forEach(handle); var push = window.eshopDataLayer.push; window.eshopDataLayer.push = function () { for (var i = 0; i < arguments.length; i++) { handle(arguments[i]); } return push.apply(this, arguments); }; })();

Testing your integration

Verify everything straight from the browser console on any store page:

// full current snapshot window.getEshopDataLayer(); // a single block window.getEshopDataLayer('cart'); // log every snapshot refresh document.addEventListener('EshopDataLayerUpdated', function (e) { console.log('snapshot', e.detail); }); // log every event var push = window.eshopDataLayer.push; window.eshopDataLayer.push = function () { console.log('event', arguments[0]); return push.apply(this, arguments); };

Add a product to the cart and you should see a cartUpdated event followed by a refreshed snapshot; complete an order and the thank-you page carries the order block together with an orderSubmitted event.

Versioning

eshop.version guards backward compatibility of the contract. A breaking schema change increments the major version — react to it in your loader (at least log an unknown major).