(function(){ const zoovuId = 'rjeHqUvdquWv3Nd6RMELUbJbvCLUqlTvxeeR/QTTDSs='; const domainId = '5ae48472-9b89-4299-a9c1-2d91641791ee'; const variables = [{"id":"1eec2be6-dc91-4c4e-a443-da2f051baf5b","name":"Add to cart","type":"CONSTANT","valueType":"TEXT","value":"Add to cart","scope":"GLOBAL"},{"id":"17544614-8761-4994-999e-0846fa6ef15f","name":"addToCartCategory","type":"FUNCTION","valueType":"TEXT","function":function(event){// Optional CSS.escape fallback (kept tiny) const esc = window.CSS && CSS.escape ? CSS.escape : (s) => String(s).replace(/[^a-zA-Z0-9_-]/g, "\\$&"); // Safely get last UI event target const evt = (window.__evt && window.__evt.target) || window.event?.target || null; // 1) If we can reach the card directly from the click, use it let card = evt?.closest?.(".stg-trackable-product-card") || null; // Helper: extract SKU from common data-testids near Qty/Add buttons function skuFromTestId(id) { if (!id) return ""; const m = id.match(/^product-button-(.+)-addToCart$/) || id.match(/^shop-button-(.+)-product-quantity-(?:input|increment|decrement)$/) || id.match(/^product-link-(.+)-product-card$/); return m ? m[1] : ""; } // 2) If no card yet, try to infer it by SKU found on the clicked control if (!card && evt && evt.closest) { const needle = evt.closest('[data-testid^="product-button-"][data-testid$="-addToCart"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-input"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-increment"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-decrement"]') || evt.closest('[data-testid^="product-link-"][data-testid$="-product-card"]'); const sku = skuFromTestId(needle?.getAttribute("data-testid") || ""); if (sku) { // (a) Card where data-tracking-id equals the SKU (common on SERP/suggestions) card = document.querySelector(`.stg-trackable-product-card[data-tracking-id="${esc(sku)}"]`) || card; // (b) Or locate the product-link for this SKU and climb to its card if (!card) { const link = document.querySelector(`[data-testid="product-link-${esc(sku)}-product-card"]`); card = link?.closest?.(".stg-trackable-product-card") || card; } } } // 3) Final read (prefer the more specific cat2 when present) const cat2 = card?.getAttribute("data-tracking-category2") || ""; const cat1 = card?.getAttribute("data-tracking-category") || ""; return cat2 || cat1 || ""; /* */},"scope":"LOCAL"},{"id":"c6abe1c2-0962-4813-8a13-d4f6771c890f","name":"addToCartPrice","type":"FUNCTION","valueType":"DECIMAL","function":function(event){function numberFromPrice(txt) { if (!txt) return 0; const raw = String(txt).replace(/[\u00A0\u202F\s]/g, " ").trim(); let keep = raw.replace(/[^\d.,']/g, ""); const m = keep.match(/([.,])(\d{2})$/); if (m) { const decSep = m[1]; keep = keep.replace(/[.,'](?=\d{3}(?:[^\d]|$))/g, ""); keep = keep.replace(decSep, "."); } else { keep = keep.replace(/[^\d]/g, ""); } const n = Number(keep); return Number.isFinite(n) ? n : 0; } const t = (window.__evt && window.__evt.target) || window.event?.target; // 1) PDP add-to-cart context let priceEl = document.querySelector('[data-testid="product-section-information"] [data-testid^="component-price-"][data-testid$="-current-price"]'); if (priceEl) return numberFromPrice(priceEl.textContent); // 2) Within a product card (PLP/SERP/suggestions) const card = t?.closest?.('.stg-trackable-product-card'); priceEl = card?.querySelector('label.MuiTypography-labelM span,[data-testid^="component-price-"][data-testid$="-current-price"]'); if (priceEl) return numberFromPrice(priceEl.textContent); // 3) Fallback: any visible “current price” priceEl = document.querySelector('[data-testid^="component-price-"][data-testid$="-current-price"]'); return priceEl ? numberFromPrice(priceEl.textContent) : 0; /* */},"scope":"LOCAL"},{"id":"e13c5676-bb2c-43c9-be42-938b221632b4","name":"addToCartQty","type":"FUNCTION","valueType":"INTEGER","function":function(event){ const evt = (window.__evt && window.__evt.target) || window.event?.target || null; // --- 1) If we are on PDP, use the main PDP quantity input const pdp = document.querySelector('[data-testid="product-section-information"]'); if (pdp) { const pdpInput = pdp.querySelector('[data-testid$="product-quantity-input"] input'); if (pdpInput && pdpInput.value) { const n = parseInt(pdpInput.value, 10); return Number.isFinite(n) && n > 0 ? n : 1; } } // Helper: parse SKU from a data-testid like "product-button--addToCart" function skuFromDataTestId(id) { if (!id) return ""; const m = id.match(/^product-button-(.+)-addToCart$/) || id.match(/^shop-button-(.+)-product-quantity-(?:input|increment|decrement)$/); return m ? m[1] : ""; } // --- 2) Try local context around the clicked element (PLP / SERP / suggestions) if (evt && evt.closest) { // (a) direct local input near the click const localInput = evt.closest('.stg-counter-input')?.querySelector('input') || evt.closest('[data-testid$="product-quantity-input"]')?.querySelector('input'); if (localInput && localInput.value) { const n = parseInt(localInput.value, 10); if (Number.isFinite(n) && n > 0) return n; } // (b) derive SKU from the addToCart button then address the input by SKU const addBtn = evt.closest('[data-testid^="product-button-"][data-testid$="-addToCart"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-increment"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-decrement"]') || evt.closest('[data-testid^="shop-button-"][data-testid$="product-quantity-input"]'); const sku = skuFromDataTestId(addBtn?.getAttribute('data-testid') || ""); if (sku) { const skuInput = document.querySelector( `[data-testid="shop-button-${CSS.escape(sku)}-product-quantity-input"] input` ); if (skuInput && skuInput.value) { const n = parseInt(skuInput.value, 10); if (Number.isFinite(n) && n > 0) return n; } } } // --- 3) Final fallback return 1; /* */},"scope":"LOCAL"},{"id":"9bcc6c18-d60d-4f77-b7d3-8f9d8dc4a217","name":"addToCartSku","type":"FUNCTION","valueType":"TEXT","function":function(event){const el = (window.__evt?.target) || (window.event?.target); const card = el?.closest?.(".stg-trackable-product-card"); if (card) return card.getAttribute("data-tracking-id") || ""; // PDP Add-to-cart button encodes SKU in data-testid: product-button--addToCart const dt = el?.closest?.("[data-testid]")?.getAttribute?.("data-testid") || ""; const m = dt.match(/^product-button-([^]+?)-addToCart$/); if (m) return m[1]; // PDP fallback from details const pdpRef = document.querySelector('ul.space-y-2 li:first-child label.MuiTypography-labelL'); const txt = (pdpRef?.textContent || ""); const ref = txt.match(/[\d.]+[A-Z]?/); return ref ? ref[0] : ""; /* */},"scope":"LOCAL"},{"id":"521ed7c6-7510-45cc-b206-4d9380418fee","name":"cartDeltaMinusOne","type":"CONSTANT","valueType":"INTEGER","value":"-1","scope":"LOCAL"},{"id":"dafc253c-b1ae-45db-81fd-4d274f7104aa","name":"cartDeltaPlusOne","type":"CONSTANT","valueType":"INTEGER","value":"1","scope":"LOCAL"},{"id":"2c79bdb1-b595-407b-9055-dc8afdff4c17","name":"cartSkuFromClick","type":"FUNCTION","valueType":"TEXT","function":function(event){const el = (window.__evt && window.__evt.target) || window.event?.target || document.activeElement; // Nearest list item carries the SKU in its data-testid: shop-listItem- const li = el?.closest?.('li[data-testid^="shop-listItem-"]'); if (li) { const id = li.getAttribute("data-testid") || ""; const m = id.match(/^shop-listItem-([A-Z0-9.]+)/i); if (m) return m[1]; } // Fallbacks inside the card const card = el?.closest?.('.MuiCardContent-root, [data-testid^="cart-card-"]'); // data-testid="cart-card-product-name-" const nameId = card?.querySelector?.('[data-testid^="cart-card-product-name-"]')?.getAttribute("data-testid") || ""; let m = nameId.match(/^cart-card-product-name-([A-Z0-9.]+)/i); if (m) return m[1]; // data-testid="cart-card-product-label--REF-" const refId = card?.querySelector?.('[data-testid^="cart-card-product-label-"]')?.getAttribute("data-testid") || ""; m = refId.match(/^cart-card-product-label-([A-Z0-9.]+)-REF-/i); if (m) return m[1]; // Absolute last resort: any attribute that looks like a SKU const txt = card?.textContent || ""; m = txt.match(/\b\d{3}\.\d{4}[A-Z]?\b/); return m ? m[0] : ""; /* */},"scope":"LOCAL"},{"id":"794148b9-d30c-4fa9-ab0f-d1e903691954","name":"cartUnitPriceFromCard","type":"FUNCTION","valueType":"DECIMAL","function":function(event){const t = (window.__evt && window.__evt.target) || window.event?.target || null; const card = t?.closest?.('li[data-testid^="shop-listItem-"], .MuiCardContent-root') || document.querySelector('li[data-testid^="shop-listItem-"], .MuiCardContent-root'); if (!card) return 0; // Try to read SKU to target price elements function skuFromCard(c) { const li = c.closest?.('li[data-testid^="shop-listItem-"]'); if (li) { const id = li.getAttribute("data-testid") || ""; const m = id.match(/^shop-listItem-([A-Z0-9.]+)/i); if (m) return m[1]; } const nameId = c.querySelector?.('[data-testid^="cart-card-product-name-"]')?.getAttribute("data-testid") || ""; let m = nameId.match(/^cart-card-product-name-([A-Z0-9.]+)/i); if (m) return m[1]; const refId = c.querySelector?.('[data-testid^="cart-card-product-label-"]')?.getAttribute("data-testid") || ""; m = refId.match(/^cart-card-product-label-([A-Z0-9.]+)-REF-/i); return m ? m[1] : ""; } const sku = skuFromCard(card); const baseEl = sku ? card.querySelector(`[data-testid="component-price-${CSS.escape(sku)}-base-price"]`) : null; const txt = (baseEl?.textContent || "").trim(); function readPrice(s) { const keep = (s || "").replace(/[^\d.,']/g, ""); if (!keep) return 0; const last = Math.max(keep.lastIndexOf(","), keep.lastIndexOf(".")); let ip, dp; if (last !== -1 && keep.length - last - 1 <= 2) { ip = keep.slice(0, last).replace(/[.,\s']/g, ""); dp = keep.slice(last + 1); } else { ip = keep.replace(/[.,\s']/g, ""); dp = ""; } dp = (dp + "00").slice(0, 2); const n = Number(`${ip}.${dp}`); return Number.isFinite(n) ? n : 0; } // 1) Direct unit/base price if available const unit = readPrice(txt); if (unit > 0) return unit; // 2) Compute: total price / quantity const totalTxt = card.querySelector('[data-testid^="component-price-"][data-testid$="-total-price"]')?.textContent || ""; const total = readPrice(totalTxt); // qty from input or xN label const inputVal = card.querySelector(".stg-counter-input input")?.value || ""; let qty = parseInt(inputVal, 10); if (!Number.isFinite(qty) || qty <= 0) { const qlbl = card.querySelector('[data-testid^="cart-card-product-quantity-"]')?.textContent || ""; qty = parseInt(qlbl.replace(/[^\d]/g, ""), 10); } if (total > 0 && Number.isFinite(qty) && qty > 0) { return +(total / qty).toFixed(2); } return 0; /* */},"scope":"LOCAL"},{"id":"e421893f-c0f4-435d-922d-3809963e986e","name":"categoryTargetUrl","type":"FUNCTION","valueType":"TEXT","function":function(event){const el = event.target; const closestHref = el?.closest('a'); return closestHref?.getAttribute('href'); /* */},"scope":"LOCAL"},{"id":"904c3ff0-8e69-48ca-a868-c61c5260d9e7","name":"checkoutLineItemsJson","type":"FUNCTION","valueType":"LIST","function":function(event){// Returns [{ sku, name, quantity, pricePerUnit }] function readPrice(txt) { const keep = (txt || "").replace(/[^\d.,']/g, ""); if (!keep) return 0; const last = Math.max(keep.lastIndexOf(","), keep.lastIndexOf(".")); let ip, dp; if (last !== -1 && keep.length - last - 1 <= 2) { ip = keep.slice(0, last).replace(/[.,\s']/g, ""); dp = keep.slice(last + 1); } else { ip = keep.replace(/[.,\s']/g, ""); dp = ""; } dp = (dp + "00").slice(0, 2); const n = Number(`${ip}.${dp}`); return Number.isFinite(n) ? n : 0; } function escapeSKU(s){ return window.CSS && CSS.escape ? CSS.escape(s) : String(s).replace(/[^a-zA-Z0-9_-]/g,"\\$&"); } // one card per line item (works on cart + checkout + confirmation) const cards = Array.from(document.querySelectorAll('[data-testid^="checkout-card-cart-entry-"]')); const items = cards.map(card => { // SKU from card testid const cardId = card.getAttribute("data-testid") || ""; const sku = (cardId.match(/^checkout-card-cart-entry-(.+)$/) || [, ""])[1]; // Name const name = card.querySelector(`[data-testid="cart-link-product-name-${escapeSKU(sku)}"]`)?.textContent?.trim() || ""; // Quantity: N const qtyTxt = card.querySelector(`[data-testid="checkout-typography-unit-quantity-${escapeSKU(sku)}"]`)?.textContent || ""; const qty = parseInt(qtyTxt.replace(/[^\d]/g, ""), 10); const quantity = Number.isFinite(qty) && qty > 0 ? qty : 1; // Price candidates const base = card.querySelector(`[data-testid="component-price-${escapeSKU(sku)}-base-price"]`)?.textContent || ""; const unit = card.querySelector(`[data-testid="component-price-${escapeSKU(sku)}-unit-price"]`)?.textContent || ""; const total= card.querySelector(`[data-testid="component-price-${escapeSKU(sku)}-total-price"]`)?.textContent || ""; let pricePerUnit = 0; if (base) pricePerUnit = readPrice(base); else if (unit) pricePerUnit = readPrice(unit); else if (total) { const t = readPrice(total); pricePerUnit = quantity ? +(t / quantity).toFixed(2) : 0; } return { sku, name, quantity, pricePerUnit }; }).filter(it => it && it.sku); return items; /* */},"scope":"LOCAL"},{"id":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","name":"clickDataTestId","type":"FUNCTION","valueType":"TEXT","function":function(event){const el = event.target; const withId = el?.closest?.("[data-testid]"); return withId ? withId.getAttribute("data-testid") : ""; /* */},"scope":"LOCAL"},{"id":"b73b1d5c-2232-410e-be49-48ec6609f4d7","name":"Clickout, add product from search result","type":"CONSTANT","valueType":"TEXT","value":"Clickout, add product from search result","scope":"GLOBAL"},{"id":"3b881070-bf08-4869-be93-2b5d94a99c5b","name":"Clickout, category","type":"CONSTANT","valueType":"TEXT","value":"Clickout, category","scope":"GLOBAL"},{"id":"d2d8bad9-06f7-4f78-9184-8c38a9a469a1","name":"Clickout, view all products","type":"CONSTANT","valueType":"TEXT","value":"Clickout, view all products","scope":"GLOBAL"},{"id":"50d1794c-965c-4d73-bb7e-558080b33281","name":"clickParentTestId","type":"FUNCTION","valueType":"TEXT","function":function(event){// clickParentTestId (hardened) const el = event.target; console.log(el?.parentElement); if (!el) return ""; // Prefer the popup root if we are inside it (more stable targeting) const popupRoot = el.closest?.('[data-testid="product-search-suggestions-popup"]'); if (popupRoot) return 'product-search-suggestions-popup'; // Otherwise: nearest ancestor with data-testid (one hop above the first hit) const first = el.closest?.('[data-testid]'); const parent = first?.parentElement?.closest?.('[data-testid]') || first; return parent?.getAttribute?.('data-testid') || ""; /* */},"scope":"LOCAL"},{"id":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","name":"currencyCode","type":"FUNCTION","valueType":"TEXT","function":function(event){return document.documentElement.getAttribute("data-currency-iso-code") || ""; /* */},"scope":"LOCAL"},{"id":"bfa64fe3-c31a-4550-bc41-39abf7f7360b","name":"emptySearchInput","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const exists = !!document.querySelector( '[data-testid="product-search-suggestions-popup"] [data-testid="product-search-product-list"] .stg-trackable-product-card' ); return !exists; /* */},"scope":"LOCAL"},{"id":"c58a7312-7b27-4ff7-804e-546e99c03152","name":"Empty search result popup","type":"CONSTANT","valueType":"TEXT","value":"Empty search result popup","scope":"GLOBAL"},{"id":"ad6080ea-719b-4732-952f-ef4f1ce45e02","name":"Event target","type":"FUNCTION","valueType":"EVENT","function":function(event){return event.target /* */},"scope":"GLOBAL"},{"id":"1e327f21-f8ab-4ffc-afbd-61bb59ee3728","name":"Event target - parent element","type":"FUNCTION","valueType":"EVENT","function":function(event){return event.target.parentElement; /* */},"scope":"GLOBAL"},{"id":"2e141436-b43c-40d6-bbed-64cfdca7f222","name":"Go to PDP - search clickout","type":"CONSTANT","valueType":"TEXT","value":"Go to PDP - search clickout","scope":"GLOBAL"},{"id":"8f616b9d-a538-4dca-a88f-8105e10c6965","name":"hasAutosuggestionWrapper","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const wrapper = event.target?.closest('div[data-testid="product-search-product-list"]'); return !!wrapper; /* */},"scope":"LOCAL"},{"id":"aaebc7bd-ec9d-48cc-a482-e61bd809fa3f","name":"hasCategorySearchSuggestionsWrapper","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const el = event.target; const hasWrapper = el.closest('div[data-testid="product-search-category-list"]'); return !!hasWrapper; /* */},"scope":"LOCAL"},{"id":"fc7e128a-8061-492a-bc9b-4bccdf013ab6","name":"identifierHref","type":"FUNCTION","valueType":"TEXT","function":function(event){ const el = (window.__evt?.target) || window.event?.target || document.activeElement; // Brand base (keeps sub-brand + locale prefix intact) const brandBase = (location.pathname.match(/^(\/(?:[^/]+\/)?[a-z]{2}\/[a-z]{2}_[a-z]{2})\b/i) || [""])[0]; // A solid "root" to search within: // - suggestions product card button // - any element carrying tracking id // - the general product card const root = el?.closest?.('[data-testid^="product-link-"]') || el?.closest?.('[data-tracking-id]') || el?.closest?.('.stg-trackable-product-card') || el; // now look for the PDP inside that root const link = root?.querySelector?.('a[href*="/p/"]') || el?.closest?.('a[href*="/p/"]'); // fallback: direct nearest if (link) { const href = link.getAttribute('href') || ''; if (!href) return ''; if (/^https?:\/\//i.test(href)) return href; // absolute // root-relative vs bare path (prefix with brandBase) return new URL(href, href.startsWith('/') ? location.origin : (location.origin + brandBase + '/')).href; } // Final fallback: build from SKU on the nearest trackable card const card = el?.closest?.('[data-tracking-id], .stg-trackable-product-card'); const sku = card?.getAttribute?.('data-tracking-id'); return sku ? new URL(`/p/${encodeURIComponent(sku)}`, location.origin + brandBase + '/').href : ''; /* */},"scope":"LOCAL"},{"id":"891ea5f6-cc29-4787-be9f-351372112e69","name":"isCategoryClickout","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const el = event.target; const closestHref = el.closest('a'); return !!closestHref?.getAttribute('href')?.includes('/c/cat_'); /* */},"scope":"LOCAL"},{"id":"2dc7bb1d-4a0f-4e0c-ab74-de088744557e","name":"isProductPdpClick","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const el = event.target; const productWrapper = el?.closest('button[data-testid*="product-link-"]'); return !!productWrapper; /* */},"scope":"LOCAL"},{"id":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","name":"locale","type":"FUNCTION","valueType":"TEXT","function":function(event){return document.documentElement.getAttribute("lang") || ""; /* */},"scope":"LOCAL"},{"id":"6c77635c-e95a-4eca-8086-f6be1b1193e8","name":"Named referral: Search","type":"CONSTANT","valueType":"TEXT","value":"Search","scope":"GLOBAL"},{"id":"fda8e609-5410-4707-b86b-01184d2af597","name":"No permission to track","type":"CONSTANT","valueType":"TEXT","value":"No permission to track","scope":"GLOBAL"},{"id":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","name":"Page URL","type":"FUNCTION","valueType":"TEXT","function":function(event){return window.location.href; /* */},"scope":"GLOBAL"},{"id":"82d3f082-6cb8-453e-8f80-567200c2a4da","name":"Page visit","type":"CONSTANT","valueType":"TEXT","value":"Page visit","scope":"GLOBAL"},{"id":"bd46e877-8f3b-4c33-91b9-1dc371e62355","name":"pdpSku","type":"FUNCTION","valueType":"TEXT","function":function(event){ const el = document.querySelector('[data-testid="product-typography-product-code"]'); const ref = (el?.textContent || "").trim(); const sku = ref.match(/[\d.]+[A-Z]?/); // e.g. 021.5310 or 021.5310A return sku ? String(sku[0]) : ""; // <-- return is required /* */},"scope":"LOCAL"},{"id":"7c90d4b8-ddf0-4166-b43a-2ce18c2f4755","name":"pdpSkuFromUrl","type":"FUNCTION","valueType":"TEXT","function":function(event){ const path = location.pathname; // Match anything after "/p/" up to a slash, question mark, or end of string const match = path.match(/\/p\/([^/?#]+)/i); if (match && match[1]) { return decodeURIComponent(match[1]); } return ""; /* */},"scope":"LOCAL"},{"id":"b12f3744-de4e-487e-b45c-494d0ecd4b3b","name":"Product details page visit","type":"CONSTANT","valueType":"TEXT","value":"Product details page visit","scope":"GLOBAL"},{"id":"42c22679-b3f7-4003-8975-c3e179e21d90","name":"Remove from cart","type":"CONSTANT","valueType":"TEXT","value":"Remove from cart","scope":"GLOBAL"},{"id":"f5260072-b60f-4a97-aad1-2950c7246db8","name":"searchInputSkusCsv","type":"FUNCTION","valueType":"LIST","function":function(event){return [...document .querySelector('[data-testid="product-search-product-list"]') ?.querySelectorAll('div.stg-trackable-product-card') || []] .map(el => el.dataset.trackingId || el.getAttribute('data-tracking-id')) .filter(Boolean); /* */},"scope":"LOCAL"},{"id":"effc6cd0-1b1d-4e33-b913-526ade59cf0a","name":"searchIsEmpty","type":"FUNCTION","valueType":"BOOLEAN","function":function(event){const main = document.querySelector("main"); if (!main) return false; // Look for the explicit empty search banner inside
const hasEmptyBanner = !!main.querySelector( '[data-testid="shop-section-empty-search-section"]' ); // True only if the banner is present return hasEmptyBanner; /* */},"scope":"LOCAL"},{"id":"ca544c79-ff6e-412a-a0b5-2bf963c493fd","name":"Search phrase typed","type":"CONSTANT","valueType":"TEXT","value":"Search phrase typed","scope":"GLOBAL"},{"id":"65acdc55-be24-40cf-ad19-de3d1ba2c697","name":"searchResultSkusCsv","type":"FUNCTION","valueType":"LIST","function":function(event){const cards = Array.from(document.querySelectorAll('main .stg-trackable-product-card')); return cards.map(c => c.getAttribute('data-tracking-id')).filter(Boolean); /* */},"scope":"LOCAL"},{"id":"17b79a43-d18f-4de9-b56c-eeb7a3e50200","name":"Search Results label (page)","type":"FUNCTION","valueType":"TEXT","function":function(event){const main = document.querySelector("main"); if (!main) return false; // Look for the explicit empty search banner inside
const hasEmptyBanner = !!main.querySelector( '[data-testid="shop-section-empty-search-section"]' ); // True only if the banner is present return hasEmptyBanner ? 'Empty search result page' : 'Search result page'; /* */},"scope":"LOCAL"},{"id":"c1fd0e80-cc66-4d38-b43f-6a20c5352a09","name":"transactionId","type":"FUNCTION","valueType":"TEXT","function":function(event){// /checkout/confirmation?order=05234000 (primary) const qs = new URLSearchParams(location.search); const qid = qs.get("order") || qs.get("orderId") || qs.get("transactionId"); if (qid) return qid; // Older pattern: /orderConfirmation/ const m = location.pathname.match(/\/orderConfirmation\/([^/?#]+)/i); return m ? m[1] : ""; /* */},"scope":"LOCAL"},{"id":"9ec04551-6b11-4101-b769-b08ee5148b1d","name":"Update cart","type":"CONSTANT","valueType":"TEXT","value":"Update cart","scope":"GLOBAL"},{"id":"16f42a89-ecfb-4b52-9363-20e91e064db8","name":"viewAllTargetUrl","type":"FUNCTION","valueType":"TEXT","function":function(event){const q = (document.querySelector('input[aria-label="search input"]')?.value || "").trim() || (new URLSearchParams(location.search).get("q") || "").trim(); const m = location.pathname.match(/^(\/(?:[^/]+\/)?[a-z]{2}\/[a-z]{2}_[a-z]{2})\b/i); const base = m ? m[1] : ""; return q ? `${base}/search?q=${encodeURIComponent(q)}` : (location.pathname + location.search); /* */},"scope":"LOCAL"}]; const script = {"id":"ea56e241-999a-49a6-a020-4edbc090064a","rows":[{"id":"55f613e0-7de5-4093-b7f8-2610cf2406b0","rowType":"EVENT","trigger":{"id":"336ce078-02f8-4f8a-9b0c-de83ab677678","name":"Reject All Cookies Click","type":"CLICK","groups":[{"id":"52a7d58b-1b61-4283-b624-6e347682c45b","rows":[{"valueType":"EVENT","id":"1fcc0196-3fef-4425-8234-f9ffffd02009","variableId":"ad6080ea-719b-4732-952f-ef4f1ce45e02","value":"onetrust-reject-all-handler","operator":"MATCHES_ID"}]}]},"action":{"type":"DECLINE_TRACKING"},"fields":[{"id":"1ed3949e-0a8f-45e1-8b46-3c645e274781","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"70c19ec4-dae9-4f2e-a54c-2232839727f5","variableId":"fda8e609-5410-4707-b86b-01184d2af597","fieldName":"eventLabel"}]},{"id":"b6511cff-e10e-4494-8335-0cc56bdd94a6","rowType":"EVENT","trigger":{"id":"d98ba2a4-9d32-4d67-ae05-d7719b5c2f41","name":"Search Result (fixed, add delay)","type":"PAGE_LOAD","groups":[{"id":"d615563f-f064-4dc2-95f6-283a7694cfa4","rows":[{"valueType":"TEXT","id":"95e1e657-e57d-496c-90d3-2feecdd0db5d","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/search","operator":"CONTAINS"}]}]},"action":{"type":"SEARCH_RESULT"},"fields":[{"id":"66db45ba-d87c-4c3d-a3ea-774913238cf0","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"113eef36-1c48-4720-858b-2ff85580f873","variableId":"effc6cd0-1b1d-4e33-b913-526ade59cf0a","fieldName":"isEmpty"},{"id":"bec9a451-a331-4859-afdc-cf6280c7672d","variableId":"65acdc55-be24-40cf-ad19-de3d1ba2c697","fieldName":"skus"},{"id":"746a78ed-ce7b-44eb-a970-f5e846481124","variableId":"17b79a43-d18f-4de9-b56c-eeb7a3e50200","fieldName":"eventLabel"}]},{"id":"cdd857d4-2dc8-4036-8f59-a045742eaf49","rowType":"EVENT","trigger":{"id":"812fcd64-4233-45dc-8ae2-1f52b181e53c","name":"Search Input (fixed, add delay)","type":"INPUT","groups":[{"id":"848a6656-5923-42d5-8a58-4f7723b8196c","rows":[{"valueType":"EVENT","id":"53b165aa-71de-483b-8d02-584aca1e910b","variableId":"ad6080ea-719b-4732-952f-ef4f1ce45e02","value":"input[aria-label=\"search input\"]","operator":"MATCHES_CSS_SELECTOR"},{"valueType":"BOOLEAN","id":"35d119b3-2016-462a-84db-4326f8940fba","variableId":"bfa64fe3-c31a-4550-bc41-39abf7f7360b","value":"true","operator":"EQUALS"}]}]},"action":{"type":"SEARCH_RESULT"},"fields":[{"id":"bb5f6e91-41f6-4424-a2e5-cb890dac1902","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"3f8d24a5-d02f-402f-9822-3f305ccbf96e","variableId":"bfa64fe3-c31a-4550-bc41-39abf7f7360b","fieldName":"isEmpty"},{"id":"f1fba82c-a18b-4890-a8c1-e7db820f94cf","variableId":"f5260072-b60f-4a97-aad1-2950c7246db8","fieldName":"skus"},{"id":"1f30e7af-9fd0-4531-93c2-66373f3907df","variableId":"c58a7312-7b27-4ff7-804e-546e99c03152","fieldName":"eventLabel"}]},{"id":"6368c407-750c-45e8-88d6-db7523b4022a","rowType":"EVENT","trigger":{"id":"cd689443-f8f6-48f8-83b6-a71af6a5a94c","name":"CLICKOUT – Add product (search plp and suggestions - fixed)","type":"CLICK","groups":[{"id":"864b5221-955a-4452-9383-25522e1ae742","rows":[{"valueType":"TEXT","id":"329c1477-389b-448e-87bf-322335aa4051","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"product-button-","operator":"CONTAINS"},{"valueType":"TEXT","id":"391ef57b-52fd-4034-8552-d78ebcec8282","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/search","operator":"CONTAINS"},{"valueType":"BOOLEAN","id":"8861869c-cb1a-4538-aefd-2ccabcc6c755","variableId":"8f616b9d-a538-4dca-a88f-8105e10c6965","value":"false","operator":"EQUALS"}]},{"id":"c4c64cc4-74b1-41f9-98f3-e1ffa996a21e","rows":[{"valueType":"TEXT","id":"1b363d65-ffdd-4cac-bb05-260955e7fbc4","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"product-button-","operator":"CONTAINS"},{"valueType":"BOOLEAN","id":"b2951763-0136-47e7-8144-a1f5b6cc49cb","variableId":"8f616b9d-a538-4dca-a88f-8105e10c6965","value":"true","operator":"EQUALS"}]}]},"action":{"type":"CLICKOUT"},"fields":[{"id":"f22a4a1f-179e-4788-a115-b2fe27cee84d","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"5f3aac5c-ffbd-4959-8bf3-46678090f4e6","variableId":"fc7e128a-8061-492a-bc9b-4bccdf013ab6","fieldName":"targetUrl"},{"id":"1bc1ccba-4690-43d0-9a23-0cb7209b8980","variableId":"6c77635c-e95a-4eca-8086-f6be1b1193e8","fieldName":"namedReferral"},{"id":"a1472d17-dfb1-4c26-aa6c-696ca838490f","variableId":"b73b1d5c-2232-410e-be49-48ec6609f4d7","fieldName":"eventLabel"}]},{"id":"bb2a83ba-d564-4578-a08b-ba6a70f9e956","rowType":"EVENT","trigger":{"id":"86246192-4b8b-4fb4-b588-e696ec596d2f","name":"CLICKOUT – Go to PDP (plp and suggestions - fixed)","type":"CLICK","groups":[{"id":"88e1d6bb-eb62-4f40-b727-da152166f3e0","rows":[{"valueType":"TEXT","id":"df74bc80-94da-4637-9bd2-f9d55402df02","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/search","operator":"CONTAINS"},{"valueType":"BOOLEAN","id":"f40371f6-13a8-4a0e-867e-8ce1293085f5","variableId":"2dc7bb1d-4a0f-4e0c-ab74-de088744557e","value":"true","operator":"EQUALS"},{"valueType":"BOOLEAN","id":"e3298a13-6d62-4f59-b76e-da10b2038d43","variableId":"8f616b9d-a538-4dca-a88f-8105e10c6965","value":"false","operator":"EQUALS"}]},{"id":"808a6df1-93d4-472a-be17-c579674dd114","rows":[{"valueType":"BOOLEAN","id":"9c8a7137-6922-4542-9df5-ff5a80afc42b","variableId":"8f616b9d-a538-4dca-a88f-8105e10c6965","value":"true","operator":"EQUALS"},{"valueType":"BOOLEAN","id":"9ab5b60e-506a-4a4d-92c4-27f95c848951","variableId":"2dc7bb1d-4a0f-4e0c-ab74-de088744557e","value":"true","operator":"EQUALS"}]}]},"action":{"type":"CLICKOUT"},"fields":[{"id":"f0e49925-92b1-4f70-950f-222346fb8693","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"c6b8e1ed-c286-4058-bed4-eef97c3caeeb","variableId":"fc7e128a-8061-492a-bc9b-4bccdf013ab6","fieldName":"targetUrl"},{"id":"23162b80-520e-4775-9778-78eddaa42c07","variableId":"6c77635c-e95a-4eca-8086-f6be1b1193e8","fieldName":"namedReferral"},{"id":"2a793d98-d159-4efc-aa5e-b738faac91f7","variableId":"2e141436-b43c-40d6-bbed-64cfdca7f222","fieldName":"eventLabel"},{"id":"6e83275f-e01f-491f-8541-4d4b758d1b1c","variableId":"17544614-8761-4994-999e-0846fa6ef15f","fieldName":"category"}]},{"id":"368933da-7391-4a10-beae-7994655d4a18","rowType":"EVENT","trigger":{"id":"257f9167-ec37-4ee9-a872-c50202668526","name":"CLICKOUT – Go to Category page (fixed)","type":"CLICK","groups":[{"id":"9381a3f0-a37b-47bb-9406-3e5b03f35ed4","rows":[{"valueType":"TEXT","id":"10a2bfb2-9581-4915-92a6-77d0f827b5cf","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/search","operator":"CONTAINS"},{"valueType":"BOOLEAN","id":"31d22566-9bdf-4ea4-bdca-051c0fcd8de1","variableId":"891ea5f6-cc29-4787-be9f-351372112e69","value":"true","operator":"EQUALS"}]},{"id":"9e3bdaee-ca5e-4de4-84d0-d4e246d6673f","rows":[{"valueType":"BOOLEAN","id":"50d13080-77ba-42a9-8f0f-3f26aefaae06","variableId":"891ea5f6-cc29-4787-be9f-351372112e69","value":"true","operator":"EQUALS"},{"valueType":"BOOLEAN","id":"79e2ddd5-9d7b-4a37-8bd2-b200e1ed016c","variableId":"aaebc7bd-ec9d-48cc-a482-e61bd809fa3f","value":"true","operator":"EQUALS"}]}]},"action":{"type":"CLICKOUT"},"fields":[{"id":"e9285d88-2d03-4fc0-9e07-96721bb7ed2c","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"3e1003ad-a042-447c-9007-a308d2df7c4c","variableId":"e421893f-c0f4-435d-922d-3809963e986e","fieldName":"targetUrl"},{"id":"b19e5d7c-bf34-4148-8f61-95691fb1030f","variableId":"6c77635c-e95a-4eca-8086-f6be1b1193e8","fieldName":"namedReferral"},{"id":"93d3bd16-328b-4973-973c-559c2d1a1de1","variableId":"3b881070-bf08-4869-be93-2b5d94a99c5b","fieldName":"eventLabel"},{"id":"b6cb3d1f-4105-4346-9eeb-c3921a55135d","variableId":"17544614-8761-4994-999e-0846fa6ef15f","fieldName":"category"}]},{"id":"23577876-65fb-4b89-9c6a-7b04698ef45a","rowType":"EVENT","trigger":{"id":"572961b5-d08d-4e97-a558-e577a2d5ddbd","name":"Checkout Confirmation","type":"PAGE_LOAD","groups":[{"id":"620711b8-2556-4ad4-aa27-7dbf881eb109","rows":[{"valueType":"TEXT","id":"0d1d23d8-7ecd-4b37-bcba-a528f714685f","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/checkout/confirmation","operator":"CONTAINS"}]}]},"action":{"type":"PURCHASED"},"fields":[{"id":"7a3e9f40-fb33-46d4-88ed-5b6e932319be","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"b0c731fd-3d4d-4a98-ad2c-d45f18baf0f3","variableId":"904c3ff0-8e69-48ca-a868-c61c5260d9e7","fieldName":"products"},{"id":"92635f6d-faa8-4ba2-93a5-df67f0e59ad4","variableId":"c1fd0e80-cc66-4d38-b43f-6a20c5352a09","fieldName":"transactionId"}]},{"id":"8eb859be-5ebb-49e7-882b-f7d41546df12","rowType":"EVENT","trigger":{"id":"a2fc863c-49f8-4fea-b842-bc378b676ad2","name":"Remove from cart – Single Item","type":"CLICK","groups":[{"id":"4bf88d2b-28e0-437e-8945-0b51742c715e","rows":[{"valueType":"TEXT","id":"b26cef14-21b9-424c-89fa-11ef74ee18d3","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"cart-button-cart-entry-delete","operator":"CONTAINS"}]}]},"action":{"type":"REMOVE_FROM_CART"},"fields":[{"id":"adccbaae-3e9c-428e-9d0b-18ae9c24e226","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"ac7cf4c2-0faa-4a03-b7d6-6c98d80e2fa6","variableId":"2c79bdb1-b595-407b-9055-dc8afdff4c17","fieldName":"sku"},{"id":"25f0fb8c-3428-4558-b8ff-84d3fc70b5f8","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"2727cbeb-37b9-478b-9cf6-e922ba64b13c","variableId":"42c22679-b3f7-4003-8975-c3e179e21d90","fieldName":"eventLabel"},{"id":"1d888c8c-178a-4dfd-ae41-5211fb0beda1","variableId":"794148b9-d30c-4fa9-ab0f-d1e903691954","fieldName":"price"}]},{"id":"5e84a706-b242-410d-b0b2-1aab9288f415","rowType":"EVENT","trigger":{"id":"fe70154b-7eb2-4e2c-a341-56659ae0e723","name":"Quantity Decrement (fixed)","type":"CLICK","groups":[{"id":"63a68bb9-eee6-4701-91b3-4b6d697298c9","rows":[{"valueType":"TEXT","id":"54871943-edc4-4c48-8385-94ad91c8811c","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/cart","operator":"CONTAINS"},{"valueType":"EVENT","id":"c6a26863-ebc0-4e17-aebf-dbaa878c4bdc","variableId":"1e327f21-f8ab-4ffc-afbd-61bb59ee3728","value":"button[data-testid*=\"-cart-entry-quantity-decrement\"]","operator":"MATCHES_CSS_SELECTOR"}]}]},"action":{"type":"UPDATE_CART"},"fields":[{"id":"5f3e2e8b-7b7a-4b1b-b5d2-52c40178d222","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"0560288f-43f6-47b5-8d0f-87964a416c54","variableId":"2c79bdb1-b595-407b-9055-dc8afdff4c17","fieldName":"sku"},{"id":"812ef2c2-d1ab-42d9-ae4b-999f1975777e","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"92073477-d3b4-45fd-bbfa-fd8ecbadef62","variableId":"9ec04551-6b11-4101-b769-b08ee5148b1d","fieldName":"eventLabel"},{"id":"0cdbde77-6b70-4b43-939d-b8da693eb6b3","variableId":"794148b9-d30c-4fa9-ab0f-d1e903691954","fieldName":"price"},{"id":"89348f1b-8317-46a5-876a-e3746e035be1","variableId":"521ed7c6-7510-45cc-b206-4d9380418fee","fieldName":"quantity"}]},{"id":"da08ca78-185d-45d6-b9a3-e07bf60a0bc0","rowType":"EVENT","trigger":{"id":"3eae7a8d-b2bd-4518-9490-d3ce2496687a","name":"Quantity increment (fixed)","type":"CLICK","groups":[{"id":"33170df7-3820-438d-9a03-94afa9308185","rows":[{"valueType":"EVENT","id":"949fc82e-23e1-45ee-9ef6-99f38a0e48bc","variableId":"1e327f21-f8ab-4ffc-afbd-61bb59ee3728","value":"button[data-testid*=\"-cart-entry-quantity-increment\"]","operator":"MATCHES_CSS_SELECTOR"},{"valueType":"TEXT","id":"dd89b3c6-e632-4dd6-aaf9-6982e7c7a4c0","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/cart","operator":"CONTAINS"}]}]},"action":{"type":"UPDATE_CART"},"fields":[{"id":"2341e2f1-2ba3-4e1e-9b6e-b650aa9dbcb7","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"234600ad-bb4b-4bf5-8f91-9f6efe6a0113","variableId":"9ec04551-6b11-4101-b769-b08ee5148b1d","fieldName":"eventLabel"},{"id":"e9c93ac8-f034-4969-ae8d-b801c1debec6","variableId":"dafc253c-b1ae-45db-81fd-4d274f7104aa","fieldName":"quantity"},{"id":"f1dda2c7-163d-49a0-b92f-b2edc3a5d73b","variableId":"794148b9-d30c-4fa9-ab0f-d1e903691954","fieldName":"price"},{"id":"bd929c79-0a9c-4c80-8ca1-67040fd92570","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"3f262e9d-311d-433d-b6a3-1cb5a4796c97","variableId":"2c79bdb1-b595-407b-9055-dc8afdff4c17","fieldName":"sku"}]},{"id":"739045a8-38f0-4b92-b8af-352194e7335d","rowType":"EVENT","trigger":{"id":"325a6bfb-1a56-4433-acd6-5767f44c75de","name":"Search Input","type":"INPUT","groups":[{"id":"36c53dfb-0893-484f-864e-68607755b9c9","rows":[{"valueType":"EVENT","id":"a4c980b2-7477-495d-ad24-0d08efb85f80","variableId":"ad6080ea-719b-4732-952f-ef4f1ce45e02","value":"input[aria-label=\"search input\"]","operator":"MATCHES_CSS_SELECTOR"}]}]},"action":{"type":"SEARCH"},"fields":[{"id":"13fb053b-d092-41b7-a5e8-b211226c6d1f","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"29e09251-8bfb-471c-b737-0772492c506a","variableId":"ca544c79-ff6e-412a-a0b5-2bf963c493fd","fieldName":"eventLabel"}]},{"id":"dd0249ef-b5b7-4996-b774-d958164dec90","rowType":"EVENT","trigger":{"id":"05ba7d0d-1728-4931-8a35-5a9591d39875","name":"PDP Page Load","type":"PAGE_LOAD","groups":[{"id":"dd1e956a-1215-4558-bca5-2050967336bc","rows":[{"valueType":"TEXT","id":"3b3ae660-7005-4920-8e86-5fc527bbdab0","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/p/","operator":"CONTAINS"}]}]},"action":{"type":"PDP_VISITED"},"fields":[{"id":"1689ad53-e4e7-42cd-8fa2-e6e9b428b012","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"ec2cfe0b-7ae5-4b8c-8085-d885ead44d73","variableId":"b12f3744-de4e-487e-b45c-494d0ecd4b3b","fieldName":"eventLabel"},{"id":"1dc4dcea-e98e-499d-8118-0db8331f4a65","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"093ac788-89e1-40aa-87c8-d684669fde45","variableId":"7c90d4b8-ddf0-4166-b43a-2ce18c2f4755","fieldName":"sku"}]},{"id":"46150c03-a724-4d93-b3fa-f442b5ce3526","rowType":"EVENT","trigger":{"id":"25fe6abf-7b99-4b98-ae52-9af63be84944","name":"Page Load","type":"PAGE_LOAD","groups":[{"id":"bb0ce265-caf4-4aa4-ae70-6ffabae2e125","rows":[{"valueType":"TEXT","id":"32b8b73c-0fe4-42b6-9999-666eb1527945","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/p/","operator":"DOES_NOT_CONTAIN"}]}]},"action":{"type":"PAGE_VISITED"},"fields":[{"id":"1e055ab5-1986-4bd5-905d-3e8d195177af","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"da08998f-10ee-49cf-a86c-2938aa9ce8f3","variableId":"82d3f082-6cb8-453e-8f80-567200c2a4da","fieldName":"eventLabel"}]},{"id":"431e2544-1e60-4c9f-93a7-4536e36fe8f1","rowType":"EVENT","trigger":{"id":"4bc664b8-13bf-4374-abbf-508223ffb79c","name":"Add to cart (Search Suggestions)","type":"CLICK","groups":[{"id":"fbef9d81-1f45-468d-8768-16cb1cdec22b","rows":[{"valueType":"TEXT","id":"2eb786d9-06b7-49fb-8136-f6eb8a892056","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"-addToCart","operator":"CONTAINS"},{"valueType":"TEXT","id":"111e189a-3482-43b4-9a7f-8ae14402961c","variableId":"50d1794c-965c-4d73-bb7e-558080b33281","value":"product-search-suggestions-popup","operator":"EQUALS"}]}]},"action":{"type":"ADD_TO_CART"},"fields":[{"id":"183eecc6-bf83-40f8-b16e-1c8efe1e8471","variableId":"9bcc6c18-d60d-4f77-b7d3-8f9d8dc4a217","fieldName":"sku"},{"id":"f52792e8-aec0-4461-9b1c-4bb69d06a3ea","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"a525ceb7-bdbe-4b10-b9cb-45917d98bfd5","variableId":"17544614-8761-4994-999e-0846fa6ef15f","fieldName":"category"},{"id":"4d0970b4-da53-4822-bf47-d8d0bdc768cc","variableId":"1eec2be6-dc91-4c4e-a443-da2f051baf5b","fieldName":"eventLabel"},{"id":"4dc8a0b3-79bb-4718-8a08-86c9ba1ff556","variableId":"c6abe1c2-0962-4813-8a13-d4f6771c890f","fieldName":"price"},{"id":"9b101cb2-b05e-4aa8-8829-cc56bcb41f0b","variableId":"e13c5676-bb2c-43c9-be42-938b221632b4","fieldName":"quantity"},{"id":"29d8c386-5718-451c-b08d-305eafa8d052","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"}]},{"id":"1da55b18-73f1-42dc-8807-e21f253a87b6","rowType":"EVENT","trigger":{"id":"3044de02-59a8-47ef-b07e-fc24187bc690","name":"Add to cart (Search Results Page - fixed)","type":"CLICK","groups":[{"id":"b3d14ef0-7d6a-4035-9221-c3dfecc8f498","rows":[{"valueType":"TEXT","id":"f5304d17-e1b1-4402-b694-ac5457fedb02","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/search","operator":"CONTAINS"},{"valueType":"TEXT","id":"612b42c3-f3ee-4e50-9636-21e5555b511a","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"-addToCart","operator":"CONTAINS"},{"valueType":"BOOLEAN","id":"2de9931a-14c7-4e94-906e-cd44453d796a","variableId":"8f616b9d-a538-4dca-a88f-8105e10c6965","value":"false","operator":"EQUALS"}]}]},"action":{"type":"ADD_TO_CART"},"fields":[{"id":"7d94f7c4-ee06-42df-816b-2deebf540f23","variableId":"c6abe1c2-0962-4813-8a13-d4f6771c890f","fieldName":"price"},{"id":"a780516e-c3bc-48a2-b811-f13b1e6edd8f","variableId":"e13c5676-bb2c-43c9-be42-938b221632b4","fieldName":"quantity"},{"id":"384bd5c1-5243-44c8-b8e1-16d6f6e43f6e","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"ef46aeda-498e-4181-974e-24d4f8691a6a","variableId":"9bcc6c18-d60d-4f77-b7d3-8f9d8dc4a217","fieldName":"sku"},{"id":"3ee682f9-7f63-4741-bd7b-76c7705e1825","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"50a38021-30ef-4676-993a-3cf10dd384ad","variableId":"17544614-8761-4994-999e-0846fa6ef15f","fieldName":"category"},{"id":"ec666725-14d0-44c7-bb12-83b425cc75b8","variableId":"1eec2be6-dc91-4c4e-a443-da2f051baf5b","fieldName":"eventLabel"}]},{"id":"7b84c993-a5fc-4018-827d-abd32f4779bb","rowType":"EVENT","trigger":{"id":"61a4b0c3-8b77-4aef-88f8-6a8641601238","name":"Add to Cart (PDP)","type":"CLICK","groups":[{"id":"ed16add2-bba1-494b-b506-87a608c883ad","rows":[{"valueType":"TEXT","id":"880694ae-dbdb-44c0-8dfa-ac7b57104c08","variableId":"75cf8fd1-fafe-44be-9806-23ff3017c9c1","value":"/p/","operator":"CONTAINS"},{"valueType":"TEXT","id":"890e72ab-5bd2-431d-bc47-0e211ec296c5","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"-addToCart","operator":"CONTAINS"}]}]},"action":{"type":"ADD_TO_CART"},"fields":[{"id":"0c8175c7-b417-4d99-89fe-842faa3a2240","variableId":"c6abe1c2-0962-4813-8a13-d4f6771c890f","fieldName":"price"},{"id":"4570a8ae-3d0d-43f3-aa87-4c25abf1e999","variableId":"e13c5676-bb2c-43c9-be42-938b221632b4","fieldName":"quantity"},{"id":"ed2b2cdb-1d7b-4825-9454-a913f5e68470","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"3b20dbfa-6a1a-4ab3-85ee-4c767d46a6de","variableId":"bd46e877-8f3b-4c33-91b9-1dc371e62355","fieldName":"sku"},{"id":"f6ad1824-3d02-4844-b1fa-44ada2548694","variableId":"17544614-8761-4994-999e-0846fa6ef15f","fieldName":"category"},{"id":"5de09d03-2da6-4dad-ab4d-b807566e03c7","variableId":"b69c433b-e98f-43bf-a3fa-80774c6b54fb","fieldName":"currencyCode"},{"id":"0717b922-33da-4f13-a0c3-f39811bf9ab3","variableId":"1eec2be6-dc91-4c4e-a443-da2f051baf5b","fieldName":"eventLabel"}]},{"id":"78b4526b-55c9-4944-89b3-1e68de83a4ea","rowType":"EVENT","trigger":{"id":"61080a23-b451-4afd-8954-8d72011a93ea","name":"View all products (suggestions)","type":"CLICK","groups":[{"id":"c2b71cbd-98b4-4218-9d77-d7c9c0204afa","rows":[{"valueType":"TEXT","id":"8ec34604-4979-4fe7-abad-d7180fab39d3","variableId":"fe8767b5-7afa-45f8-ae72-0ed18dda9f49","value":"product-search-suggestions-view-all-button","operator":"EQUALS"}]}]},"action":{"type":"CLICKOUT"},"fields":[{"id":"33ad2a30-bbb0-450f-8dc8-2952df1bd20e","variableId":"59dfcac1-9388-4dd0-9382-8ec21d1d0033","fieldName":"locale"},{"id":"f3211303-5551-4aa6-9a42-bb9286985646","variableId":"16f42a89-ecfb-4b52-9363-20e91e064db8","fieldName":"targetUrl"},{"id":"e23b3226-8032-494e-a5a3-c7f23bb942a9","variableId":"6c77635c-e95a-4eca-8086-f6be1b1193e8","fieldName":"namedReferral"},{"id":"c96acf09-a42d-42dd-af01-8c63a340f0e5","variableId":"d2d8bad9-06f7-4f78-9184-8c38a9a469a1","fieldName":"eventLabel"}]}]}; const advancedCode = function(){/* ========================================================= URL helpers → derive env|brand|locale from the current URL ========================================================= */ (function () { function detectEnv(host) { if (!host) return "prod"; const h = host.toLowerCase(); return h.startsWith("test-") || h.startsWith("test.") || h.includes("test-shop") || h.includes(".stg.") || h.includes("-stg.") || h.includes(".stage.") ? "test" : "prod"; } function detectBrand(pathname) { const parts = (pathname || "/").split("/").filter(Boolean); const seg = (parts[0] || "").toLowerCase(); if (seg === "medentika") return "medentika"; if (seg === "neodent") return "neodent"; return "straumann"; // default when no explicit brand segment } // Supports standard xx_xx locales and distributor locales like dist_en_di function detectLocale(pathname) { const parts = (pathname || "/").split("/").filter(Boolean); let i = 0; const seg0 = (parts[0] || "").toLowerCase(); if (seg0 === "medentika" || seg0 === "neodent") i = 1; // Distributor paths (e.g., /medentika/dist/en/di/ → dist_en_di) const maybeDist = (parts[i] || "").toLowerCase(); if (maybeDist === "dist") { const a = (parts[i] || "").toLowerCase(); const b = (parts[i + 1] || "").toLowerCase(); const c = (parts[i + 2] || "").toLowerCase(); const distLocale = [a, b, c].filter(Boolean).join("_"); return distLocale || null; } // Standard brandless or branded: country + xx_xx const loc = (parts[i + 1] || "").toLowerCase(); if (/^[a-z]{2}_[a-z]{2}$/i.test(loc)) return loc; // Fallbacks: try to detect any xx_xx anywhere for (let p of parts) { const s = (p || "").toLowerCase(); if (/^[a-z]{2}_[a-z]{2}$/i.test(s)) return s; } return null; } function makeKey(env, brand, locale) { return `${(env || "").toLowerCase()}|${(brand || "").toLowerCase()}|${(locale || "").toLowerCase()}`; } /* ========================================================= FULL inline PROJECT_MAP (env|brand|locale → projectId) ========================================================= */ const PROJECT_MAP = { // ---------- Neodent Test ---------- "test|neodent|fr_ca": 46115, "test|neodent|en_za": 46117, "test|neodent|en_us": 46119, "test|neodent|de_de": 46121, "test|neodent|en_ca": 46123, "test|neodent|en_be": 46125, "test|neodent|fr_fr": 46127, "test|neodent|fr_be": 46128, "test|neodent|de_ch": 46129, "test|neodent|en_fi": 46130, "test|neodent|en_nz": 46131, "test|neodent|en_se": 46132, "test|neodent|de_at": 46133, "test|neodent|en_uk": 46136, "test|neodent|en_dk": 46139, "test|neodent|fr_ch": 46141, "test|neodent|en_nl": 46143, "test|neodent|en_au": 46144, "test|neodent|en_no": 46146, "test|neodent|en_hu": 46148, "test|neodent|en_ro": 46150, "test|neodent|es_pe": 46152, "test|neodent|pt_pt": 46154, "test|neodent|es_es": 46156, "test|neodent|it_it": 46158, "test|neodent|es_ar": 46160, "test|neodent|es_mx": 46162, "test|neodent|it_ch": 46164, "test|neodent|es_cl": 46166, "test|neodent|es_co": 46168, "test|neodent|pt_br": 46170, "test|neodent|hu_hu": 53982, // ---------- Straumann Test ---------- "test|straumann|fr_ca": 29029, "test|straumann|en_za": 29672, "test|straumann|en_us": 29026, "test|straumann|de_de": 29027, "test|straumann|en_ca": 29028, "test|straumann|en_be": 29835, "test|straumann|fr_fr": 29825, "test|straumann|fr_be": 29836, "test|straumann|de_ch": 29830, "test|straumann|en_fi": 29839, "test|straumann|en_kr": 29840, "test|straumann|en_nz": 29841, "test|straumann|en_se": 29833, "test|straumann|de_at": 29837, "test|straumann|en_uk": 29829, "test|straumann|en_dk": 29838, "test|straumann|en_jp": 29824, "test|straumann|fr_ch": 29831, "test|straumann|en_nl": 29832, "test|straumann|en_au": 30796, "test|straumann|en_no": 30803, "test|straumann|en_ie": 30798, "test|straumann|en_hu": 30804, "test|straumann|en_ro": 30795, "test|straumann|en_sg": 30797, "test|straumann|es_pe": 31871, "test|straumann|pt_pt": 31865, "test|straumann|es_es": 31863, "test|straumann|it_it": 31864, "test|straumann|es_ar": 31867, "test|straumann|es_mx": 31870, "test|straumann|it_ch": 31862, "test|straumann|es_cl": 31868, "test|straumann|es_co": 31869, "test|straumann|pt_br": 31872, "test|straumann|ko_kr": 31866, "test|straumann|jp_jp": 41000, "test|straumann|hu_hu": 53980, // ---------- Neodent Production ---------- "prod|neodent|es_ar": 46089, "prod|neodent|de_at": 46090, "prod|neodent|en_au": 46091, "prod|neodent|en_be": 46092, "prod|neodent|fr_be": 46093, "prod|neodent|pt_br": 46094, "prod|neodent|en_ca": 46095, "prod|neodent|fr_ca": 46096, "prod|neodent|es_cl": 46097, "prod|neodent|es_co": 46098, "prod|neodent|en_dk": 46099, "prod|neodent|en_fi": 46100, "prod|neodent|fr_fr": 46101, "prod|neodent|de_de": 46102, "prod|neodent|en_hu": 46103, "prod|neodent|it_it": 46104, "prod|neodent|es_mx": 46105, "prod|neodent|en_nz": 46106, "prod|neodent|en_no": 46107, "prod|neodent|es_pe": 46108, "prod|neodent|pt_pt": 46109, "prod|neodent|en_ro": 46110, "prod|neodent|es_es": 46111, "prod|neodent|en_za": 46112, "prod|neodent|en_se": 46113, "prod|neodent|de_ch": 46116, "prod|neodent|fr_ch": 46118, "prod|neodent|it_ch": 46120, "prod|neodent|en_nl": 46122, "prod|neodent|en_uk": 46124, "prod|neodent|en_us": 46126, "prod|neodent|hu_hu": 53981, // ---------- Medentika Test ---------- "test|medentika|de_at": 46138, "test|medentika|en_au": 46140, "test|medentika|en_be": 46142, "test|medentika|fr_be": 46145, "test|medentika|en_dk": 46147, "test|medentika|en_fi": 46149, "test|medentika|fr_fr": 46151, "test|medentika|de_de": 46153, "test|medentika|it_it": 46155, "test|medentika|en_nz": 46157, "test|medentika|en_no": 46159, "test|medentika|pt_pt": 46161, "test|medentika|es_es": 46163, "test|medentika|en_za": 46165, "test|medentika|en_se": 46167, "test|medentika|en_nl": 46169, "test|medentika|en_uk": 46171, "test|medentika|en_us": 46172, "test|medentika|dist_en_di": 52689, "test|medentika|dist_es_di": 52690, "test|medentika|dist_fr_di": 52691, // ---------- Straumann Production ---------- "prod|straumann|de_de": 29354, "prod|straumann|en_ca": 29355, "prod|straumann|fr_ca": 29356, "prod|straumann|en_us": 29353, "prod|straumann|en_be": 29851, "prod|straumann|fr_be": 29852, "prod|straumann|en_kr": 29856, "prod|straumann|en_za": 29858, "prod|straumann|fr_fr": 29843, "prod|straumann|en_uk": 29844, "prod|straumann|de_at": 29853, "prod|straumann|en_se": 29850, "prod|straumann|en_nz": 29857, "prod|straumann|de_ch": 29845, "prod|straumann|en_nl": 29849, "prod|straumann|en_dk": 29854, "prod|straumann|en_fi": 29855, "prod|straumann|fr_ch": 29847, "prod|straumann|en_jp": 29842, "prod|straumann|en_ro": 30799, "prod|straumann|en_sg": 30801, "prod|straumann|en_ie": 30802, "prod|straumann|en_no": 30743, "prod|straumann|en_hu": 30744, "prod|straumann|en_au": 30800, "prod|straumann|es_co": 31858, "prod|straumann|es_mx": 31859, "prod|straumann|it_ch": 31851, "prod|straumann|es_es": 31852, "prod|straumann|es_pe": 31860, "prod|straumann|pt_pt": 31854, "prod|straumann|ko_kr": 31855, "prod|straumann|es_ar": 31856, "prod|straumann|es_cl": 31857, "prod|straumann|pt_br": 31861, "prod|straumann|it_it": 31853, "prod|straumann|hu_hu": 53979, // ---------- Medentika Production ---------- "prod|medentika|de_at": 46176, "prod|medentika|en_au": 46177, "prod|medentika|en_be": 46178, "prod|medentika|fr_be": 46179, "prod|medentika|en_dk": 46180, "prod|medentika|en_nl": 46181, "prod|medentika|en_fi": 46182, "prod|medentika|fr_fr": 46183, "prod|medentika|de_de": 46184, "prod|medentika|it_it": 46185, "prod|medentika|en_nz": 46186, "prod|medentika|en_no": 46187, "prod|medentika|pt_pt": 46188, "prod|medentika|es_es": 46189, "prod|medentika|en_za": 46190, "prod|medentika|en_se": 46191, "prod|medentika|en_uk": 46192, "prod|medentika|en_us": 46193, "prod|medentika|dist_en_di": 52697, "prod|medentika|dist_fr_di": 52698, "prod|medentika|dist_es_di": 52699, }; // Compute the key from the current URL const env = detectEnv(window.location.hostname); const brand = detectBrand(window.location.pathname); const locale = detectLocale(window.location.pathname); const key = makeKey(env, brand, locale); const resolvedProjectId = PROJECT_MAP[key]; if (!resolvedProjectId) { console.warn("[Zoovu] No projectId for key:", key, { env, brand, locale, url: location.href }); } // OPTIONAL: last-resort fallback if nothing resolves const PROJECT_ID = String(resolvedProjectId || "30743"); // ---- Zoovu Search Tracking Configuration ---- window.zoovuSearchTrackingConfiguration = { siteId: String(PROJECT_ID), // ← resolved project ID // single "insights" segment; no querystring baseUrl: "https://api.search.zoovu.com/insights", interface: { /* ========== SEARCH BOX ========== */ searchBox: { selector: 'input[aria-label="search input"]', }, /* ========== SEARCH SUGGESTIONS (popup/autocomplete) ========== */ searchSuggestions: { blockSelector: '[data-testid="product-search-suggestions-popup"]', itemSelector: '[data-testid="product-search-suggestions-popup"] .stg-trackable-product-card', activeItemSelector: '[data-testid="product-search-suggestions-popup"] .stg-trackable-product-card[aria-selected="true"]', initializationStrategy: { type: "observer", wrapper: '[data-testid="product-search-suggestions-popup"]' }, // SKU / Article number articleNumberSource: { type: "domElement", selector: '[data-testid="product-search-suggestions-popup"] .stg-trackable-product-card', source: "@data-tracking-id" }, // Clicked product URL inside the suggestion card identifierSource: { type: "domElement", selector: '[data-testid="product-search-suggestions-popup"] a[href*="/p/"]', source: "@href" }, }, /* ========== SEARCH RESULTS (SERP) ========== */ searchResults: { blockSelector: "main", itemSelector: "main .stg-trackable-product-card", // URL is /search?q=... expected expectedConditions: { urlRegex: "/search", searchParam: "q", // client’s “empty results” marker emptySelector: 'div[data-testid="shop-section-empty-search-section"]', }, // query from URL querySource: { type: "urlParam", paramName: "q" }, // SKU / Article number articleNumberSource: { type: "domElement", selector: "main .stg-trackable-product-card", source: "@data-tracking-id" }, // Product link on card (when present) identifierSource: { type: "domElement", selector: 'main .stg-trackable-product-card a[href*="/p/"]', source: "@href" }, }, /* ========== PDP ========== */ productDetailPage: { // native PDP add-to-cart button trigger: '[data-testid="product-section-information"] button[data-testid^="product-button-"][data-testid$="-addToCart"]', expectedConditions: { urlRegex: "/p/" }, // REF / SKU articleNumberSource: { type: "domElement", selector: '[data-testid="product-section-information"] label[data-testid="product-typography-product-code"]', source: "text", }, // Price text (parsed by tracker to Decimal) priceSource: { type: "domElement", selector: '[data-testid="product-section-information"] [data-testid^="component-price-"][data-testid$="-current-price"]', source: "text", }, // Currency code from priceUnitSource: { type: "domElement", selector: "html", source: "@data-currency-iso-code" }, // Quantity input in PDP main info block countSource: { type: "domElement", selector: '[data-testid="product-section-information"] [data-testid$="-product-quantity-input"] input', source: "@value" }, }, /* ========== CHECKOUT ========== */ checkout: { expectedConditions: { urlRegex: "\\/(cart|checkout\\/(addresses|shipping-method|payment-type|confirmation|orderConfirmation))(\\/|\\?|$)", }, // e.g. “Next” / continue button during checkout trigger: 'button[data-testid="checkout-button-next"]', // Each product card on checkout views itemSource: { // Card wrapper contains the SKU in its data-testid: checkout-card-cart-entry- selector: '[data-testid^="checkout-card-cart-entry-"]', // REF label — data-testid="checkout-card-product-label--REF-" articleNumberSource: { type: "domElement", selector: 'label[data-testid*="checkout-card-product-label-"]', source: "text" }, // Product link — data-testid="cart-link-product-name-" linkSource: { type: "domElement", selector: 'a[data-testid^="cart-link-product-name-"]', source: "@href" }, // Unit/line price label — prefer total; fall back to base/unit if exposed later unitPriceSource: { type: "domElement", selector: 'div[data-testid^="checkout-card-cart-entry-"] label[data-testid^="component-price-"]', source: "text" }, // Currency code from priceUnitSource: { type: "domElement", selector: "html", source: "@data-currency-iso-code" }, // Quantity: read-only span with just the number countSource: { type: "domElement", selector: '[data-testid^="checkout-typography-unit-quantity-"]', source: "text" }, }, }, }, }; // ---- Load Zoovu tracker (idempotent) ---- (function loadZoovuTracker() { if (document.querySelector('script[src*="zoovu-tracker.min.js"]')) return; const s = document.createElement("script"); s.src = "https://cdn.search-studio.zoovu.com/zoovu-tracker.min.js"; s.defer = true; document.head.appendChild(s); })(); })();}; const url = 'https://queue-propagator.zoovu.com'; const currentEnvironment = 'orca'; const currentAccountId = 250000008; const currencies = ['FJD', 'MXN', 'STD', 'LVL', 'SCR', 'CDF', 'BBD', 'HNL', 'UGX', 'ZAR', 'MXV', 'STN', 'CUC', 'BSD', 'SDD', 'SDG', 'IQD', 'GMD', 'CUP', 'TWD', 'RSD', 'UYI', 'MYR', 'FKP', 'XOF', 'UYU', 'CVE', 'OMR', 'SEK', 'KES', 'BTN', 'GNF', 'MZN', 'SVC', 'MZM', 'ARS', 'QAR', 'IRR', 'NLG', 'XPD', 'UZS', 'XPF', 'THB', 'BDT', 'LYD', 'KWD', 'XPT', 'RUB', 'ISK', 'BEF', 'MKD', 'RUR', 'DZD', 'PAB', 'SGD', 'KGS', 'XAD', 'XAF', 'XAG', 'ITL', 'HRK', 'CHF', 'ATS', 'CHE', 'DJF', 'TZS', 'VND', 'XAU', 'ADP', 'AUD', 'CHW', 'KHR', 'XBA', 'IDR', 'KYD', 'XBC', 'XBB', 'SHP', 'BWP', 'XBD', 'CYP', 'TJS', 'AED', 'RWF', 'DKK', 'ZWD', 'BGL', 'BGN', 'MMK', 'SYP', 'NOK', 'ZWG', 'ZWL', 'YUM', 'ZWN', 'LKR', 'ZWR', 'IEP', 'CZK', 'XCD', 'GRD', 'HTG', 'XSU', 'AFA', 'XCG', 'SIT', 'BHD', 'PTE', 'SZL', 'KZT', 'YER', 'AFN', 'BYB', 'NPR', 'AWG', 'MNT', 'GBP', 'BYN', 'XTS', 'HUF', 'BYR', 'BIF', 'XUA', 'XDR', 'BZD', 'MOP', 'NAD', 'SKK', 'TMM', 'PEN', 'WST', 'TMT', 'FRF', 'CLF', 'GTQ', 'CLP', 'TND', 'SLE', 'SLL', 'AYM', 'XFO', 'DOP', 'KMF', 'XFU', 'GEL', 'MAD', 'AZM', 'TOP', 'AZN', 'PGK', 'UAH', 'ERN', 'TPE', 'MRO', 'CNY', 'MRU', 'BMD', 'PHP', 'XXX', 'PYG', 'JMD', 'GWP', 'ESP', 'COP', 'USD', 'COU', 'USN', 'ETB', 'VEB', 'VED', 'USS', 'VEF', 'SOS', 'VUV', 'LAK', 'BND', 'ZMK', 'LRD', 'ALL', 'GHC', 'MTL', 'ZMW', 'VES', 'TRL', 'ILS', 'GHS', 'GYD', 'KPW', 'MDL', 'BOB', 'AMD', 'TRY', 'LBP', 'JOD', 'HKD', 'EUR', 'LSL', 'CAD', 'BOV', 'EEK', 'MUR', 'ROL', 'GIP', 'RON', 'NGN', 'CRC', 'PKR', 'ANG', 'SRD', 'TTD', 'LTL', 'SAR', 'MVR', 'SRG', 'INR', 'KRW', 'JPY', 'AOA', 'PLN', 'SBD', 'CSD', 'LUF', 'MWK', 'MGA', 'FIM', 'MGF', 'DEM', 'BAM', 'EGP', 'SSP', 'NIO', 'NZD', 'BRL'] // ------------------------- API ------------------------- let trackingEnabled = true; function disableTracking() { trackingEnabled = false; } function enableTracking() { trackingEnabled = true; } function getNumericPriceFromString(stringPrice) { const parsedPrice = stringPrice .replace(/\.$/, '') .replace(/([^.',\s\d])*/g, '') .replace(/([.',\s](?=\d{3}))/g, '') .replace(/([.',](?=\d{2}))/g, '.'); return Number(parsedPrice); } class TrackingExecutionError extends Error { constructor(message, trackingEntityType, variableId, triggerId, scriptId, trackingErrorType) { super(message); this.trackingEntityType = trackingEntityType; this.variableId = variableId; this.triggerId = triggerId; this.scriptId = scriptId; this.trackingErrorType = trackingErrorType; } } // ------------------------- helpers ------------------------- const eventTypes = Object.freeze({ PAGE_VISITED: "PAGE_VISITED", ADD_TO_CART: "ADD_TO_CART", REMOVE_FROM_CART: "REMOVE_FROM_CART", PDP_VISITED: "PDP_VISITED", PURCHASED: "PURCHASED", UPDATE_CART: "UPDATE_CART", DECLINE_TRACKING: "DECLINE_TRACKING", SEARCH: "SEARCH", SEARCH_RESULT: "SEARCH_RESULT", CLICKOUT: "CLICKOUT", LEAD_GEN: "LEAD_GEN" }); const trackingEventTypes = Object.freeze({ TRACKING_SUCCESSFUL_EXECUTION: 'TRACKING_SUCCESSFUL_EXECUTION', TRACKING_EXECUTION_FAILURE: 'TRACKING_EXECUTION_FAILURE' }) const actionTypes = Object.freeze({ ...eventTypes, CUSTOM: 'CUSTOM' }) const triggerTypes = Object.freeze({ CLICK: 'CLICK', INPUT: 'INPUT', PAGE_LOAD: 'PAGE_LOAD' }); const variableTypes = Object.freeze({ FUNCTION: 'FUNCTION', CONSTANT: 'CONSTANT' }); const trackingEntityTypes = Object.freeze({ VARIABLE: 'VARIABLE', TRIGGER: 'TRIGGER', CUSTOM_ACTION: 'CUSTOM_ACTION' }); const trackingErrorTypes = Object.freeze({ MISSING_VALUE: 'MISSING_VALUE', TYPE_MISMATCH: 'TYPE_MISMATCH', UNSUPPORTED_VARIABLE: 'UNSUPPORTED_VARIABLE', MISSING_VARIABLE: 'MISSING_VARIABLE', OTHER: 'OTHER' }); const trackingVariableScopes = Object.freeze({ GLOBAL: 'GLOBAL', LOCAL: 'LOCAL' }); const namedReferrals = Object.freeze({ SEARCH: 'SEARCH' }) const getElementAttribute = (target, attributeName) => { const attribute = target[attributeName]; if (typeof attribute === 'string') { return attribute; } if (attribute && attribute.baseVal !== undefined) { return attribute.baseVal; } return target.getAttribute(attributeName === 'className' ? 'class' : attributeName) || ''; }; const getElementId = (target) => { return getElementAttribute(target, 'id'); }; const getElementClassName = (target) => { return getElementAttribute(target, 'className'); }; const matchers = Object.freeze({ EQUALS: (a, b) => a === b, DOES_NOT_EQUAL: (a, b) => a !== b, CONTAINS: (a, b) => a.indexOf(b) >= 0, DOES_NOT_CONTAIN: (a, b) => a.indexOf(b) === -1, GREATER_THAN: (a, b) => a > b, LESS_THAN: (a, b) => a < b, GREATER_THAN_OR_EQUAL: (a, b) => a >= b, LESS_THAN_OR_EQUAL: (a, b) => a <= b, MATCHES_CSS_SELECTOR: (target, test) => target.matches(test), MATCHES_ID: (target, test) => getElementId(target) === test, CONTAINS_ID: (target, test) => getElementId(target).includes(test), DOES_NOT_CONTAIN_ID: (target, test) => !getElementId(target).includes(test), MATCHES_CLASS: (target, test) => getElementClassName(target) === test, CONTAINS_CLASS: (target, test) => getElementClassName(target).includes(test), DOES_NOT_CONTAIN_CLASS: (target, test) => !getElementClassName(target).includes(test), MATCHES_REGEX: (a, b) => parseRegexString(b).test(a), }); const trackingFieldName = `${domainId}_${zoovuId}_trackingExecutions` const MAX_RECORDS = 100 const DEBOUNCE_TIME = 1500 // helper to retrieve variableId later let eventFields = [] if (!JSON.parse(localStorage.getItem(trackingFieldName))) { localStorage.setItem(trackingFieldName, JSON.stringify([])) } function parseRegexString(input) { const trimmed = input.trim(); // check if it starts and ends with slashes (e.g., /^abc$/gi) const match = trimmed.match(/^\/(.+)\/([a-z]*)$/i); if (match) { const pattern = match[1]; const flags = match[2]; return new RegExp(pattern, flags); } // no flags return new RegExp(trimmed); } function checkValue(type, value) { switch (type) { case 'BOOLEAN': return value === true || value === 'true'; case 'TEXT': return value; case 'DECIMAL': return typeof value === 'string' ? parseFloat(value) : value; case 'INTEGER': return typeof value === 'string' ? parseInt(value) : value; default: return value; } } function cast(type, value) { switch (type) { case 'BOOLEAN': return value === true || value === 'true'; case 'TEXT': return value; case 'DECIMAL': return typeof value === 'string' ? parseFloat(value) : value; case 'INTEGER': return typeof value === 'string' ? parseInt(value) : value; default: return value; } } function debounce(fn, delay) { let lastCallTime = 0; let animationFrameId = null; let isScheduled = false; function execute(context, args, currentTime) { if (currentTime - lastCallTime >= delay) { fn.apply(context, args); isScheduled = false; } else { animationFrameId = requestAnimationFrame((newTime) => { execute(context, args, newTime); }); } } return function () { const context = this, args = arguments; lastCallTime = performance.now(); if (!isScheduled) { isScheduled = true; animationFrameId = requestAnimationFrame((currentTime) => { execute(context, args, currentTime); }); } }; } function getOrganization() { return zoovuId; } function getDomainId() { return domainId; } function getTimezone() { return Intl.DateTimeFormat().resolvedOptions().timeZone; } function getReferrer() { const referrer = document.referrer; if (/^(https?|android-app):\/\//i.test(referrer)) { return referrer; } else { return undefined; } } function getPath() { return window.location.href.replace(window.location.origin, ''); } function getCookieValue(cookieName) { const cookies = document.cookie.split('; '); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].split('='); if (cookie[0] === cookieName) { return cookie[1]; } } return null; } function generateUuid() { return self.crypto.randomUUID(); } function addZoovuCidToCookies() { const uuid = generateUuid(); const zoovuCid = `zoovu-cid=${uuid}; path=/`; document.cookie = zoovuCid; return uuid; } function getCID() { return getCookieValue(`zoovu-cid`) !== null ? getCookieValue(`zoovu-cid`) : addZoovuCidToCookies(); } function getEnvironment() { return currentEnvironment; } function getAccountId() { return currentAccountId; } function getPropertyTypeError(propertyName, expectedType, currentType) { return `TYPE MISMATCH: ${propertyName}: should be ${expectedType} but is ${currentType}` } function typeCheckValue(value, variableType, propertyName, variableId, triggerId) { let errorMessage = ''; if (value === undefined || value === null) { throw new TrackingExecutionError(`${propertyName}: value is not defined.`, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.MISSING_VALUE) } switch (variableType) { case "TEXT": if (typeof value !== 'string') errorMessage = getPropertyTypeError(propertyName, 'string', typeof value); break; case "INTEGER": case "DECIMAL": if (typeof value !== 'number') errorMessage = getPropertyTypeError(propertyName, 'number', typeof value); break; case "BOOLEAN": if (typeof value !== 'boolean') errorMessage = getPropertyTypeError(propertyName, 'boolean', typeof value); break; case 'LIST': if (!Array.isArray(value)) errorMessage = getPropertyTypeError(propertyName, 'list', typeof value); break; case 'EVENT': break; default: throw new TrackingExecutionError(`Not supported variable type: ${variableType}`, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.UNSUPPORTED_VARIABLE) } if (errorMessage) { throw new TrackingExecutionError(errorMessage, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.TYPE_MISMATCH) } } function ensureRequiredFieldsPresent(fields, eventType) { return Object.entries(fields).every(([key, value]) => { if (!value) { const variableId = eventFields.find(field => field.fieldName === key).variableId; // empty eventFields eventFields = []; throw new TrackingExecutionError( `Required property ${key} missing value for ${eventType}.`, trackingEntityTypes.VARIABLE, variableId, null, script.id, trackingErrorTypes.MISSING_VALUE ) } return true; }); } function getBaseEventBody(eventType) { return { origin: 'CLIENT', queryParams: {}, organization: getOrganization(), domainId: getDomainId(), path: getPath(), referrer: getReferrer(), cid: getCID(), timezone: getTimezone(), // dynamic eventType: eventType ?? '', eventLabel: '', }; } function getEventExecutable(actionType) { switch (actionType) { case actionTypes.PAGE_VISITED: return sendPageVisitedEvent; case actionTypes.ADD_TO_CART: return sendAddToCartEvent; case actionTypes.CLICKOUT: return sendClickoutEvent; case actionTypes.REMOVE_FROM_CART: return sendRemoveFromCartEvent; case actionTypes.PDP_VISITED: return sendPdpVisitedEvent; case actionTypes.PURCHASED: return sendPurchaseEvent; case actionTypes.DECLINE_TRACKING: return sendDeclineTrackingEvent; case actionTypes.UPDATE_CART: return sendUpdateCartEvent; case actionTypes.SEARCH: return sendSearchEvent; case actionTypes.SEARCH_RESULT: return sendSearchResultEvent; case actionTypes.LEAD_GEN: return sendLeadGenEvent; } } function checkSpecificFieldValues(fieldName, value, variableId) { if (fieldName === 'currencyCode' && !currencies.includes(value)) { throw new TrackingExecutionError( `Value ${value} is not compatible with currencyCode.`, trackingEntityTypes.VARIABLE, variableId, null, script.id, trackingErrorTypes.OTHER ) } if (fieldName === 'namedReferral' && !namedReferrals[value.toUpperCase()]) { throw new TrackingExecutionError( `Value ${value} is not compatible with namedReferral.`, trackingEntityTypes.VARIABLE, variableId, null, script.id, trackingErrorTypes.OTHER ) } } function getVariableValueById(variableId, event, fieldName, triggerId) { const foundVariable = variables.find(v => v.id === variableId); let variableValue = null; if (foundVariable) { if (foundVariable.type === variableTypes.CONSTANT) { variableValue = cast(foundVariable.valueType, foundVariable.value); } else if (foundVariable.type === variableTypes.FUNCTION && typeof foundVariable.function === 'function') { try { variableValue = foundVariable.function(event); } catch (e) { throw new TrackingExecutionError( e.message, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.OTHER ) } } else { throw new TrackingExecutionError( `${foundVariable.type} is not supported.`, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.UNSUPPORTED_VARIABLE ) } typeCheckValue(variableValue, foundVariable.valueType, fieldName ? fieldName : foundVariable.name, variableId, triggerId); if (fieldName === 'currencyCode' || fieldName === 'namedReferral') { checkSpecificFieldValues(fieldName, variableValue, variableId) } return variableValue; } else { throw new TrackingExecutionError( `No variable with ID ${variableId}`, trackingEntityTypes.VARIABLE, variableId, triggerId, script.id, trackingErrorTypes.MISSING_VARIABLE ) } } function evaluateSingleTriggerRow(row, event, triggerId) { const target = getVariableValueById(row.variableId, event, undefined, triggerId); const matcher = matchers[row.operator]; checkValue(row.valueType, row.value); const value = cast(row.valueType, row.value); if (matcher && typeof matcher === 'function') { return matcher(target, value); } return false; } function preparePayloadFromFields(fields, event) { const payload = {}; fields.forEach(f => { payload[f.fieldName] = getVariableValueById(f.variableId, event, f.fieldName) }) return payload; } function evaluateTriggerConditions(trigger, event) { // OR between groups return trigger.groups.some(group => // AND between rows group.rows.every(row => evaluateSingleTriggerRow(row, event, trigger.id))) } function runAction(action, fields, event, trigger) { const trackingExecutions = jsonParser(trackingFieldName) if (action.type === actionTypes.CUSTOM && typeof action.code === 'function') { // add script custom action trackingExecutions.push(createTrackingSuccessfulExecutionRecord(trackingEntityTypes.CUSTOM_ACTION, action.id)) try { action.code(event); } catch (e) { throw new TrackingExecutionError( e.message, trackingEntityTypes.CUSTOM_ACTION, action.id, null, script.id, trackingErrorTypes.OTHER ) } localStorage.setItem(trackingFieldName, JSON.stringify(trackingExecutions)); } else { const sendEventFunction = getEventExecutable(action.type); eventFields = [...fields]; if (sendEventFunction && typeof sendEventFunction === 'function') { const payload = preparePayloadFromFields(fields, event) sendEventFunction(payload); addSuccessfulExecutions(trigger, fields) } } } function evaluateSingleRule(rule, event) { if (evaluateTriggerConditions(rule.trigger, event)) { runAction(rule.action, rule.fields, event, rule.trigger); } } function evaluateRules(rules, event) { try { rules.forEach(rule => { evaluateSingleRule(rule, event) }); } catch (error) { const trackingExecutions = jsonParser(trackingFieldName); const {message, trackingEntityType, variableId, triggerId, scriptId, trackingErrorType} = error; const failedExecution = createTrackingFailedExecutionRecord( trackingEntityType, variableId, triggerId, scriptId, trackingErrorType, message ) trackingExecutions.push(failedExecution) localStorage.setItem(trackingFieldName, JSON.stringify(trackingExecutions)); console.debug(error) } } function observeAndReactOnPageChange(callback) { let oldHref; if (oldHref === undefined) { callback(); oldHref = document.location.href; } const body = document.querySelector('body'); const observer = new MutationObserver(() => { if (oldHref !== document.location.href) { oldHref = document.location.href; callback(); } }); observer.observe(body, {childList: true, subtree: true}); } function executeAdvancedCode() { if (typeof advancedCode === 'function') { advancedCode(); } } function jsonParser(key) { const foundValue = JSON.parse(localStorage.getItem(key)) if (!Array.isArray(foundValue)) { throw Error('Invalid value in localStorage for key ' + key) } return foundValue } function createTrackingSuccessfulExecutionRecord(entityType, entityId) { const executionTime = Date.now(); return { organization: getOrganization(), domainId: getDomainId(), eventType: trackingEventTypes.TRACKING_SUCCESSFUL_EXECUTION, trackingEntityType: entityType, trackingEntityId: entityId, executionTime } } function createTrackingFailedExecutionRecord(entityType, entityId, triggerId, scriptId, errorType, message) { const executionTime = Date.now(); return { organization: getOrganization(), domainId: getDomainId(), eventType: trackingEventTypes.TRACKING_EXECUTION_FAILURE, trackingEntityType: entityType, trackingEntityId: entityId, executionTime, triggerId: triggerId || null, scriptId: scriptId || null, error: { type: errorType, message } } } function addSuccessfulExecutions(trigger, fields) { const successfulExecutions = jsonParser(trackingFieldName) // add script trigger successfulExecutions.push(createTrackingSuccessfulExecutionRecord(trackingEntityTypes.TRIGGER, trigger.id)) // add script function variables fields.forEach(field => { const foundVariableInField = variables.find(variable => variable.id === field.variableId) if (foundVariableInField.type === variableTypes.FUNCTION && foundVariableInField.scope === trackingVariableScopes.LOCAL) { successfulExecutions.push(createTrackingSuccessfulExecutionRecord(trackingEntityTypes.VARIABLE, foundVariableInField.id)) } }) // add trigger function variables trigger.groups.forEach(groups => { groups.rows.forEach(row => { const foundVariable = variables.find(variable => variable.id === row.variableId) if (foundVariable.type === variableTypes.FUNCTION && foundVariable.scope === trackingVariableScopes.LOCAL) { successfulExecutions.push(createTrackingSuccessfulExecutionRecord(trackingEntityTypes.VARIABLE, foundVariable.id)) } }) }) localStorage.setItem(trackingFieldName, JSON.stringify(successfulExecutions)); } // ------------------------- events ------------------------- async function sendEvent(body) { if (trackingEnabled) { await fetch(`${url}/fact`, { method: 'POST', mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(body), }); } else { console.debug("Tracking disabled - no permission to track"); } } async function sendSSTRPurchaseEvent(body) { if (trackingEnabled) { const purchaseUrl = 'https://ev-co.zoovu.com/v1/CollectSalesEvent'; await fetch(purchaseUrl, { method: 'POST', mode: 'cors', cache: 'no-cache', headers: { 'Content-Type': 'application/json', }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(body), }); } else { console.debug("Tracking disabled - no permission to track"); } } async function sendTrackingSuccessfulExecution(body) { if (trackingEnabled) { await fetch(`${url}/tracking/executions`, { method: 'POST', mode: 'cors', cache: 'no-cache', headers: { 'Content-Type': 'application/json', }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(body), }); } else { console.debug("Tracking disabled - no permission to track"); } } function sendFactEventBase(eventType, eventSpecificBody) { const body = { ...getBaseEventBody(eventType), // event label + custom per-event fields ...eventSpecificBody, }; sendEvent(body); }; function sendPageVisitedEvent({locale, category, eventLabel = 'Page visit'}) { const body = { locale, eventLabel, // optional category, }; if (ensureRequiredFieldsPresent({locale}, eventTypes.PAGE_VISITED)) { sendFactEventBase(eventTypes.PAGE_VISITED, body); } }; function sendPdpVisitedEvent({ locale, sku, quantity = 1, currencyCode, eventLabel = "Product details page visit", price, category }) { const body = { locale, sku, eventLabel, // optional category, price, currencyCode, quantity, }; if (ensureRequiredFieldsPresent({locale, sku}, eventTypes.PDP_VISITED)) { sendFactEventBase(eventTypes.PDP_VISITED, body); } }; function sendAddToCartEvent({ locale, sku, quantity = 1, currencyCode, eventLabel = "Add to cart", price, category }) { const body = { locale, sku, eventLabel, // optional category, price, currencyCode, quantity, }; if (ensureRequiredFieldsPresent({locale, sku}, eventTypes.ADD_TO_CART)) { sendFactEventBase(eventTypes.ADD_TO_CART, body); } }; function sendRemoveFromCartEvent({ locale, sku, quantity = 1, currencyCode, eventLabel = "Remove from cart", price, category }) { const body = { locale, sku, eventLabel, // optional category, price, currencyCode, quantity, }; if (ensureRequiredFieldsPresent({locale, sku}, eventTypes.REMOVE_FROM_CART)) { sendFactEventBase(eventTypes.REMOVE_FROM_CART, body); } }; function sendUpdateCartEvent({ locale, sku, quantity = 1, currencyCode, eventLabel = "Update cart", price, category }) { const body = { locale, sku, eventLabel, // optional category, price, currencyCode, quantity, }; if (ensureRequiredFieldsPresent({locale, sku}, eventTypes.UPDATE_CART)) { sendFactEventBase(eventTypes.UPDATE_CART, body); } }; function sendDeclineTrackingEvent({ locale, eventLabel = "No permission to track", category }) { const body = { locale, eventLabel, // optional category }; if (ensureRequiredFieldsPresent({locale}, eventTypes.DECLINE_TRACKING)) { sendFactEventBase(eventTypes.DECLINE_TRACKING, body); disableTracking(); } }; function sendSearchEvent({ locale, eventLabel = "Search phrase typed", category }) { const body = { locale, eventLabel, // optional category, }; if (ensureRequiredFieldsPresent({locale}, eventTypes.SEARCH)) { sendFactEventBase(eventTypes.SEARCH, body); } }; function sendSearchResultEvent({ locale, isEmpty = false, eventLabel = "Search results", skus, category }) { const body = { locale, isEmpty, skus, eventLabel, // optional category }; if (ensureRequiredFieldsPresent({locale, skus}, eventTypes.SEARCH_RESULT)) { sendFactEventBase(eventTypes.SEARCH_RESULT, body); } }; function sendClickoutEvent({ locale, targetUrl, namedReferral, eventLabel = "Clickout", category }) { const body = { locale, targetUrl, namedReferral, eventLabel, // optional category }; if (ensureRequiredFieldsPresent({locale, targetUrl, namedReferral}, eventTypes.CLICKOUT)) { sendFactEventBase(eventTypes.CLICKOUT, body); } }; function sendPurchaseEvent({ currencyCode, transactionId, products }) { const sstrBody = { transactionId, products, currency: currencyCode, browserTimestamp: Date.now(), env: getEnvironment(), accountId: getAccountId(), clientId: getCID(), }; if (ensureRequiredFieldsPresent({products, currencyCode,}, eventTypes.PURCHASED)) { sendSSTRPurchaseEvent(sstrBody); } }; function sendLeadGenEvent({ locale, currencyCode, products, leadId, leadType, category, eventLabel = "Lead gen sent" }) { const body = { locale, eventLabel, // optional currencyCode, products, leadId, leadType, category }; if (ensureRequiredFieldsPresent({locale}, eventTypes.LEAD_GEN)) { sendFactEventBase(eventTypes.LEAD_GEN, body); } }; function sendSuccessfulExecutionEvent(forceSend) { const successfulExecutions = jsonParser(trackingFieldName) if (successfulExecutions.length === MAX_RECORDS || (forceSend && successfulExecutions.length > 0)) { sendTrackingSuccessfulExecution(successfulExecutions) localStorage.setItem(trackingFieldName, JSON.stringify([])) } } // ------------------------- core ------------------------- function reactOnLoad() { const pageLoadRules = script.rows.filter(row => row.trigger.type === triggerTypes.PAGE_LOAD); window.addEventListener("load", (event) => { observeAndReactOnPageChange(() => evaluateRules(pageLoadRules, event) && sendSuccessfulExecutionEvent()) }, {capture: true}); } function reactOnClick() { const clickRules = script.rows.filter(row => row.trigger.type === triggerTypes.CLICK); // click via mouse document.querySelector('body').addEventListener('mousedown', (event) => { evaluateRules(clickRules, event); sendSuccessfulExecutionEvent() }, {capture: true}); // click via enter button document.querySelector('body').addEventListener('keydown', (event) => { if (event.code === "Enter" || event.code === "NumpadEnter") { evaluateRules(clickRules, event); sendSuccessfulExecutionEvent() } }, {capture: true}); } function reactOnInput() { const inputRules = script.rows.filter(row => row.trigger.type === triggerTypes.INPUT); document.querySelector('body').addEventListener('input', debounce(function (event) { evaluateRules(inputRules, event); sendSuccessfulExecutionEvent() }, DEBOUNCE_TIME), {capture: true}); } function reactOnMouseLeave() { document.addEventListener("mouseleave", function (event) { if (event.clientY <= 0 || event.clientX <= 0 || (event.clientX >= window.innerWidth || event.clientY >= window.innerHeight)) { sendSuccessfulExecutionEvent(true) } }); } function track() { try { executeAdvancedCode(); reactOnLoad(); reactOnClick(); reactOnInput(); reactOnMouseLeave(); } catch (error) { console.debug("Tracking disabled", error); } } // RUN SCRIPT AFTER PAGE LOAD if (document.readyState === "loading" || document.readyState === "interactive") { // Loading hasn't finished yet document.addEventListener("readystatechange", (event) => { if (event.target.readyState === "complete") { track(); } }); } else { track(); } })();