async function boot() { let init = async () => { let [navigation, session] = await initializeService() getAsyncInfos(navigation, session) await initProcessSession(navigation, session) initProcessProduct(navigation, session) initProcessUser(navigation, session) initProcessRemoveCart(navigation, session) initProcessOrder(navigation, session) initCustomClicks(navigation, session, _cvConfig.custom_clicks) initPopPushs(navigation, session, _cvConfig.pushs) initProcessCheckout(navigation) initProcessCheckProducts(navigation) if (window['_cAddProductToWishlist']) _cAddProductToWishlist() if (window['_cvGetFormDependent']) _cvGetFormDependent(session) } if (_cvConfig.windowLoad == true) { window.addEventListener("load", async () => { init() }) } else if (_cvConfig.singlePage == true) { if (_cvFlagSinglePage === false) init() // init first time if (_cvConfig.customerKey === '219SH6DUX') { // beta _cvLoadSingleConfig(init) } else { let currentUrl = window.location.href setInterval(() => { let urlNow = window.location.href if (currentUrl != urlNow) { currentUrl = urlNow init() } }, 500) } } else { init() } } let _cvFlagSinglePage = false function _cvLoadSingleConfig(initCallback) { if (_cvFlagSinglePage === false) { _cvFlagSinglePage = true // console.log('[DEBUG] chamou _cvLoadSingleConfig...') const generateId = () => Math.round(Math.random() * 8999 + 1000); const requestUrl = new Map(); const blacklist = ["sumo", "shopback", "/_next/data/"]; const isOnBlackList = (url) => blacklist.some((key) => new RegExp(key, "i").test(url)); // alteração do metodo fetch const { fetch: originalFetch } = window; window.fetch = (...args) => { const [url] = args; const id = generateId(); if (!isOnBlackList(url)) { requestUrl.set(id, url); // console.log("Começou uma requisição fetch", id, url); setTimeout(() => { requestUrl.delete(id); // console.log("Não concluiu a requisição", id, Array.from(requestUrl)); }, 5000); } else { // console.log("Está na blacklist", url); } const response = originalFetch(...args); response.finally(() => { requestUrl.delete(id); // console.log("Terminou uma requisição fetch", id, url); }); return response; }; // alteração da classe XMLHttpRequest const { send: originalSend, open: originalOpen } = XMLHttpRequest.prototype; XMLHttpRequest.prototype.open = function (...args) { const [, url] = args; new RegExp(`//`); if (!isOnBlackList(url)) { const id = generateId(); this.id = id; requestUrl.set(id, url); // console.log("Começou uma requisição xHttp", id, url); } else { // console.log("Está na blacklist", url); } originalOpen.call(this, ...args); }; XMLHttpRequest.prototype.send = function (...args) { // console.log("Começou uma requisição xHttp", this); const originalReadyStateChange = this.onreadystatechange?.bind(this); this.onreadystatechange = function (event) { if (this.readyState === 4) { requestUrl.delete(this.id); // console.log("Terminou uma requisição xHttp", this.id, this.responseURL); // console.log("Requisições restantes", Array.from(requestUrl)); } originalReadyStateChange?.(event); }; setTimeout(() => { if (this.readyState < 4) { requestUrl.delete(this.id); // console.log("Não concluiu a requisição", this.id, Array.from(requestUrl)); } }, 5000); originalSend.call(this, ...args); }; // alteração do método pushState const originalPushState = history.pushState; history.pushState = function (...args) { originalPushState.call(this, ...args); window.dispatchEvent(new Event("cv_changepage")); }; // alteração do método replaceState const originalReplaceState = history.pushState; history.replaceState = function (...args) { originalReplaceState.call(this, ...args); window.dispatchEvent(new Event("cv_changepage")); }; window.addEventListener("cv_changepage", () => { console.log("Mudou de URL"); const interval = setInterval(() => { if (requestUrl.size === 0) { console.log("[DEBUG] terminou as requisições..."); clearInterval(interval); initCallback() } else console.log('[DEBUG] requestUrl.size -->', requestUrl.size); }, 500); }); window.addEventListener("popstate", () => { const interval = setInterval(() => { if (requestUrl.size === 0) { console.log("[DEBUG] terminou as requisições..."); clearInterval(interval); initCallback() } else console.log('[DEBUG] requestUrl.size -->', requestUrl.size); }, 500); }); } } async function initializeService() { return new Promise(async resolve => { let navigation = new _Navigation() let session = new _Session() let cart = new _Cart() let newSession let initNewSession = async () => { newSession = true let hashCookie = await getCookieCV('_cvhash') if (hashCookie != 0) { hashCookie = JSON.parse(hashCookie) session.hash = hashCookie.hash session.identified = hashCookie.identified } else { session.hash = await generateCVID() setCookieCV('_cvhash', JSON.stringify({ hash: session.hash, identified: session.identified }), 365) } session.session = await generateCVID() session.started_at = new Date() session.processTimeOut(_cvConfig.session_timeout) processTimeSpend() session.save() } if (localStorage._cvsession) { session.init() if (await session.processSessionTime() == true) { session = new _Session() await initNewSession() } else { newSession = false session.processTimeOut(_cvConfig.session_timeout) processTimeSpend() session.page_views++ } resolve([navigation, session]) } else { await initNewSession() resolve([navigation, session]) } if (localStorage._cvcart) { cart.init() if (newSession == true) { await cart.clearRemoved() if (cart.hasActiveProducts == true) { cart.cart_id = await generateCVID() cart.save() } else cart.clear() } if (cart.hasActiveProducts == true) { if (cart.record_duration != _cvConfig.cart_duration) cart.record_duration = _cvConfig.cart_duration await cart.processCartDuration() } } }) } async function initProcessSession(navigation, session) { await processForSession(navigation, _cvConfig.functions.forNavCategories, session, 'categories_view', [navigation, 'getPathCategories', _cvConfig.notValidCategories]) await processForSession(navigation, _cvConfig.functions.forNavProduct, session, 'products_view') await processForSession(navigation, _cvConfig.functions.forNavSearches, session, 'searches') let utms = await getUrlParameters(navigation.params, 'utm') if (Object.entries(utms).length > 0) { if (session.utms.length > 0) { await processForUtms(utms, session) } else session.utms.push(utms) } session.has_order = await initProcessOrder(navigation, session) new _PayloadNavigation(navigation, session).send() if (session.bis == false) session.bis = true if (navigation.geolocation != undefined || session.gls == false) session.gls = true await updateInterationLists(session) session.save() } async function updateInterationLists(session) { if (session.pushs) { // for pushs for (let i = 0; i < session.pushs.length; i++) { session.pushs[i].intervalAttempts++ } } } async function processForSession(navigation, functionName, objTo, paramTo, callbackElse) { if (functionName != 'default') { if (window[functionName]) { let values = await window[functionName](navigation).catch(err => { new _CVPROCESSBEAT('ERROR', functionName, `Erro na função de captação para sessão --> ${err}`) }) if (values) { let valuesList = await processListObjs(values, objTo[paramTo]) objTo[paramTo] = valuesList[0] navigation[paramTo] = valuesList[1] } } else new _CVPROCESSBEAT('ERROR', functionName, 'Função de captação para sessão não existe na tag') } else { objTo[paramTo] = await processListObjs(await callbackElse[0][callbackElse[1]](callbackElse[2]), objTo[paramTo]) } } async function processForUtms(utms, session) { let exist = false for (let i = 0; i < session.utms.length; i++) { if (session.utms[i].utm_campaign && utms.utm_campaign) if (await session.utms[i].utm_campaign == utms.utm_campaign) exist = true } if (!exist) session.utms.push(utms) } async function initProcessProduct(navigation) { if (window[_cvConfig.functions.isProductPage] && window[_cvConfig.functions.forProductInfos]) { if (await window[_cvConfig.functions.isProductPage](navigation) != undefined) { initProcessAddCart(navigation) let product = await window[_cvConfig.functions.forProductInfos](navigation).catch(err => { new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isProductPage, `Erro na função de captação para produto --> ${err}`) }) if (product) { let productClass = new _Product(product) productClass.save() productClass.send() productClass.validate() } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.forProductInfos, 'Função de captação para produto não retornou o objeto esperado', product) } } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isProductPage, 'Função de captação para produto não existe na tag') } async function initProcessAddCart(navigation) { if (window[_cvConfig.functions.addProductToCart]) { window[_cvConfig.functions.addProductToCart](navigation) } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.addProductToCart, 'Função de adicionar produto no carrinho não existe na tag') } async function initProcessRemoveCart(navigation) { if (window[_cvConfig.functions.removeProductToCart]) { window[_cvConfig.functions.removeProductToCart](navigation) } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.removeProductToCart, 'Função de remover produto do carrinho não existe na tag') } async function initProcessCheckProducts(navigation) { if (window[_cvConfig.functions.checkCartProducts]) { let objProducts = await window[_cvConfig.functions.checkCartProducts](navigation) if (objProducts != undefined) { let cart = new _Cart() if (localStorage._cvcart) cart.init() cart.checkProducts(objProducts[0], objProducts[1], objProducts[3]) } } else new _CVPROCESSBEAT('ERROR', 'initProcessCheckProducts', 'Função de validação de produtos no carrinho não existe na tag') } async function initProcessUser(navigation, session) { if (_cvConfig.optin_forms.length > 0) { let mapped = form => { if (form.default_visible == true) { let trigger = document.querySelector(form.trigger) if (trigger) addEvent(trigger, form) else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Trigger ${form.trigger} cadastrada para form ${form.name} não existe`) } else { // let interval1 = form => { // let idI1 = setInterval(() => { // let trigger = document.querySelector(form.trigger) // if (trigger) { // clearInterval(idI1) // addEvent(trigger, form) // interval2(form) // } // }, 600) // } // let interval2 = form => { // let idI2 = setInterval(() => { // let trigger = document.querySelector(form.trigger) // if (trigger == undefined) { // clearInterval(idI2) // interval1(form) // } // }, 800) // } // interval1(form) let intervalId = setInterval(() => { let trigger = document.querySelector(form.trigger) if (trigger) { clearInterval(intervalId) addEvent(trigger, form) } }, 400) } } let addEvent = (element, form) => { element.addEventListener('click', () => { catchInfo(form) }) element.addEventListener('touchstart', () => { catchInfo(form) }) document.addEventListener('keydown', event => { if (event.key == 'Enter' || event.keyCode == 13) catchInfo(form) }) } let catchInfo = form => { let acceptTerm = async form => { let getVariants = async form => { let variantsToReturn = {} if (form.variants.length > 0) { for (let i = 0; i < form.variants.length; i++) { const variant = form.variants[i] let field = document.querySelector(variant.field) if (field) { let value = field.value if (await value.length > 0) { variantsToReturn[variant.name] = value } else { value = field.innerText if (await value.length > 0) { variantsToReturn[variant.name] = value } } } else if (variant.required == true) { new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Variante ${variant.field} para form ${form.name} não existe`) return undefined } } } return variantsToReturn } let email = document.querySelector(form.email) if (email) { email = email.innerText ? email.innerText : email.value if (await validateEmail(email) == true) { let variants = await getVariants(form) if (variants) { let user = new _User() user.email_address = email user.variants = variants user.origin = form.name if (form.optin_field == true) user.optin_field = true else { let optin_field = document.querySelector(form.optin_field) if (await optin_field) user.optin_field = optin_field.checked else { user.optin_field = false new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Campo de opt-in ${form.optin_field} para form ${form.name} não existe`) } } registerCvUser(user, session) } } } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Campo de email ${form.email} para form ${form.name} não existe`) } if (form.term_field == true) { acceptTerm(form) } else { let termField = document.querySelector(form.term_field) if (termField) { if (termField.checked == true) acceptTerm(form) else if (termField.value == 'true') acceptTerm(form) } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', `Termo de consentimento ${form.term_field} para form ${form.name} não existe`) } } for (let i = 0; i < _cvConfig.optin_forms.length; i++) { const form = _cvConfig.optin_forms[i] if (form.url == 'all') mapped(form) else if (form.url == navigation.cleanUrl) mapped(form) } } else new _CVPROCESSBEAT('ERROR', 'initProcessUser', 'Não existem formulários de opt-in para captação de usuários') } async function initProcessOrder(navigation, session) { if (window[_cvConfig.functions.isOrderPage]) { if (session.has_order == false) { if (await window[_cvConfig.functions.isOrderPage](navigation) == true) { if (localStorage._cvcart) { let cart = new _Cart() cart.init() cart.type = 2 new _PayloadCart(cart).send() cart.clear() } return true } else return false } else return true } else { new _CVPROCESSBEAT('ERROR', _cvConfig.functions.isOrderPage, 'Função de identificação de página de compra não existe na tag') return false } } async function initProcessCheckout(navigation) { if (window[_cvConfig.functions.forOriginCart]) { if (await window[_cvConfig.functions.forOriginCart](navigation) == 2) { if (localStorage._cvcart) { let cart = new _Cart() cart.init() cart.id_origin = 2 cart.save() cart.type = 1 new _PayloadCart(cart).send() } } } else new _CVPROCESSBEAT('ERROR', _cvConfig.functions.forOriginCart, 'Função de origem de carrinho não existe na tag') } async function registerCvUser(user, session) { let hash = await triggerRequest('post', user, _cvConfig.endpoints.user, true) if (hash) { let saveSession = async (session, hashCookie) => { session.identified = true session.hash = hashCookie setCookieCV('_cvhash', JSON.stringify({ hash: hashCookie, identified: true }), 365) await session.save() session = new _Session().init() let navigation = new _Navigation() new _PayloadNavigation(navigation, session, true).send() } if (session.identified == false) { saveSession(session, hash) } else if (session.hash != hash) { saveSession(session, hash) } } else new _CVPROCESSBEAT('ERROR', 'registerCvUser', 'Requisição para registro de usário não retornou a hash esperada') } async function initPopPushs(navigation, session, pushs) { let pushToProcess = [] for (let i = 0; i < pushs.length; i++) { let rules = pushs[i].rules let passHomolog = true if (rules.homologHashs != false) { passHomolog = false if (session.identified == true) { let index = await rules.homologHashs.findIndex(e => e == session.hash) if (index >= 0) passHomolog = true else passHomolog = false } } else { if (rules.identified == 'all') passHomolog = true else if (await rules.identified == true && session.identified == false) passHomolog = false else if (await rules.identified == false && session.identified == true) passHomolog = false } if (passHomolog == true) { let passPage = true for (let j = 0; j < rules.pagesToIgnore.length; j++) { if (await navigation.cleanUrl == rules.pagesToIgnore[j]) passPage = false } if (passPage == true) { if (rules.pagesToShow == 'all') { pushToProcess.push(pushs[i]) } else { let valid = false for (let j = 0; j < rules.pagesToShow.length; j++) { if (rules.pagesToShow[j] == '$product') { valid = await window[_cvConfig.functions.isProductPage](navigation) != undefined ? true : false if (valid == true) break } else if (rules.pagesToShow[j] == '$categorie') { valid = await window[_cvConfig.functions.isCategoriePage](navigation) if (valid == true) break } else if (navigation.cleanUrl == rules.pagesToShow[j]) { valid = true; break } } if (valid == true) { pushToProcess.push(pushs[i]) } } } } } if (pushToProcess.length > 0) processPopPushs(navigation, pushToProcess, 0, session) } async function processPopPushs(navigation, pushs, index, session) { let initPush = push => { let show = true if (push.rules.hasCart === true) { if (localStorage._cvcart) { let cart = new _Cart().init() if (cart.hasActiveProducts === true) show = true else show = false } else show = false } if (show == true) { if (push.rules.show.mouseLeave == true) { let lock = false document.addEventListener('mouseleave', () => { if (!lock) { new _Push(push).showPush(navigation) lock = true } }) } else if (push.rules.show.pageLoad == true) new _Push(push).showPush(navigation) else if (push.rules.show.clickSelectors != false) { // dev selectors } } else { if (index + 1 < pushs.length) { processPopPushs(navigation, pushs, index + 1, session) } } } let currentPush = pushs[index] if (session.pushs) { let sessionIndex = await session.pushs.findIndex(e => e.name == currentPush.name) if (sessionIndex >= 0) { if (currentPush.rules.oneTimeClick === false || (currentPush.rules.oneTimeClick === true && session.pushs[sessionIndex].clicks == 0)) { if (session.pushs[sessionIndex].attempts < currentPush.rules.maxTry) { if (currentPush.rules.intervalPagesToTry < session.pushs[sessionIndex].intervalAttempts) { initPush(currentPush) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else if (index + 1 < pushs.length) processPopPushs(navigation, pushs, index + 1, session) } else { initPush(currentPush) } } else { initPush(currentPush) } } async function processCartAddProduct(product, paramToCompare, send, isEquals, check) { let cart = new _Cart() if (localStorage._cvcart) { cart.init() await cart.insertProduct(product, paramToCompare, isEquals, check) if (send) { cart.type = 1 new _PayloadCart(cart).send() } } else { cart.cart_id = await generateCVID() cart.created_at = new Date() cart.record_duration = _cvConfig.cart_duration await cart.insertProduct(product, paramToCompare, isEquals, check) if (send) { cart.type = 1 new _PayloadCart(cart).send() } } } async function processCartRemoveProduct(paramToCompare, valueToCompare, send, isEquals) { let cart = new _Cart() if (localStorage._cvcart) { cart.init() await cart.deleteProduct(paramToCompare, valueToCompare, isEquals) if (send) new _PayloadCart(cart).send() } else new _CVPROCESSBEAT('INFO', 'processCartRemoveProduct', 'Objeto de persistência de carrinho não existe') } async function initCustomClicks(navigation, session, custom) { for (let i = 0; i < custom.length; i++) { if (custom[i].page == 'all') { processCustomClicks(custom[i], session) } else if (custom[i].page == navigation.cleanUrl) { processCustomClicks(custom[i], session) } } } async function processCustomClicks(custom, session) { let indexClick = session.custom_clicks.findIndex(e => e.name == custom.name) let mapedElements = async () => { let element if (await custom.unique === true) { element = document.querySelector(custom.selector) } else { element = document.querySelectorAll(custom.selector) if (await custom.index != 'all') element = element[custom.index] } if (element) { if (await custom.unique === true || custom.index != 'all') { element.addEventListener('click', countClick) } else { for (let i = 0; i < element.length; i++) { element[i].addEventListener('click', countClick) } } } else { new _CVPROCESSBEAT('ERROR', 'processCustomClicks', `Não foi possível mapear o elemento configurado no clique personalizado`, custom) } } let countClick = async () => { custom.clicked_at = new Date() if (indexClick >= 0) { session.custom_clicks[indexClick].countClick++ } else { if (await custom.count === true) custom.countClick = 1 session.custom_clicks.push(custom) } session.save() } if (custom.count === false) { if (indexClick >= 0) mapedElements() } else mapedElements() } async function getAsyncInfos(navigation, session) { if (_cvConfig.geolocation === true) { navigation.geolocation = await navigation.getGeolocation().catch(err => { }) } if (window[_cvConfig.functions.getLoged]) window[_cvConfig.functions.getLoged](navigation, session) } function triggerRequest(method, payload, endpoint, hasReturn) { return new Promise((resolve, reject) => { let request = new XMLHttpRequest() request.open(method, endpoint, true) request.setRequestHeader('Authorization', _cvConfig.customerKey) request.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost:3500') if (payload) { request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8') request.send(JSON.stringify(payload)) } else { request.send() } request.onload = () => { if (request.status === 200 || request.status === 202) { if (hasReturn) resolve(request.responseText) else resolve() } else { new _CVPROCESSBEAT('INFO', 'triggerRequest', `Status ${request.status} para endpoint ${endpoint}`, payload) reject() } } request.onerror = () => { new _CVPROCESSBEAT('ERROR', 'triggerRequest', `Status ${request.status} para endpoint ${endpoint}`, payload) reject() } }) } async function setCookieCV(name, value, days) { let d = new Date() d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000)) let expires = "expires=" + d.toUTCString() document.cookie = name + "=" + value + ";" + expires + ";path=/" } async function getCookieCV(cname) { return new Promise(async resolve => { let name = cname + "=" let decodedCookie = decodeURIComponent(document.cookie) let ca = decodedCookie.split(';') for (let i = 0; i < ca.length; i++) { let c = ca[i] while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { resolve(c.substring(name.length, c.length)) } } resolve(0) }) } async function generateCVID() { let s4 = () => { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1) } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() } async function replaceChain(s) { return await s.replaceAll('-', ' ').replaceAll('_', ' ').replaceAll(' ', ' ') .replaceAll('á', 'a').replaceAll('à', 'a').replaceAll('ã', 'a').replaceAll('â', 'a') .replaceAll('é', 'e').replaceAll('è', 'e').replaceAll('ê', 'e') .replaceAll('í', 'i').replaceAll('ì', 'i') .replaceAll('ó', 'o').replaceAll('ò', 'o').replaceAll('õ', 'o').replaceAll('ô', 'o') .replaceAll('ú', 'u').replaceAll('ù', 'u').replaceAll('û', 'u') .replaceAll('ç', 'c').trim().toLowerCase() } async function validateEmail(email) { if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/.test(email)) return true else return false } function processTimeSpend() { let startInterval = () => { setInterval(() => { let time = Number(localStorage._cvtime) time++ localStorage.setItem('_cvtime', time) }, 1000) } if (_cvConfig.singlePage == true) { if (!localStorage._cvtime) { _cvConfig.intervalStarts = true localStorage.setItem('_cvtime', '0') startInterval() } else if (!_cvConfig.intervalStarts) { _cvConfig.intervalStarts = true startInterval() } } else { if (!localStorage._cvtime) localStorage.setItem('_cvtime', '0') startInterval() } } async function getUrlParameters(params, compare) { if (!params) params = location.search let results = {} if (params) { let query = params.substring(1); query.split('&').forEach(p => { let item = p.split('=') if (compare) { if (item[0].indexOf(compare) >= 0) { results[item[0]] = decodeURIComponent(item[1]) } } else { results[item[0]] = decodeURIComponent(item[1]) } }) return results } else { return results } } async function processListObjs(values, list) { if (values.length > 0) { if (list.length > 0) { let listToNav = [] for (let i = 0; i < values.length; i++) { listToNav.push({ value: values[i], count: 1, level: i }) let index = await checkValueExists(values[i], list) if (index >= 0) { list[index].count++ } else { await list.push({ value: values[i], count: 1, level: i }) } } await orderCvList(list, 'count') return [list, listToNav] } else { let listReturn = [] for (let i = 0; i < values.length; i++) { listReturn.push({ value: values[i], count: 1, level: i }) } await orderCvList(listReturn, 'count') return [listReturn, listReturn] } } else { await orderCvList(list, 'count') return [list, undefined] } } async function checkValueExists(value, list) { for (let i = 0; i < list.length; i++) { if (await value == list[i].value) { return i } } return -1 } async function orderCvList(list, param) { if (list.length > 0) { let n = list.length for (let i = 1; i < n; ++i) { let key = list[i] let j = i - 1 while (j >= 0 && list[j][param] < key[param]) { list[j + 1] = list[j] j = j - 1 } list[j + 1] = key } } } class _Navigation { constructor() { this.urlBase = decodeURIComponent(window.location.origin + '/') this.url = decodeURIComponent(window.location.href) this.params = decodeURIComponent(window.location.search) this.cleanUrl = this.url.replace(this.params, '') this.pathsEncoded = window.location.pathname == '/' ? '' : window.location.pathname this.pathsDecoded = decodeURIComponent(this.pathsEncoded) this.geolocation = undefined this.browserInfos = this.getBrowserInfos(), this.categories_view = undefined this.products_view = undefined this.searches = undefined } getBrowserInfos() { let userAgentString = navigator.userAgent let chromeAgent = userAgentString.indexOf("Chrome") > -1 ? 'chrome' : undefined let IExplorerAgent = userAgentString.indexOf("MSIE") > -1 || userAgentString.indexOf("rv:") > -1 ? 'internet explorer' : undefined let firefoxAgent = userAgentString.indexOf("Firefox") > -1 ? 'firefox' : undefined let safariAgent = userAgentString.indexOf("Safari") > -1 ? 'safari' : undefined if ((chromeAgent) && (safariAgent)) safariAgent = undefined let operaAgent = userAgentString.indexOf("OP") > -1 ? 'opera' : undefined if ((chromeAgent) && (operaAgent)) chromeAgent = undefined return { userAgent: userAgentString, language: navigator.language, browser: safariAgent || chromeAgent || IExplorerAgent || operaAgent || firefoxAgent } } async getGeolocation() { return new Promise(resolve => { try { navigator.geolocation.getCurrentPosition(position => { resolve(position) }) } catch (e) { } }) } async getPathCategories(notValidCategories) { let validCategories = [] if (this.pathsEncoded != '') { let pathToCompare = this.pathsEncoded if (pathToCompare.slice(0, 1) == '/') pathToCompare = pathToCompare.slice(1) let pathCategories = pathToCompare.split('/') for (let i = 0; i < pathCategories.length; i++) { pathCategories[i] = decodeURIComponent(pathCategories[i]) let valid = true for (let j = 0; j < notValidCategories.length; j++) { if (await notValidCategories[j] == '$pagination') { if (isNaN(pathCategories[i]) == false) valid = false } else if (await notValidCategories[j] == pathCategories[i] || pathCategories[i] == '') valid = false } if (valid) validCategories.push(await replaceChain(pathCategories[i].toLowerCase())) } } return validCategories } } class _PayloadNavigation { constructor(navigation, session, hasChange) { this.url = navigation.url this.cleanUrl = navigation.cleanUrl this.params = navigation.params this.paths = navigation.pathsDecoded this.session = session.session this.hash = session.hash this.identified = session.identified this.page_views = session.page_views this.utms = session.utms.length > 0 ? session.utms : undefined this.permanence_time = Number(localStorage._cvtime) this.browserInfos = session.bis == false ? navigation.browserInfos : undefined this.categories_view = session.categories_view.length > 0 ? session.categories_view : undefined this.products_view = session.products_view.length > 0 ? session.products_view : undefined this.searches = session.searches.length > 0 ? session.searches : undefined this.navigation = { categories_view: navigation.categories_view, products_view: navigation.products_view, searches: navigation.searches } this.has_order = session.has_order this.custom_clicks = session.custom_clicks.length > 0 ? session.custom_clicks : undefined this.pushs = session.pushs this.shc = hasChange this.nps_answered = session.nps_answered this.geolocation = session.gls == false ? navigation.geolocation : undefined this.started_at = session.started_at } send() { triggerRequest('post', this, _cvConfig.endpoints.navigation, false) } } class _Session { constructor() { this.session = undefined this.hash = undefined this.identified = false this.page_views = 1 this.utms = [] this.categories_view = [] this.products_view = [] this.searches = [] this.custom_clicks = [] this.pushs = undefined this.nps_answered = undefined this.has_order = false this.started_at = undefined this.updated_at = undefined this.bis = false this.gls = false } init() { let session = JSON.parse(localStorage._cvsession) this.session = session.session this.hash = session.hash this.identified = session.identified this.page_views = session.page_views this.utms = session.utms this.categories_view = session.categories_view this.products_view = session.products_view this.searches = session.searches this.custom_clicks = session.custom_clicks this.pushs = session.pushs this.nps_answered = session.nps_answered this.has_order = session.has_order this.started_at = new Date(session.started_at) this.updated_at = new Date(session.updated_at) this.bis = session.bis this.gls = session.gls return this } save() { this.updated_at = new Date() localStorage.setItem('_cvsession', JSON.stringify(this)) } remove() { localStorage.removeItem('_cvsession') localStorage.removeItem('_cvtime') } async processSessionTime() { let now = new Date() let cloneUpdate = new Date(this.updated_at) cloneUpdate.setMinutes(cloneUpdate.getMinutes() + _cvConfig.session_timeout) if (now.getTime() >= cloneUpdate) { this.remove() return true } else return false } processTimeOut(sessionTimeOut) { let intervalId = setTimeout(() => { triggerRequest('post', { session: this.session }, _cvConfig.endpoints.endsession, false) this.remove() clearInterval(intervalId) }, sessionTimeOut * 60000) } } class _Cart { constructor() { this.cart_id = undefined this.products = [] this.hasActiveProducts = false this.type = 1 this.id_origin = undefined this.created_at = undefined this.updated_at = undefined this.record_duration = undefined } init() { let cart = JSON.parse(localStorage._cvcart) this.cart_id = cart.cart_id this.products = cart.products this.hasActiveProducts = cart.hasActiveProducts this.type = cart.type this.id_origin = cart.id_origin this.created_at = new Date(cart.created_at) this.updated_at = new Date(cart.updated_at) this.record_duration = cart.record_duration return this } save() { this.updated_at = new Date() localStorage.setItem('_cvcart', JSON.stringify(this)) } async processCartDuration() { let now = new Date() let cloneUpdate = new Date(this.updated_at) cloneUpdate.setMinutes(cloneUpdate.getMinutes() + this.record_duration) if (now.getTime() >= cloneUpdate) { await this.clear() } } async clear() { localStorage.removeItem('_cvcart') } async clearRemoved() { this.hasActiveProducts = false for (let i = 0; i < this.products.length; i++) { if (await this.products[i].removed == true) { this.products.splice(i, 1) i-- } else this.hasActiveProducts = true } } async insertProduct(productToInsert, param, isEquals, check) { if (productToInsert[param]) { let index = false for (let i = 0; i < this.products.length; i++) { let product = this.products[i] try { if (isEquals == true) { if (await product[param] == productToInsert[param]) { index = i break } } else { if (await productToInsert[param].indexOf(product[param]) >= 0) { index = i break } } } catch (err) { new _CVPROCESSBEAT('ERROR', 'insertProduct', err) } } if (index === false) { this.products.push(productToInsert) this.hasActiveProducts = true this.save() } else { if (!check) { if (this.products[index].selectable) this.products[index].selectable.qtd += productToInsert.selectable ? productToInsert.selectable.qtd : 1 else this.products[index].selectable = { qtd: productToInsert.selectable ? productToInsert.selectable.qtd : 1 } } if (this.products[index].removed == true) this.products[index].removed = false this.save() } } else { new _CVPROCESSBEAT('ERROR', 'insertProduct', 'Produto a ser inserido não possui parâmetro de comparação informado', productToInsert) } } async deleteProduct(param, valueToCompare, isEquals) { let exist = false for (let i = 0; i < this.products.length; i++) { let product = this.products[i] if (isEquals) { if (await product[param] == valueToCompare) { exist = true product.removed = true } } else { if (await valueToCompare.indexOf(product[param]) > -1) { exist = true product.removed = true } } } if (exist) { let active = this.products.findIndex(e => e.removed !== true) this.hasActiveProducts = active >= 0 ? true : false this.save() } else new _CVPROCESSBEAT('INFO', 'deleteProduct', 'Produto a ser deletado não foi encontrado no objeto de carrinho') } async checkProducts(currentProducts, param, isEquals) { let update = false for (let i = 0; i < currentProducts.length; i++) { // insert products in cart let exist = false for (let j = 0; j < this.products.length; j++) { if (isEquals == true) { if (await this.products[j][param] == currentProducts[i][param]) { exist = true break } } else { if (await currentProducts[i][param].indexOf(this.products[j][param]) >= 0) { exist = true break } } } if (!exist) { await processCartAddProduct(currentProducts[i], param, false, isEquals) update = true } else { await processCartAddProduct(currentProducts[i], param, false, isEquals, true) } } for (let i = 0; i < this.products.length; i++) { // delete products that are no longer in cart let exist = false for (let j = 0; j < currentProducts.length; j++) { if (isEquals == true) { if (await this.products[i][param] == currentProducts[j][param]) { exist = true break } } else { if (await currentProducts[j][param].indexOf(this.products[i][param]) >= 0) { exist = true break } } } if (!exist && this.products[i].removed != true) { update = true await processCartRemoveProduct(param, this.products[i][param], false, true) } } if (update) new _PayloadCart(this.init()).send() } } class _User { constructor() { this.email_address = undefined this.variants = {} this.origin = undefined this.optin_field = false } } class _Recommendation { constructor() { this.products = undefined } init() { let recommendation = JSON.parse(sessionStorage._cvrecommendation) this.products = recommendation.products return this } save() { sessionStorage.setItem('_cvrecommendation', JSON.stringify(this)) } } class _Product { constructor(product) { this.name = product.name this.sku = product.sku this.categories = product.categories this.url = product.url this.price = product.price this.selectable = product.selectable this.images = product.images this.defaultImage = product.defaultImage this.variants = product.variants this.removed = product.removed this.unavailable = product.unavailable } init() { if (sessionStorage._cvproduct) { let obj = JSON.parse(sessionStorage._cvproduct) this.name = obj.name this.sku = obj.sku this.categories = obj.categories this.url = obj.url this.price = obj.price this.selectable = obj.selectable this.images = obj.images this.defaultImage = obj.defaultImage this.variants = obj.variants this.removed = obj.removed this.unavailable = obj.unavailable return this } else return undefined } validate() { if (!this.name && !this.sku && this.categories.length > 0 && !this.price && !this.defaultImage) new _CVPROCESSBEAT('ERROR', 'validateProduct', 'Produto captado não atendeu os requisitos de validação', this) } save() { sessionStorage.setItem('_cvproduct', JSON.stringify(this)) } send() { triggerRequest('post', this, _cvConfig.endpoints.product, false) } } class _Push { constructor({ name, pushHTML, rules }) { this.name = name this.pushHTML = pushHTML this.rules = rules this.pushElement = undefined } showPush(navigation) { let alreadyPush = document.querySelector('#cv-push') if (!alreadyPush) { let pushElement = document.createElement('section') pushElement.id = 'cv-push' pushElement.innerHTML = this.pushHTML this.pushElement = pushElement if (this.rules.recommendation === true) { this.processPushRecommendation(navigation) } else { document.body.appendChild(pushElement) if (this.rules.customCss) document.head.insertAdjacentHTML('beforeend', this.rules.customCss) this.addEvents() this.processShow(navigation) } } } async processPushRecommendation(navigation) { if (sessionStorage._cvrecommendation) { let session = new _Session().init() let recommendation = new _Recommendation().init() this.showPushRecommendation(session, recommendation, navigation) } else { let session = new _Session().init() let payload = { hash: session.hash, categories: session.categories_view, rules: { limit_of_products: 5 } } let recCall = await triggerRequest('post', payload, _cvConfig.endpoints.recommendation, true).catch(err => { }) recCall = JSON.parse(recCall) if (recCall.recommended) { let recommendation = new _Recommendation() recommendation.products = recCall.recommended recommendation.save() this.showPushRecommendation(session, recommendation, navigation) }//else no products to recommended } } async showPushRecommendation(session, recommendation, navigation) { let indexRecom = 0 let productRecom = recommendation.products[indexRecom] if (session.products_view.length > 0) { for (let i = 0; i < session.products_view.length; i++) { if (session.products_view[i].value == productRecom.sku || productRecom.show == true) { indexRecom += 1 if (await recommendation.products[indexRecom] != undefined) { productRecom = recommendation.products[indexRecom] } else { productRecom = undefined; break } } else break } } if (productRecom) { this.pushElement.style = 'display: none' document.body.appendChild(this.pushElement) if (this.rules.customCss) document.head.insertAdjacentHTML('beforeend', this.rules.customCss) let titleElement = document.querySelector('.cv-push-box p') titleElement.innerText = productRecom.name let imgElement = document.querySelector('.cv-push-img img') imgElement.src = productRecom.defaultImage this.pushElement.style = '' recommendation.products[indexRecom].show = true recommendation.save() this.addEvents(productRecom.url + this.rules.params) this.processShow(navigation, productRecom) }//else no products to recommended } addEvents(redirect) { let closedElement = document.querySelector('.cv-push-closed img') closedElement.addEventListener('click', () => { this.pushElement.remove() }) let boxElement = document.querySelector('.cv-push-box') boxElement.addEventListener('click', () => { this.click(redirect) }) let imgElement = document.querySelector('.cv-push-img') imgElement.addEventListener('click', () => { this.click(redirect) }) } async processShow(navigation, product) { let session = new _Session().init() let createPush = exist => { let pushPayload = { name: this.name, attempts: 1, clicks: 0, intervalAttempts: 0, history: [{ url: navigation.cleanUrl, created_at: new Date(), click: 0, product: product ? { sku: product.sku } : undefined }] } if (exist) { session.pushs.push(pushPayload) } else { session.pushs = [pushPayload] } session.save() } if (session.pushs) { let index = await session.pushs.findIndex(e => e.name == this.name) if (index >= 0) { session.pushs[index].attempts++ session.pushs[index].intervalAttempts = 0 session.pushs[index].history.push({ url: navigation.cleanUrl, created_at: new Date(), click: 0, product: product ? { sku: product.sku } : undefined }) session.save() } else createPush(true) } else createPush(false) } async click(redirect) { let session = new _Session().init() let index = await session.pushs.findIndex(e => e.name == this.name) if (index >= 0) { session.pushs[index].clicks++ session.pushs[index].history[session.pushs[index].history.length - 1].click++ session.save() if (redirect) window.location.replace(redirect) else window.location.replace(this.rules.redirect) } else new _CVPROCESSBEAT('ERROR', 'clickPush', `Objeto push ${this.name} não existe na lista de pushs da sessão`) } } class _PayloadCart { constructor(cart) { let session = new _Session().init() this.session = session.session this.hash = session.hash this.identified = session.identified this.utms = session.utms.length > 0 ? session.utms : undefined this.cart_id = cart.cart_id this.products = cart.products this.type = cart.type this.id_origin = cart.id_origin this.created_at = cart.created_at this.updated_at = cart.updated_at this.pushs = session.pushs } send() { triggerRequest('post', this, _cvConfig.endpoints.cart, false) } } class _CVPROCESSBEAT { constructor(type, method, message, payload) { this.type = type this.method = method this.message = message this.payload = payload this.process() } process() { switch (this.type) { case 'INFO': console.log(`[CV.INFO.${this.method}] ${this.message}`) break case 'ERROR': // triggerRequest('POST', this, _cvConfig.endpoints.beat, false) break default: break } } } let _cvConfig = { "customerKey": "219SH6DUX", "session_timeout": 5, "windowLoad": false, "cart_duration": 10080, "singlePage": true, "geolocation": false, "notValidCategories": ["p", "cart", "checkout", "email", "profile"], "endpoints": { "navigation": "https://oci.claravista-api.com.br/register/navigation", "cart": "https://oci.claravista-api.com.br/register/cart", "product": "https://oci.claravista-api.com.br/register/product", "user": "https://oci.claravista-api.com.br/register/user", "beat": "https://oci.claravista-api.com.br/register/beat", "recommendation": "https://dashp5.claravista.com.br/core/api/v.2.2/recommendation/push" }, "functions": { "forNavCategories": "_cGetNavCategorie", "isProductPage": "_cIsProductPage", "forNavProduct": "_cGetNavProduct", "forNavSearches": "_cGetSeachers", "forProductInfos": "_cGetProductInfo", "addProductToCart": "_cAddProductToCart", "removeProductToCart": "_cRemoveProductToCart", "forOriginCart": "_cOriginCartPage", "isOrderPage": "_cIsOrderPage", "getLoged": "_cGetLoged", "checkCartProducts": "_cCheckCartProducts" }, "custom_clicks": [], "pushs": [], "optin_forms": [ { "name": "login_checkout_page", "url": "https://www.duxnutrition.com/checkout/#/email", "default_visible": true, "email": "#client-pre-email", "trigger": "#btn-client-pre-email", "term_field": true, "optin_field": true, "variants": [] }, { "name": "login_menu_key", "url": "all", "default_visible": false, "email": ".vtex-login-2-x-emailVerification.vtex-login-2-x-emailForm.w-100 .vtex-styleguide-9-x-input.ma0.border-box.vtex-styleguide-9-x-hideDecorators.vtex-styleguide-9-x-noAppearance.br2.w-100.bn.outline-0.bg-base.c-on-base.b--muted-4.hover-b--muted-3.t-body.ph5", "trigger": ".vtex-login-2-x-emailVerification.vtex-login-2-x-emailForm.w-100 .vtex-login-2-x-sendButton.ml-auto", "term_field": true, "optin_field": true, "variants": [] }, { "name": "login_menu", "url": "all", "default_visible": false, "email": ".vtex-input.w-100 .vtex-input-prefix__group.flex.flex-row.items-stretch.overflow-hidden.br2.bw1.b--solid.b--muted-4.hover-b--muted-3.h-regular", "trigger": ".vtex-login-2-x-sendButton.ml-auto", "term_field": true, "optin_field": true, "variants": [] }, { "name": "register_page_key", "url": "all", "default_visible": false, "email": ".vtex-login-2-x-emailVerification.vtex-login-2-x-emailForm.w-100 .vtex-styleguide-9-x-input.ma0.border-box.vtex-styleguide-9-x-hideDecorators.vtex-styleguide-9-x-noAppearance.br2.w-100.bn.outline-0.bg-base.c-on-base.b--muted-4.hover-b--muted-3.t-body.ph5", "trigger": ".vtex-login-2-x-emailVerification.vtex-login-2-x-emailForm.w-100 .vtex-login-2-x-sendButton.ml-auto", "term_field": true, "optin_field": true, "variants": [] }, { "name": "register_checkout_page", "url": "https://www.duxnutrition.com/checkout/#/profile", "default_visible": true, "email": "#client-email", "trigger": ".submit.btn.btn-large.btn-success", "term_field": true, "optin_field": false, "variants": [] }, { "name": "form_launch", "url": "https://www.duxnutrition.com/cadastro-lancamento-skin-body", "default_visible": true, "email": "#email", "trigger": ".duxnutrition-institutional-0-x-skinBodyFormButton button", "term_field": true, "optin_field": true, "variants": [ { "name": "name", "field": "#firstName", "required": true }, { "name": "lastName", "field": "#lastName", "required": true }, { "name": "birthDate", "field": "#birthDate", "required": true }, { "name": "cellPhone", "field": "#cellphone", "required": false } ] }, { "name": "newsletter", "url": "all", "default_visible": false, "email": "#newsletter-input-email", "trigger": ".vtex-store-newsletter-1-x-formSubmitContainer.vtex-store-newsletter-1-x-formSubmitContainer--newsletter__button button", "term_field": true, "optin_field": true, "variants": [] } ], "modals": [] } async function _cIsProductPage() { //ok let check = () => { return new Promise(resolve => { let timesToTry = 2 let intervalCount = 0 let product = undefined let intervalId = setInterval(() => { for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].ecommerce) if (dataLayer[i].ecommerce.detail) if (dataLayer[i].ecommerce.detail.products) { product = dataLayer[i].ecommerce.detail.products[0] clearInterval(intervalId) resolve(product) } } if (!product) { intervalCount++ if (intervalCount === timesToTry) { clearInterval(intervalId) resolve() } } }, 500) }) } let product = await check() return product ? product : undefined } async function _cIsCategoriePage() { //ok let categorie if (document.querySelector('.vtex-search-result-3-x-filtersWrapper.vtex-search-result-3-x-filtersWrapper--mobileFilter')) { return true } else { return false } } async function _cIsSearchPage() { //ok for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].event == "internalSiteSearchView") { return true } } } async function _cGetNavCategorie(navigation) { //ok let product = await _cIsProductPage() if (product) { let categories = [] for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].pageDepartment) categories.push(await replaceChain(dataLayer[i].pageDepartment.toLowerCase())) } let categorie = await replaceChain(product.category.toLowerCase()) let index = categories.find(e => e === categorie) if (index === undefined) categories.push(categorie) return categories } else if (await _cIsSearchPage(navigation) == true) { return [] } else if (await _cIsOrderPage(navigation) == true) { return [] } else { return await navigation.getPathCategories(_cvConfig.notValidCategories) } } async function _cGetNavProduct() { // ok let product = await _cIsProductPage() if (product) { for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].ecommerce) if (dataLayer[i].ecommerce.detail) if (dataLayer[i].ecommerce.detail.products) { let product = dataLayer[i].ecommerce.detail.products[0] return [product.id] } } } else return [] } async function _cGetSeachers(navigation) { // ok let product = await _cIsSearchPage() if (product == true) { for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].siteSearchTerm) { let product = dataLayer[i].siteSearchTerm let productHtml = document.querySelector('.vtex-breadcrumb-1-x-link.vtex-breadcrumb-1-x-link--1.dib.pv1.link.ph2.c-muted-2.hover-c-link').innerText.toLowerCase() if (product === productHtml) { return [product] //Correto } else { return [productHtml] //Correto } } } } else return [] } async function _cGetProductInfo(navigation) { // return new Promise(resolve => { let product = { variants: {}, categories: [], images: [] } let intervalLimit = 20 let intervalCount = 0 let intervalId = setInterval(async () => { let prodLayer = await _cIsProductPage() let htmlName = document.querySelector('.vtex-store-components-3-x-productBrand.vtex-store-components-3-x-productBrand--quickview') if (htmlName) product.name = htmlName.innerText product.sku = prodLayer.id product.categories = await _cGetNavCategorie(navigation) product.price = Number(Number(prodLayer.price).toFixed(2)) product.url = navigation.cleanUrl product.unavailable = false try { let fullFlavors = document.querySelectorAll('.o-0.absolute.top-0.left-0.h-100.w-100.bottom-0.t-body.pointer option') if (fullFlavors.length > 0) product.variants.fullFlavors = [] for (let i = 0; i < fullFlavors.length; i++) { let flavor = fullFlavors[i].value /*let filtered = flavor.filter(function (value) { return value > 0; });*/ product.variants.fullFlavors.push(flavor) } } catch (err) { new _CVPROCESSBEAT('ERROR', '_cGetProductInfo', `Seletores de informações de produto são nulos. Erro: ${err}`) throw `Seletores de informações de produto são nulos. Erro: ${err}` } try { let defaultImage = document.querySelector('.vtex-store-components-3-x-productImage img') product.defaultImage = defaultImage.src product.images.push(defaultImage.src) } catch (err) { new _CVPROCESSBEAT('INFO', '_cGetProductInfo', `Seletor de imagem para registro de produto é nulo. Erro: ${err}`) throw `Seletor de imagem para registro de produto é nulo. Erro: ${err}` } try { let images = document.querySelectorAll('.vtex-store-components-3-x-carouselGaleryThumbs.dn.h-auto.mt3.db-ns .swiper-wrapper .vtex-store-components-3-x-thumbImg.w-100.h-auto.db') for (let i = 0; i < images.length; i++) { try { product.images.push(images[i].src.replace('height=100&width=100', 'height=500&width=500')) } catch (e) { } } } catch (err) { new _CVPROCESSBEAT('INFO', '_cGetProductInfo', `Seletor de imagem para registro de produto é nulo. Erro: ${err}`) throw `Seletor de imagem para registro de produto é nulo. Erro: ${err}` } if (product.sku && product.name && product.price && product.defaultImage && product.images.length > 0) { clearInterval(intervalId) resolve(product) } else { intervalCount++ if (intervalCount === intervalLimit) { clearInterval(intervalId) resolve() } } }, 300) }) } async function _cAddProductToCart() { // let buttons = ['.vtex-button.bw1.ba.fw5.v-mid.relative.pa0.lh-solid.br2.min-h-regular.t-action.bg-action-primary.b--action-primary.c-on-action-primary.hover-bg-action-primary.hover-b--action-primary.hover-c-on-action-primary.pointer.w-100'] let mapped = element => { element.addEventListener('click', addClick) element.addEventListener('touchstart', addClick) } let addClick = () => { let product = new _Product({}).init() if (product != undefined) { product.selectable = { qtd: 1 } let valid = true let flavor = document.querySelector('.vtex-dropdown__caption.flex-auto.tl.truncate.h-100') if (flavor) { let flavorText = flavor.innerText.toLowerCase() if (flavorText === 'escolha uma opção') valid = false else product.selectable.flavor = flavor.innerText } if (valid) processCartAddProduct(product, 'sku', true, true) } else new _CVPROCESSBEAT('ERROR', '_cAddProductToCart', 'Produto a ser adicionado no carrinho não existe') } for (let i = 0; i < buttons.length; i++) { let element = document.querySelector(buttons[i]) console.log(element) if (element) mapped(element) } } async function _cOriginCartPage(navigation) { // ok if (navigation.cleanUrl.indexOf('/cart') >= 0) { return 1 } else if (navigation.cleanUrl.indexOf('/checkout') >= 0) { return 2 } else { return 0 } } async function _cRemoveProductToCart(navigation) {//ok let mapped = (element, callback) => { element.addEventListener('click', callback) element.addEventListener('touchstart', callback) } let removeForCart = event => { try { let node = event.target.parentNode.parentNode let name = node.querySelector('.product-name').innerText processCartRemoveProduct('name', name, true, true) } catch (err) { new _CVPROCESSBEAT('ERROR', '_cRemoveProductToCart', `Erro no método removeForCart --> ${err}`) } } let removeForMiniCart = event => { try { let node = event.target.parentNode.parentNode.parentNode let name = node.querySelector('.c-on-base.t-title.lh-copy.fw6.no-underline.fw5-m.vtex-product-list-0-x-productName.vtex-product-list-0-x-productName--minicart__product-list-name').innerText processCartRemoveProduct('name', name, true, true) } catch (err) { new _CVPROCESSBEAT('ERROR', '_cRemoveProductToCart', `Erro no método removeForMiniCart --> ${err}`) } } let idOrigin = await _cOriginCartPage(navigation) if (idOrigin == 1) { let elementRemove = document.querySelectorAll('.icon.icon-remove.item-remove-ico') for (let i = 0; i < elementRemove.length; i++) { mapped(elementRemove[i], removeForCart) } } else if (idOrigin == 0) { let elementsMini = document.querySelectorAll('.vtex-product-list-0-x-removeButtonContainer.vtex-product-list-0-x-item') for (let i = 0; i < elementsMini.length; i++) { mapped(elementsMini[i], removeForMiniCart) } } } async function _cIsOrderPage(navigation) { // if (navigation.cleanUrl.indexOf('/orderPlaced/') >= 0) { return true } else { return false } } async function _cGetLoged() { } async function _cCheckCartProducts(navigation) {//ok let origin = await _cOriginCartPage(navigation) if (origin == 1) { let productsLayer, products = [] for (let i = 0; i < dataLayer.length; i++) { if (dataLayer[i].ecommerce) if (dataLayer[i].ecommerce.checkout) if (await dataLayer[i].ecommerce.checkout.products) productsLayer = dataLayer[i].ecommerce.checkout.products } if (productsLayer) { for (let i = 0; i < productsLayer.length; i++) { products.push({ sku: productsLayer[i].id }) } return [products, 'sku', true] } else return undefined } else return undefined } boot() console.log('[SUCCESS] Claravista Tag v2.0.2')