function runScript() { try { // CHECK PERMISSION (function checkPermission() { const permissionRegexes = [/C0001:(\d)/, /C0002:(\d)/, /C0003:(\d)/, /C0004:(\d)/]; const groupsCookie = document.cookie.split('&').find(row => row.startsWith('groups=')); if (!groupsCookie) { throw new Error("No permission, upssss there is no cookies yet"); } const groupsValue = groupsCookie.match(/groups=([^;]*)/); for (let regex of permissionRegexes) { const permissionMatch = decodeURIComponent(groupsValue[1]).match(regex); if (!permissionMatch || permissionMatch[1] === '0') { throw new Error("No permission"); } } return; })(); const organization = document .querySelector('script[data-zoovuid]') .getAttribute('data-zoovuid'); const domainId = () => { const src = document .querySelector('script[data-zoovuid]') .getAttribute('src') const parts = src.split('/'); return parts[parts.length - 2]; } const eventBody = { organization: organization, domainId: domainId(), eventLabel: '', queryParams: {}, origin: 'CLIENT', }; const selectedCardsList = []; function getReferrer() { const referrer = document.referrer; if (/^(https?|android-app):\/\//i.test(referrer)) { return referrer; } else { return undefined; } } async function sendEvent(body) { const url = "https://queue-propagator.zoovu.com/fact"; // !!REMEMBER!! to set proper environment await fetch(url, { method: 'POST', mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(body), }); } async function sendPurchaseEvent(body) { const url = 'https://ev-co.zoovu.com/v1/CollectSalesEvent'; await fetch(url, { method: 'POST', mode: 'cors', cache: 'no-cache', headers: { 'Content-Type': 'application/json', }, redirect: 'follow', referrerPolicy: 'no-referrer', body: JSON.stringify(body), }); } //_________________________HELPER FUNCTIONS_________________________ 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(); } const addZoovuCidToCookies = () => { const uuid = generateUuid() const zoovuCid = `zoovu-cid=${uuid}; path=/` document.cookie = zoovuCid return uuid; } // GET ITEM PRICE const assignItemPriceFromCard = (parenElement) => { if (parenElement === null) { return; } // Extract the numbers (including decimal points, commas, and apostrophes) const numbers = parenElement.textContent.match(/[\d.,’]+/g).join(''); // Remove currency symbols and spaces const cleanedNumbers = numbers.replace(/kr|Fr\.|\s/g, ''); // Replace apostrophes and commas with nothing (removing them), then replace dots with nothing if they are used for thousand separators const price = cleanedNumbers.replace(/[’,]/g, "").replace(/(\d)\.(\d{3})/g, "$1$2"); // If the price starts with a dot, remove it const finalPrice = price.startsWith('.') ? price.slice(1) : price; eventBody["price"] = finalPrice; }; const assignItemSKU = (parenElement) => { if (parenElement === undefined) { eventBody['sku'] = 'No SKU available'; return; } const sku = parenElement.getAttribute('data-clipboard'); eventBody['sku'] = sku; }; // ADD MISSED FIELDS TO EVENTOBJECT function addMissingFieldsToEventObject() { const path = window.location.href.replace(window.location.origin, ''); const cid = getCookieValue(`zoovu-cid`) !== null ? getCookieValue(`zoovu-cid`) : addZoovuCidToCookies(); eventBody['cid'] = cid; eventBody['path'] = path; eventBody['timezone'] = Intl.DateTimeFormat().resolvedOptions().timeZone; eventBody['locale'] = document.querySelector("html[lang]")?.getAttribute('lang'); eventBody['currencyCode'] = document.querySelector("main[data-currency-iso-code]")?.getAttribute('data-currency-iso-code'); eventBody['referrer'] = getReferrer(); } // Distinguish which type of page was visited and sent event function handlePageVisited() { const isPDP = window.location.href.replace(window.location.origin, '').includes('/p/') && document.querySelector('body').className.includes('variantProductDetails'); if (isPDP) { assignItemPriceFromCard(document.querySelector('.productVariant__summary__price-row__price')); assignItemSKU(document.querySelector('.js-product-details-code')) eventBody['eventType'] = 'PDP_VISITED'; eventBody['eventLabel'] = 'Product details page visit'; } else { eventBody['eventType'] = 'PAGE_VISITED'; eventBody['eventLabel'] = 'Page visit'; if (window.location.href.includes('checkout')) { eventBody['eventLabel'] = eventBody.eventLabel.concat(', ', 'Checkout'); } if (window.location.href.includes('cart')) { eventBody['eventLabel'] = eventBody.eventLabel.concat(', ', 'Shopping cart'); } } sendEvent(eventBody); // new search version if (document.querySelector('.searchEmptyPageTop-component') !== null) { sendEvent({ ...eventBody, isEmpty: true, eventType: 'SEARCH_RESULT', eventLabel: 'Empty search result page' }); } // old search version if (document.querySelector('.ss360-no-results') !== null) { sendEvent({ ...eventBody, isEmpty: true, eventType: 'SEARCH_RESULT', eventLabel: 'Empty search result page' }); } } // Helper functions for assigning and sending events const assignAndSendEvent = (eventType, price, eventBody, eventLabel) => { eventBody['eventType'] = eventType; eventBody['eventLabel'] = eventLabel; assignItemPriceFromCard(price) sendEvent(eventBody) } const addToCartClickout = (eventBody, eventLabel) => { const { sku, price, quantity, ...pureBody } = eventBody; sendEvent({ ...pureBody, eventType: 'CLICKOUT', eventLabel, namedReferral: 'Search', targetUrl: window.location.href.replace(window.location.origin, '') }); } //_________________________EVENT HANDLERS_________________________ const handleTrackingDecline = (event) => { if (event.target.className === "save-preference-btn-handler onetrust-close-btn-handler" ) { const permissionCheckbox = document.querySelectorAll(".ot-switch-nob"); for (let checkbox = 0; checkbox < permissionCheckbox.length; checkbox++) { if (permissionCheckbox[checkbox].getAttribute("aria-checked") === "false") { addMissingFieldsToEventObject() eventBody["eventType"] = "DECLINE_TRACKING"; eventBody["eventLabel"] = "No permission to track"; sendEvent(eventBody); throw new Error("No permission to track user data."); } } return; } } // ADD EVENT LISTENER TO INPUTS IN SHOPPING CART const addEventListenerToInputsShoppingCart = () => { try { new Promise((resolve) => { const observer = new MutationObserver(() => { const inputs = document.querySelectorAll('input[name="quantity"][class="quantity js-update-entry-quantity-input qty"]'); if (inputs.length > 0) { for (const input of inputs) { let oldValue = Number(input.value); const parentCard = input.closest('.item__description-wrapper') const priceElement = parentCard.querySelector('div[class="item__price item__price--cart"]') const addOrRemoveEvent = () => { const newValue = Number(input.value) if (newValue !== oldValue) { assignItemPriceFromCard(priceElement); assignItemSKU(parentCard.querySelector('.smg-producttile-code')) eventBody['eventType'] = 'UPDATE_CART' eventBody['eventLabel'] = 'Update cart'; eventBody['quantity'] = newValue - oldValue; sendEvent(eventBody); oldValue = newValue; } else { return } } input.addEventListener('input', () => { setTimeout(() => { addOrRemoveEvent() }, 1000); }); } observer.disconnect(); return resolve(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } catch (error) { console.debug("Input in shopping cart - DOM change error", error) } } // ADD EVENT LISTENER TO SEARCH INPUTS const addEventListenerToSearch = () => { try { new Promise((resolve) => { const observer = new MutationObserver(() => { const search = document.querySelector('input[id="js-site-search-input"]'); if (search !== null) { let oldValue = search.value; const sendSearchEvent = () => { const newValue = search.value if (newValue !== oldValue && newValue !== '') { eventBody['eventType'] = 'SEARCH' eventBody['eventLabel'] = 'Search phrase typed'; sendEvent(eventBody); if (!(document.querySelectorAll('.product-result').length > 0 || document.querySelectorAll('.unibox__selectable').length > 0)) { sendEvent({ ...eventBody, isEmpty: true, eventType: 'SEARCH_RESULT', eventLabel: 'Empty search result popup' }); } oldValue = newValue; } else { return } } search.addEventListener('input', () => { setTimeout(() => { sendSearchEvent() }, 2500); }); observer.disconnect(); return resolve(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } catch (error) { console.debug("Search - error occured", error) } } // ADD EVENT LISTENER TO PRODUCT RESULTS FROM PLP -> new search version const addEventListenerToPLPSearchResults = () => { try { new Promise((resolve) => { const observer = new MutationObserver(() => { const productCards = document.querySelectorAll('.producttile '); if (productCards.length > 0 && document.querySelector("#searchHeadline") !== null) { for (const product of productCards) { const namedReferral = 'Search'; const sendClickoutEvent = (event) => { const targetUrl = product.getAttribute("data-producturl"); const label = event.which === 1 ? 'Go to PDP - search clickout' : "Right click PLP" eventBody['eventType'] = 'CLICKOUT'; eventBody['eventLabel'] = label; sendEvent({ ...eventBody, targetUrl, namedReferral }); } product.addEventListener('mousedown', (event) => { if (event.target.className === 'addToCartForm' || event.target.closest('form')?.className === "addToCartForm") { return } sendClickoutEvent(event) }); } observer.disconnect(); return resolve(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } catch (error) { console.debug("Search result product item - error", error) } } const handleProductSearchResultsClickout = (event) => { try { if (event.target.closest('li')?.className === "product-result" || event.target.closest('article')?.className === "unibox__selectable") { if (event.target.className === 'searchResultsAddToCartForm' || event.target.closest('form')?.className === "searchResultsAddToCartForm") { return } const namedReferral = 'Search'; const targetUrl = event.target.closest('li')?.getAttribute("data-url") || event.target.closest('article')?.getAttribute("data-href"); const label = event.which === 1 ? 'Go to PDP - search clickout' : "Right click popup" eventBody['eventType'] = 'CLICKOUT'; eventBody['eventLabel'] = label; sendEvent({ ...eventBody, targetUrl, namedReferral }); } } catch (error) { console.debug("Clickout on search result", error) } } const handleAddToCartByPressingAddButtonProductList = (event) => { try { if (event.target.id === "variantAddToCartIcon" || event.target.parentElement.id.includes('addToCartButton') || event.target.id.includes('addToCartButton')) { const parentCard = event.target.closest('.smg-producttile-content') const priceElement = parentCard.querySelector('div[class="smg-producttile-price smg-producttile-price-all-product "]') assignItemSKU(parentCard.querySelector('.smg-producttile-code')) const quantity = parentCard.querySelector('input[name="qty"][class="quantity "]').value eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; eventBody['quantity'] = Number(quantity); assignItemPriceFromCard(priceElement) sendEvent(eventBody); } } catch (error) { console.debug("Add to cart button, product list - DOM change error", error) } } const handleAddToCartFromSearch = (event) => { try { if (event.target.className.includes("searchAddToCartLabel") || event.target.children[0]?.className.includes('searchAddToCartLabel')) { eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; let parentCard; let quantity; let priceElement; // new search version if (event.target.closest('.product-result') !== null) { parentCard = event.target.closest('.product-result'); priceElement = parentCard.querySelector('.price') assignItemSKU(parentCard.querySelector('.ref')) quantity = Number(parentCard.querySelector('input[name="qty"][class="quantity "]').value) } else { // old search version parentCard = event.target.closest('article'); priceElement = parentCard.querySelector('.price') assignItemSKU(parentCard.querySelector('.ref')) quantity = Number(parentCard.querySelector('input[name="qty"][class="quantity"]').value) } if (parentCard.querySelector('.price') !== null) { assignItemPriceFromCard(priceElement); } sendEvent({ ...eventBody, quantity }); // CLICKOUT addToCartClickout(eventBody, 'Clickout, add product from search result'); } } catch (error) { console.debug("Add to cart button, search - error", error) } } const handleAddToCartByPressingAddButtonPDPPage = (event) => { try { if ((event.target.parentElement.className === "addToCartForm addToCartForm__variantPDP" && event.target.type === "submit") || (event.target.parentElement.parentElement.className === "addToCartForm addToCartForm__variantPDP" && event.target.parentElement.type === "submit")) { let quantity; if (event.target.parentElement.parentElement.parentElement.className.includes('sticky')) { quantity = event.target.parentElement.className === "addToCartForm addToCartForm__variantPDP" ? event.target.previousElementSibling.children[1].value : event.target.parentElement.previousElementSibling.children[1].value } else { quantity = event.target.parentElement.className === "addToCartForm addToCartForm__variantPDP" ? event.target.parentElement.children[3].children[1].value : event.target.parentElement.parentElement.children[3].children[1].value; } eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; eventBody['quantity'] = Number(quantity); assignItemPriceFromCard(document.querySelector('.productVariant__summary__price-row__price')); assignItemSKU(document.querySelector('.js-product-details-code')) sendEvent(eventBody); } } catch (error) { console.debug("Add to cart PDP - DOM change error", error) } } const handleAddRecommendedProducts = (event) => { try { if ((event.target.closest('form')?.getAttribute('data-location_id') === 'PDP_OftenCombined_Caroussel' || event.target.closest('form')?.getAttribute('data-location') === 'Category') && (event.target.className === ('glyphicon glyphicon-shopping-cart') || event.target.previousElementSibling.className === ('glyphicon glyphicon-shopping-cart') || event.target.className === ('btn btn-block btn-secondary waves-effect waves-light'))) { const parentCard = event.target.closest('.producttile__content') const priceElement = parentCard.querySelector('.producttile__price') assignItemSKU(parentCard.querySelector('.producttile__code')) const quantity = parentCard.querySelector('input[name="qty"][class="quantity "]').value eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; eventBody['quantity'] = Number(quantity); assignItemPriceFromCard(priceElement) sendEvent(eventBody); } } catch (error) { console.debug("Add to cart, recommended products - DOM change error", error) } } const handleAddProductsFromSearchResultPage = (event) => { try { if ((event.target.closest('form')?.getAttribute('data-location_id') === 'Search_Results_Page') && (event.target.className === ('glyphicon glyphicon-shopping-cart') || event.target.previousElementSibling.className === ('glyphicon glyphicon-shopping-cart') || event.target.className === ('btn btn-block btn-secondary waves-effect waves-light'))) { const parentCard = event.target.closest('.producttile ') const priceElement = parentCard.querySelector('.producttile__price') assignItemSKU(parentCard.querySelector('.producttile__code')) const quantity = Number(parentCard.querySelector('input[name="qty"][class="quantity "]').value) eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; assignItemPriceFromCard(priceElement) sendEvent({ ...eventBody, quantity }); addToCartClickout(eventBody, 'Clickout, add product from PLP search result'); } } catch (error) { console.debug("Add to cart, search result products - error", error) } } const handleAddProductsFromSearchResultPageOldVersion = (event) => { try { if ((event.target.closest('form')?.getAttribute('data-location_id') === 'Zoovu_Search') && (event.target.className === ('glyphicon glyphicon-shopping-cart') || event.target.previousElementSibling.className === ('glyphicon glyphicon-shopping-cart') || event.target.className === ('btn btn-block btn-secondary waves-effect waves-light'))) { const parentCard = event.target.closest('.producttile__content') const priceElement = parentCard.querySelector('.producttile__price') assignItemSKU(parentCard.querySelector('.producttile__code')) const quantity = Number(parentCard.querySelector('input[name="qty"][class="quantity"]').value) eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; if (priceElement !== null) { assignItemPriceFromCard(priceElement) } sendEvent({ ...eventBody, quantity }); if (document.querySelector("#ss360-layer") !== null && document.querySelector("#searchHeadline") !== null) { addToCartClickout(eventBody, 'Clickout, add product from PLP search result'); } } } catch (error) { console.debug("Add to cart, search result products - error", error) } } const handleAddProductPlusButton = (event) => { try { if (event.target.className === "increase-quantity" && event.target.closest('form').id?.includes('updateCartForm')) { const parentCard = event.target.closest(".item__description-wrapper") const priceElement = parentCard.querySelector('div[class="item__price item__price--cart"]') assignItemSKU(parentCard.querySelector('.smg-producttile-code')); eventBody['quantity'] = 1; assignAndSendEvent('UPDATE_CART', priceElement, eventBody, 'Update cart, add item') } } catch (error) { console.debug("Add to cart, plus button - DOM change error", error) } } const handleAddToCartByInput = (event) => { try { if (event.target.className === "quantity ") { const isPDPInput = event.target.closest('form').className.includes('variantPDP') let priceElement if (isPDPInput) { const parent = event.target.closest('.productVariant__summary__price-row') priceElement = parent.querySelector('div[class="productVariant__summary__price-row__price"]') assignItemSKU(document.querySelector('.js-product-details-code')) } else { const parentCard = event.target.closest('.smg-producttile-content') priceElement = parentCard.querySelector('div[class="smg-producttile-price smg-producttile-price-all-product "]') assignItemSKU(parentCard.querySelector('.smg-producttile-code')) } const quantity = event.target.value eventBody['eventType'] = 'ADD_TO_CART'; eventBody['eventLabel'] = 'Add to cart'; eventBody['quantity'] = Number(quantity); assignItemPriceFromCard(priceElement) sendEvent(eventBody); } } catch (error) { console.debug("Add to cart button, product list - DOM change error", error) } } const handleRemoveProductMinusButton = (event) => { try { if (event.target.className === "decrease-quantity" && event.target.closest('form').id?.includes('updateCartForm')) { const parentCard = event.target.closest(".item__description-wrapper") const priceElement = parentCard.querySelector('div[class="item__price item__price--cart"]') eventBody['quantity'] = -1; assignItemSKU(parentCard.querySelector('.smg-producttile-code')); assignAndSendEvent('UPDATE_CART', priceElement, eventBody, 'Update cart, remove item'); } } catch (error) { console.debug("Remove product, minus button - DOM change error", error) } } const handleRemoveCard = (event) => { try { if (event.target.className === "icon-trash" || event.target.className.includes('smg-remove-entry')) { const parentCard = event.target.closest('.item__description-wrapper') const priceElement = parentCard.querySelector('div[class="item__price item__price--cart"]') assignItemSKU(parentCard.querySelector('.smg-producttile-code')) const quantity = parentCard.querySelector('input[name="quantity"]').value eventBody['eventType'] = 'REMOVE_FROM_CART'; eventBody['eventLabel'] = 'Remove from cart'; eventBody['quantity'] = Number(quantity); assignItemPriceFromCard(priceElement) sendEvent(eventBody); } } catch (error) { console.debug("Remove a cart - DOM change error", error) } } const handleSelectCardFromCart = (event) => { try { if (event.target.className === "smg-checkbox" || event.target.parentElement.className === "smg-checkbox") { let selectedId; if (event.target.className === "smg-checkbox") { selectedId = event.target.children[0].getAttribute('id') } else if (event.target.type === 'checkbox') { selectedId = event.target.id; } else if (event.target.localName === 'label') { selectedId = event.target.htmlFor; } const isElementSelected = !!selectedCardsList.find(el => el === selectedId) if (isElementSelected) { selectedCardsList.splice(selectedCardsList.indexOf(selectedId), 1); } else { selectedCardsList.push(selectedId) } } } catch (error) { console.debug("Select a cart - DOM change error", error) } } const handleRemoveAll = (event) => { try { if (event.target.className === "remove-all" || event.target.className === "js-smg-cart-clearall icon-trash" || event.target.className === 'remove-selected') { if (selectedCardsList.length === 0) { const cardList = document.querySelectorAll('.item__list--item.item__list--cart-item.smg-cartitem.smg-cartitem-straumann') for (let card = 0; card < cardList.length; card++) { const priceElement = cardList[card].querySelector('.item__price.item__price--cart') const quantity = cardList[card].querySelector('input[name="quantity"]').value assignItemSKU(cardList[card].querySelector('.smg-producttile-code')); assignItemPriceFromCard(priceElement); eventBody['eventType'] = 'REMOVE_FROM_CART'; eventBody['eventLabel'] = 'Remove from cart'; eventBody['quantity'] = Number(quantity); sendEvent(eventBody); } } else { selectedCardsList.map(id => { const card = document.querySelector(`#${id}`) const price = JSON.parse(card.getAttribute('data-cart')).productPostPrice; const sku = card.getAttribute('data-entry-product-code'); eventBody['eventType'] = 'REMOVE_FROM_CART'; eventBody['eventLabel'] = 'Remove from cart'; eventBody['price'] = price; eventBody['quantity'] = Number(card.getAttribute('data-entry-initial-quantity')); eventBody['sku'] = sku; sendEvent(eventBody); }) } } } catch (error) { console.debug("Remove all products from cart - DOM change error", error) } } const handlePurchase = () => { try { if (document.location.href.includes("orderConfirmation")) { if (localStorage.getItem('order') === null) { return } const trackPurchaseObject = {}; const cid = getCookieValue(`zoovu-cid`) !== null ? getCookieValue(`zoovu-cid`) : addZoovuCidToCookies(); trackPurchaseObject['products'] = JSON.parse(localStorage.getItem('order')); trackPurchaseObject['currency'] = document.querySelector("main[data-currency-iso-code]").getAttribute('data-currency-iso-code'); trackPurchaseObject['env'] = "orca"; trackPurchaseObject['accountId'] = "250000008"; trackPurchaseObject['browserTimestamp'] = Date.now(); trackPurchaseObject['clientId'] = cid; const parts = document.location.href.split('/'); trackPurchaseObject['transactionId'] = parts[parts.length - 1]; sendPurchaseEvent(trackPurchaseObject); window.localStorage.removeItem('order'); } } catch (error) { console.debug("Purchase - DOM change error", error) } } const handleSaveOrderInLocalStorage = (event) => { try { if (event.target.className.includes('checkoutSummaryButton')) { const products = []; const productsCards = document.querySelectorAll('.checkout-order-summary-list-items'); for (const product of productsCards) { const productObj = {} productObj['sku'] = product.querySelector('.sku').textContent.replace("REF", "") productObj['name'] = product.querySelector('.name').textContent productObj['price'] = parseFloat(product.querySelector('.baseprice').textContent.match(/[\d.,]+/)[0]); productObj['quantity'] = parseFloat(product.querySelector('.qty ').textContent.replace("×", "")) productObj['unit'] = 'unit'; products.push(productObj) } window.localStorage.setItem('order', JSON.stringify(products)); } } catch (error) { console.debug("Save order in local storage - DOM change error", error) } } const observeAndReactOnPageChange = () => { try { let oldHref; if (oldHref === undefined) { addMissingFieldsToEventObject(); handlePageVisited(); oldHref = document.location.href; } const body = document.querySelector('body'); const observer = new MutationObserver(() => { if (oldHref !== document.location.href) { oldHref = document.location.href; addMissingFieldsToEventObject(); handlePageVisited(); } }); observer.observe(body, { childList: true, subtree: true }); } catch (error) { console.debug("Page change - DOM change error", error) } }; const handleOnEnterSearch = (event) => { try { if (event.target.id === "js-site-search-input") { eventBody['eventType'] = 'SEARCH' eventBody['eventLabel'] = 'Search phrase typed'; sendEvent(eventBody); } } catch (error) { console.debug("On enter search event", error) } } const handleViewAllClickout = (event) => { try { if (event.target.className === "smg-search-showmore btn btn-primary" || event.target.className.includes("unibox__selectable--show-all") || event.target.closest("button")?.className.includes("unibox__selectable--show-all")) { const searchTerm = document.querySelector('input[id="js-site-search-input"]').value const { sku, price, quantity, ...pureBody } = eventBody; const localeBaseUrl = document.location.pathname.split('/').slice(1, 3).join('/'); sendEvent({ ...pureBody, eventType: 'CLICKOUT', eventLabel: 'Clickout, view all products', namedReferral: 'Search', targetUrl: `${localeBaseUrl}/search/?text=${searchTerm}` }); } } catch (error) { console.debug("Clickout - view all products", error) } } const handleCategoryClickout = (event) => { try { if (event.target.closest('div')?.className === "categories" || event.target.closest('ol')?.className.includes('search-data-categoryResult')) { const { sku, price, quantity, ...pureBody } = eventBody; const targetUrl = event.target.href || event.target.closest("a").href; sendEvent({ ...pureBody, eventType: 'CLICKOUT', eventLabel: 'Clickout, category', namedReferral: 'Search', targetUrl }); } } catch (error) { console.debug("Clickout - category", error) } } //_________________________EVENT HANDLERS USAGE_________________________ observeAndReactOnPageChange(); // HANDLE PURCHASE handlePurchase(); // ALLOCATE EVENT LISTENER ON BODY document.querySelector('body').addEventListener('mousedown', (event) => { handleTrackingDecline(event) handleSelectCardFromCart(event) handleAddToCartByPressingAddButtonProductList(event) handleAddToCartByPressingAddButtonPDPPage(event) handleAddProductPlusButton(event) handleRemoveCard(event) handleRemoveProductMinusButton(event) handleRemoveAll(event) handleAddRecommendedProducts(event) handleSaveOrderInLocalStorage(event) handleViewAllClickout(event) handleCategoryClickout(event) handleAddToCartFromSearch(event) handleAddProductsFromSearchResultPage(event) handleAddProductsFromSearchResultPageOldVersion(event) handleProductSearchResultsClickout(event) }, { capture: true }) // ALLOCATE KEYDOWN EVENT LISTENER ON BODY document.querySelector('body').addEventListener('keydown', (event) => { if (event.code === "Enter" || event.code === "NumpadEnter") { handleTrackingDecline(event) handleSelectCardFromCart(event) handleAddToCartByPressingAddButtonProductList(event) handleAddToCartByPressingAddButtonPDPPage(event) handleAddProductPlusButton(event) handleAddToCartByInput(event) handleRemoveCard(event) handleRemoveProductMinusButton(event) handleRemoveAll(event) handleAddRecommendedProducts(event) handleSaveOrderInLocalStorage(event) handleOnEnterSearch(event) handleViewAllClickout(event) handleCategoryClickout(event) handleAddToCartFromSearch(event) handleAddProductsFromSearchResultPage(event) handleAddProductsFromSearchResultPageOldVersion(event) handleProductSearchResultsClickout(event) } }, { capture: true }) // ADD EVENT LISTENER TO INPUTS IN SHOPPING CART addEventListenerToInputsShoppingCart() // ADD EVENT LISTENER TO SEARCH addEventListenerToSearch() addEventListenerToPLPSearchResults() } 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") { runScript(); } }); } else { runScript(); }