1import{AlgoliaClient}from"./algolia-client.js";import{renderProductTile}from"./algolia-product-tile.js";import{d as addItemById,a as contexts}from"./cart-cce84c00.js";import{E as EVENTS}from"./events-58bc9098.js";function publishGtmEvent(name,payload){try{window.Shopify?.analytics?.publish?.(name,payload)}catch{}}function hitToGtmItem(hit,position){return{objectID:hit.objectID,title:hit.title,vendor:hit.vendor,price:hit.price,position}}function getInsightsUserToken(){try{const m=document.cookie.match(/(?:^|;\s*)_ALGOLIA=([^;]+)/);return m?decodeURIComponent(m[1]):null}catch{return null}}const RECO_CACHE_TTL_MS=1800*1e3;function recoCacheKey(indexName,model,objectId,facetName,facetValue){return"algolia_reco:"+[indexName,model,objectId||"",facetName||"",facetValue||""].join("|")}function readRecoCache(key){try{const raw=sessionStorage.getItem(key);if(!raw)return null;const c=JSON.parse(raw);return!c||typeof c.ts!="number"||Date.now()-c.ts>RECO_CACHE_TTL_MS?null:c}catch{return null}}function writeRecoCache(key,hits,queryID){try{sessionStorage.setItem(key,JSON.stringify({hits,queryID,ts:Date.now()}))}catch{}}let userEngaged=!1,engagementBound=!1;const engagementWaiters=[],ENGAGEMENT_EVENTS=["pointerdown","pointermove","wheel","touchstart","keydown","scroll"];function onEngaged(){if(!userEngaged)for(userEngaged=!0,ENGAGEMENT_EVENTS.forEach(t=>window.removeEventListener(t,onEngaged,!0));engagementWaiters.length;)engagementWaiters.shift()()}function whenEngaged(fn){if(userEngaged){fn();return}engagementBound||(engagementBound=!0,ENGAGEMENT_EVENTS.forEach(t=>window.addEventListener(t,onEngaged,{capture:!0,passive:!0}))),engagementWaiters.push(fn)}function consentDecided(){try{const cp=window.Shopify&&window.Shopify.customerPrivacy;if(!cp||typeof cp.currentVisitorConsent!="function")return!1;const c=cp.currentVisitorConsent()||{};return c.analytics==="yes"||c.analytics==="no"}catch{return!1}}function withPrivacyApi(cb){if(window.Shopify&&window.Shopify.customerPrivacy&&window.Shopify.customerPrivacy.currentVisitorConsent){cb();return}try{window.Shopify.loadFeatures([{name:"consent-tracking-api",version:"0.1"}],()=>cb())}catch{cb()}}function whenConsentDecided(fn){withPrivacyApi(()=>{if(consentDecided()){fn();return}document.addEventListener("visitorConsentCollected",function onCollected(){consentDecided()&&(document.removeEventListener("visitorConsentCollected",onCollected),fn())})})}class AlgoliaRecommend extends HTMLElement{connectedCallback(){this.controller=new AbortController;const eventOptions={signal:this.controller.signal},configEl=this.querySelector("[js-algolia-recommend-config]");if(configEl){if(this.config=JSON.parse(configEl.textContent),!this.config.appId||!this.config.searchKey||!this.config.indexName){console.warn("[algolia-recommend] missing Algolia app ID/search key/index name - not rendering."),this.classList.add("hidden");return}if(this.config.requiresObjectId&&!this.config.objectId){this.classList.add("hidden");return}this.client=new AlgoliaClient({appId:this.config.appId,searchKey:this.config.searchKey}),this.bindQuickAddDelegate(eventOptions),this.bindClickAttribution(eventOptions),this.config.eager?this.fetchRecommendations():this.observeAndFetch()}}observeAndFetch(){if(!("IntersectionObserver"in window)){whenEngaged(()=>this.fetchRecommendations());return}const observer=new IntersectionObserver(entries=>{entries[0].isIntersecting&&(observer.disconnect(),whenEngaged(()=>this.fetchRecommendations()))},{rootMargin:"0px"});observer.observe(this),this.fetchObserver=observer}async fetchRecommendations(){if(!(typeof navigator<"u"&&navigator.webdriver===!0)){if(!consentDecided()){this.consentWaiterBound||(this.consentWaiterBound=!0,whenConsentDecided(()=>this.fetchRecommendations()));return}try{let hits=[];if((this.config.objectId||this.config.model==="trending-items")&&(hits=await this.runModel(this.config.model,this.config.modelLabel,this.config.objectId)),hits.length<this.config.minRecommendations&&this.config.fallbackModel&&(hits=await this.runModel(this.config.fallbackModel,this.config.fallbackModelLabel,null)),hits.length<this.config.minRecommendations){console.warn(`[algolia-recommend] only ${hits.length} usable hit(s) (model "${this.config.model}"${this.config.fallbackModel?` / fallback "${this.config.fallbackModel}"`:""}, objectID: ${this.config.objectId||"none"}, index: ${this.config.indexName}), minRecommendations is ${this.config.minRecommendations} - hiding section.`),this.classList.add("hidden");return}this.hits=hits,this.renderTiles(hits),this.observeViewed(hits),this.classList.remove("loading")}catch(e){console.error("[algolia-recommend] recommendations request failed",e),this.classList.add("hidden")}}}async runModel(model,modelLabel,objectId){const request={indexName:this.config.indexName,model,maxRecommendations:this.config.maxRecommendations,threshold:this.config.threshold};objectId&&(request.objectID=objectId),model==="trending-items"&&this.config.facetName&&this.config.facetValue&&(request.facetName=this.config.facetName,request.facetValue=this.config.facetValue),request.queryParameters={clickAnalytics:!0};const userToken=getInsightsUserToken();userToken&&(request.queryParameters.userToken=userToken);const cacheKey=recoCacheKey(this.config.indexName,model,objectId,request.facetName,request.facetValue);let rawHits,queryID;const cached=readRecoCache(cacheKey);if(cached)rawHits=cached.hits||[],queryID=cached.queryID||null;else{const[result]=await this.client.getRecommendations([request]);rawHits=result?.hits||[],queryID=result?.queryID||null,writeRecoCache(cacheKey,rawHits,queryID)}const exclude=new Set([objectId,...this.config.excludeObjectIds||[]].filter(
1Boolean).map(String)),hits=rawHits.filter(hit=>!exclude.has(String(hit.objectID))).slice(0,this.config.maxRecommendations);return(hits.length>=this.config.minRecommendations||model===this.config.fallbackModel)&&(this.queryID=queryID,this.activeModel=model,this.activeModelLabel=modelLabel),hits}renderTiles(hits){const oldRoot=this.querySelector(".algolia-recommend__slider-anchor")?.firstElementChild;if(!oldRoot)return;const newRoot=oldRoot.cloneNode(!0),track=newRoot.matches?.(".scroll-slider__slider")?newRoot:newRoot.querySelector(".scroll-slider__slider");if(!track){console.warn("[algolia-recommend] slider track (.scroll-slider__slider) not found - not rendering tiles.");return}const recommendEvent=`${this.activeModelLabel||this.config.modelLabel||"Recommend"} Clicked`;track.innerHTML=hits.map((hit,i)=>renderProductTile(hit,this.config,i,{recommendEvent,queryID:this.queryID})).join(""),oldRoot.replaceWith(newRoot)}reportViewed(hits){publishGtmEvent("algolia_recommend_viewed",{model:this.activeModel||this.config.model,modelLabel:this.activeModelLabel||this.config.modelLabel,sourceObjectId:this.config.objectId,items:hits.map((hit,i)=>hitToGtmItem(hit,i+1))})}observeViewed(hits){const observer=new IntersectionObserver(entries=>{entries[0].isIntersecting&&(observer.disconnect(),this.reportViewed(hits))});observer.observe(this),this.viewedObserver=observer}recordAddIntent(variantId,hit){if(!(!this.queryID||!variantId)){try{const raw=sessionStorage.getItem("algolia_query_map"),map=raw?JSON.parse(raw):{};map[String(variantId)]={queryID:this.queryID,index:"",ts:Date.now()};const keys=Object.keys(map);keys.length>50&&(keys.sort((a,b)=>map[a].ts-map[b].ts),keys.slice(0,keys.length-50).forEach(k=>delete map[k])),sessionStorage.setItem("algolia_query_map",JSON.stringify(map))}catch{}publishGtmEvent("algolia_recommend_add_intent",{objectID:String(variantId),productId:hit?.product_id!=null?String(hit.product_id):null,queryID:this.queryID})}}bindClickAttribution(eventOptions){this.addEventListener("click",event=>{if(event.target.closest("[js-algolia-quick-add]")||!event.target.closest("a[href]"))return;const tile=event.target.closest("[data-algolia-objectid]");if(!tile)return;const position=Number(tile.dataset.algoliaPosition),hit=position?this.hits?.[position-1]:null;this.recordAddIntent(tile.dataset.algoliaObjectid,hit)},eventOptions)}bindQuickAddDelegate(eventOptions){this.addEventListener("click",event=>{const button=event.target.closest("[js-algolia-quick-add]");if(!button||button.disabled)return;const tile=button.closest("[data-algolia-objectid]"),position=tile?Number(tile.dataset.algoliaPosition):null,hit=position!=null?this.hits?.[position-1]:null;this.recordAddIntent(button.dataset.variantId,hit),button.disabled=!0;const originalLabel=button.textContent;button.textContent="...";let addErrorMessage=null;const handleAddError=errorEvent=>{addErrorMessage=errorEvent.detail?.errorMessage||"Couldn't add to cart"};button.addEventListener(EVENTS.QUICK_ADD_ERROR,handleAddError,{once:!0}),addItemById(button.dataset.variantId,1,contexts.productItem,button).then(()=>{if(addErrorMessage){console.error("[algolia-recommend] add to cart failed:",addErrorMessage);return}window.dispatchEvent(new CustomEvent(EVENTS.CART_DRAWER_OPENING)),tile&&publishGtmEvent("algolia_recommend_converted",{model:this.activeModel||this.config.model,modelLabel:this.activeModelLabel||this.config.modelLabel,sourceObjectId:this.config.objectId,queryID:this.queryID||null,item:hit?hitToGtmItem(hit,position):{objectID:tile.dataset.algoliaObjectid,position}})}).catch(e=>{console.error("[algolia-recommend] add to cart failed",e)}).finally(()=>{if(button.removeEventListener(EVENTS.QUICK_ADD_ERROR,handleAddError),button.disabled=!1,addErrorMessage){button.textContent="Unavailable",setTimeout(()=>{button.textContent=originalLabel},2500);return}button.textContent=originalLabel})},eventOptions)}disconnectedCallback(){this.controller?.abort(),this.fetchObserver?.disconnect(),this.viewedObserver?.disconnect()}}customElements.get("algolia-recommend")||customElements.define("algolia-recommend",AlgoliaRecommend); 2//# sourceMappingURL=/cdn/shop/t/477/assets/algolia-recommend.js.map?v=110622077208160305521787048402
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.