(function(ns, fetch){ const shopifyScopeUpdatedPlaceholder = false; const cartTokenName = 'sibPreviousCartEventToken'; const cartStateName = 'sibCartState'; const { ShopifyAnalytics } = window; const { meta: { page: { customerId } = {} } = {} } = ShopifyAnalytics || {}; const { page: { customerId: metaCustomerId } = {} } = meta || {}; const isShopifyScopeUpdated = shopifyScopeUpdatedPlaceholder === true; const enableCartTracking = Boolean(metaCustomerId); // const enableCartTracking = Boolean(isShopifyScopeUpdated ? ShopifyAnalytics : metaCustomerId); // const vistiorIdCookieName = 'sib_cuid'; const setCookie = (name, value, days = '6.25') => { let expires = ''; if (days) { const date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); expires = `; expires=${date.toUTCString()}`; } document.cookie = `${name}=${value || ''}${expires}; path=/`; }; const getCookie = (cookieName) => { const name = `${cookieName}=`; const cookieArray = document.cookie.split(';'); for (let i = 0; i < cookieArray.length; i++) { let cookie = cookieArray[i]; while (cookie.charAt(0) === ' ') cookie = cookie.substring(1, cookie.length); if (cookie.indexOf(name) === 0) return cookie.substring(name.length, cookie.length); } return null; }; addListenerOnAjaxComplete(); addWrapperForFetch(ns, fetch); async function sha1Encoding(message) { const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8); // hash the message const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string return hashHex; }; const adds = (newItems, oldItems, action = 'addToCart') => { return Object.keys(newItems).reduce((result, productId) => { const newItemData = newItems[productId]||{}; const oldItemData = oldItems[productId]||{}; const quantity = newItemData.quantity || 0; const previousQuantity = oldItemData.quantity || 0; if( previousQuantity < quantity) { const data = { ...newItemData }; data.quantity = quantity-previousQuantity; result.push({ action, data }); } return result }, []) } const removes = (newItems, oldItems) => { return adds(oldItems, newItems, 'removeFromCart') }; const checkForCartStateChanges = (cart) => { const {items, token} = cart; if (!items) return { data: cart, newCartState: {}, oldCartState: {} }; if (getCookie(cartTokenName) !== token) { if (items.length > 0) setCookie(cartTokenName, token); setCookie(cartStateName);//remove cart state } const {actiondata, newCartState, oldCartState} = resolveCartEvents(items); data = {...cart, actiondata}; return { data, newCartState, oldCartState }; } const resolveCartEvents = (items) => { const cartStateCookie = getCookie(cartStateName); const oldCartState = cartStateCookie ? JSON.parse(cartStateCookie) : {} const newCartState = items.reduce((result, item) => { const { variant_title, quantity, product_id, product_title, variant_id, featured_image:{url:imageURL} = { url: ''}, price, url, options_with_values = []} = item; const productId = variant_title ? variant_id : product_id; const sizeObj = (options_with_values && options_with_values.filter( option => option.name === 'Size'))[0] || {}; const data = { variant_name: variant_title || '', quantity: quantity || '', product_id: product_id || '', variant_id: variant_id || '', name: product_title || '', image: imageURL || '', price: price || '', url: url ? window.location.origin + url : '', size: sizeObj.value || '' } result[productId] = data; return result }, {}) const actiondata = adds(newCartState, oldCartState).concat(removes(newCartState, oldCartState))[0]; setCookie(cartStateName,JSON.stringify(newCartState)); return {actiondata, newCartState, oldCartState}; } function addWrapperForFetch(ns, fetch) { if(typeof fetch !== 'function') return; ns.fetch = function() { var out = fetch.apply(this, arguments); out.then( function(responseJson) { if (responseJson.status && responseJson.status == 200) { if ( enableCartTracking && (responseJson.url.match('/cart/add') || responseJson.url.match('/cart/change') || (isShopifyScopeUpdated && responseJson.url.match('/cart/update')))) { fetch('/cart.js', { method: 'GET', credentials: 'same-origin', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' } }).then(function(response) { return response.json(); }).then (function (cart) { callCartTrackingByFetch(cart) }) } } } ) return out; } function callCartTrackingByFetch(response) { if(isShopifyScopeUpdated){ const { data, newCartState, oldCartState } = checkForCartStateChanges(response); data.customerId = customerId || ''; // data.visitor_uid = getCookie(vistiorIdCookieName); data.isFromShopFrontend = true; if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') { data.moneyFormat = theme.moneyFormat; } try { sha1Encoding(JSON.stringify(oldCartState) + JSON.stringify(newCartState)).then( fingerPrint => { fetch('https://plugin.brevo.com/integrations/api/events/60b465615325cb510361b212/cart_tracking?ma-key=r4eut29jrxf0z7n344jafgc1', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({fingerPrint,...data}) }) }); } catch (error) { } } else{ let data = response; data.customerId = metaCustomerId; data.isFromShopFrontend = true; if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') { data.moneyFormat = theme.moneyFormat; } fetch('https://plugin.brevo.com/integrations/api/events/60b465615325cb510361b212/cart_tracking?ma-key=r4eut29jrxf0z7n344jafgc1', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); } } } function addListenerOnAjaxComplete() { if (typeof jQuery === 'undefined') return; $(document).ajaxComplete(function (event, xhr, settings) { function callCartTrackingByJquery() { if(isShopifyScopeUpdated){ const { data, newCartState, oldCartState } = checkForCartStateChanges(JSON.parse(this.responseText)); data.isFromShopFrontend = true; if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') { data.moneyFormat = theme.moneyFormat; } data.customerId = customerId || ''; // data.visitor_uid = getCookie(vistiorIdCookieName); data.isFromShopFrontend = true; if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') { data.moneyFormat = theme.moneyFormat; } try { sha1Encoding(JSON.stringify(oldCartState) + JSON.stringify(newCartState)).then( fingerPrint => { let request = new XMLHttpRequest(); request.open('POST', 'https://plugin.brevo.com/integrations/api/events/60b465615325cb510361b212/cart_tracking?ma-key=r4eut29jrxf0z7n344jafgc1', true); request.setRequestHeader('Content-Type', 'application/json'); request.send(JSON.stringify({fingerPrint,...data})); }); } catch (error) { } } else{ let data = JSON.parse(this.responseText); data.customerId = metaCustomerId; data.isFromShopFrontend = true; if(typeof theme !== 'undefined' && typeof theme.moneyFormat !== 'undefined') { data.moneyFormat = theme.moneyFormat; } let request = new XMLHttpRequest(); request.open('POST', 'https://plugin.brevo.com/integrations/api/events/60b465615325cb510361b212/cart_tracking?ma-key=r4eut29jrxf0z7n344jafgc1', true); request.setRequestHeader('Content-Type', 'application/json'); request.send(JSON.stringify(data)); } } if (enableCartTracking && (settings.url === '/cart/add.js' || settings.url === '/cart/change.js' || (isShopifyScopeUpdated && settings.url === '/cart/update.js'))) { let request = new XMLHttpRequest(); request.addEventListener('load', callCartTrackingByJquery); request.open('GET', '/cart.js', true); request.send(); } }); } }(window, window.fetch))