@topsort/toppie-sdk
Version:
Toppie sdk is a JS library that allows to integrate Topsort auctions and analytics into your website.
3 lines (2 loc) • 15.4 kB
JavaScript
(function(b,x){typeof exports=="object"&&typeof module<"u"?x(exports):typeof define=="function"&&define.amd?define(["exports"],x):(b=typeof globalThis<"u"?globalThis:b||self,x(b.ts={}))})(this,function(b){"use strict";class x{constructor(){this.debug=!1,this.baseURL="https://gtm.topsort.workers.dev/",this.cookieName="tsuid",this.deviceType=typeof window<"u"&&window.navigator.userAgent.includes("Mobile")?"mobile":"desktop",this.enabledCatalogIngestion=!1}setAppId(e){this.appId=e}getAppId(){return this.appId}setBaseURL(e){this.baseURL=e}setDebug(e){this.debug=e}setCookieName(e){this.cookieName=e}setUserId(e){this.userId=e}setEnabledCatalogIngestion(e){this.enabledCatalogIngestion=e}}const I=new x;function R(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const n=Math.random()*16|0;return(e==="x"?n:n&3|8).toString(16)})}function B(){var n;const r=I.cookieName;return(n=new RegExp(`(^|;)\\s*${r}\\s*=\\s*([^;]+)`).exec(document.cookie))==null?void 0:n.pop()}function O(r){const e=I.cookieName;document.cookie=`${e}=${r};max-age=31536000`}function S(){if(I.userId)return I.userId;const r=B();if(r)return r;const e=R();return O(e),e}const A=new Map;function $(r,e=void 0){A.set(r,e)}function H(r){return A.has(r)}const _=(r,{method:e,body:n,params:t})=>{let s=`${I.baseURL}${r}`;const c={method:e,body:n,headers:{"Content-Type":"application/json","X-TS-ID":`${I.appId}`}};return t&&(s+=`?${new URLSearchParams(t).toString()}`),window.fetch(s,c)};class P{constructor(){this.service_url=I.baseURL,this.deviceType=I.deviceType,this.user_id=S()}setUserId(e){this.user_id=e}send(e){return _("v1/events",{method:"POST",body:JSON.stringify({...e})})}event(e,n,t=!1){if("resolvedBidId"in n&&!t){const s=n.resolvedBidId;if(H(`${s}-${e}`))return;$(`${s}-${e}`,e)}return this.send({[e]:[{id:R(),opaqueUserId:this.user_id,occurredAt:new Date().toISOString(),deviceType:this.deviceType,placement:this.placement(),...n}]})}placement(){let e=window.location.pathname;const n=new URLSearchParams(window.location.search);return n.delete("address"),n.toString()&&(e+=`?${n.toString()}`),{path:e}}}const C=new P;async function T(r){try{const e=await _("v1/auctions",{method:"POST",body:JSON.stringify(r)});return e.ok?await e.json():void 0}catch{return}}const D={position:"append"};function k(r,e,n=D){n.position==="append"?e.appendChild(r):e.insertBefore(r,e.firstChild)}function j({id:r,className:e,slotId:n,resolvedBidId:t,rank:s,href:c,target:o="_self",onclick:i,imageSrc:d,width:a,height:g,style:l={},...u}){const h=document.createElement("div");h.dataset.tsBanner=n,h.dataset.tsResolvedId=t,h.dataset.tsRank=s?s.toString():"1",h.classList.add("ts-banner"),h.style.width="100%",h.style.height="auto",h.style.display="flex",h.style.justifyContent="center",h.style.alignItems="center",r&&(h.id=r),e&&h.classList.add(e);const f=document.createElement("img");f.src=d,f.alt="ts-banner",Object.assign(f.style,l),f.style.width="100%",f.style.height="auto",f.style.maxWidth=`${a}px`,f.style.maxHeight=`${g}px`;const p=document.createElement("a");p.href=c,p.target=o,p.style.width="100%",p.style.height="auto",p.style.maxWidth=`${a}px`,p.style.maxHeight=`${g}px`,p.style.display="inline-block",i&&p.addEventListener("click",async m=>{m.preventDefault(),await i(m),window.location.href=c});const y=m=>m.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();for(const[m,w]of Object.entries(u))if(typeof w=="string"&&p.setAttribute(y(m),w),typeof w=="function"&&m.startsWith("on")){const E=m.slice(2).toLowerCase();p.addEventListener(E,w)}return k(f,p),k(p,h),h}const z={"medium-banner":{width:300,height:250},"wide-skyscraper":{width:160,height:600},halfpage:{width:300,height:600},leaderboard:{width:728,height:90},"mobile-1":{width:320,height:50},"mobile-2":{width:300,height:250}};function W({slotId:r,width:e,height:n}){const t=z[r];if(t)return t;if(e&&n)return{width:e,height:n}}async function X({target:{target:r,width:e,height:n,position:t="prepend"},auction:s}){const c=W({slotId:s.slotId,width:e,height:n});if(!c)return;const o=await T({auctions:[{type:"banners",slots:1,opaqueUserId:S(),...s}]});if(o){for(const i of o.results)if(i.resultType==="banners")for(const d of i.winners){const[a]=d.asset;if(!a)continue;const g=j({slotId:s.slotId,resolvedBidId:d.resolvedBidId,rank:d.rank,href:d.id,imageSrc:a.url,width:c.width,height:c.height,onclick:async()=>{await C.event("clicks",{resolvedBidId:d.resolvedBidId})}});k(g,r,{position:t})}return null}}const F=.5;function J({target:r}){const e=new WeakSet,n=new IntersectionObserver(o=>{for(const i of o)i.isIntersecting&&(r.event(i.target),e.add(i.target),n.unobserve(i.target))},{threshold:r.threshold??F}),t=o=>{for(const i of Array.from(o))e.has(i)||n.observe(i)},s=document.querySelectorAll(r.target);t(s);const c=new MutationObserver(o=>{for(const i of o)if(i.type==="childList"){const d=document.querySelectorAll(r.target);if(!d)return;t(d)}});return c.observe(document.body,{childList:!0,subtree:!0,attributeFilter:[r.target]}),()=>{n.disconnect(),c.disconnect()}}class K{constructor(e){this.targets=[],this.observer=null,this.pollInterval=null,this.lastData=new Map,this.interval=1e3,this.checkCache=()=>{var s;const t=(s=window.__APOLLO_CLIENT__)==null?void 0:s.cache.data;if(t)for(const[c,o]of Object.entries(t))for(const i of this.targets){const d=c.split(":")[0];if(d&&i.cacheKeyMatcher(d)){const a=this.lastData.get(d),g=Object.keys(o).length;g>(a??0)&&(this.lastData.set(d,g),i.onIntercept({data:o,key:d}))}}},e&&(this.interval=e),this.observeCache()}addTarget(e){this.targets.push(e)}clear(){this.targets=[],this.disconnect()}observeCache(){this.checkCache(),this.pollInterval=window.setInterval(this.checkCache,this.interval)}disconnect(){this.observer&&(this.observer.disconnect(),this.observer=null),this.pollInterval&&(window.clearInterval(this.pollInterval),this.pollInterval=null),this.lastData.clear()}}let V=class{constructor(){this.targets=[],this.originalFetch=fetch.bind(window),this.intercept()}clear(){this.targets=[]}addTarget(e){this.targets.push(e)}intercept(){window.fetch=async(e,n)=>{var c;const t=typeof e=="string"?e:e instanceof URL?e.toString():e.url,s=(n==null?void 0:n.method)||"GET";try{let o;if(n!=null&&n.body)try{o=JSON.parse(n.body.toString())}catch{o=n.body}const i=await this.originalFetch(e,n),d=i.clone();for(const a of this.targets)a.urlMatcher(t)&&a.methodMatcher(s)&&await a.onIntercept({response:d,request:{url:t,method:s,headers:new Headers(n==null?void 0:n.headers),body:o}});return i}catch(o){for(const i of this.targets)i.urlMatcher(t)&&i.methodMatcher(s)&&((c=i.onError)==null||c.call(i,o instanceof Error?o:new Error(String(o))));throw o}}}};const G=window.XMLHttpRequest;class Y{constructor(){this.targets=[],this.intercept()}clear(){this.targets=[]}addTarget(e){this.targets.push(e)}intercept(){const e=this;function n(){const t=new G,s=t.open,c=t.send,o=t.setRequestHeader;let i="",d="",a;const g={};return t.setRequestHeader=(l,u)=>(g[l.toLowerCase()]=u,o.call(t,l,u)),t.open=(l,u,...h)=>(i=l,d=u,s.apply(t,[l,u,...h])),t.addEventListener("load",()=>{var l;for(const u of e.targets)if(u.urlMatcher(d)&&u.methodMatcher(i)){const h={},f=t.getAllResponseHeaders().split(`\r
`);for(const p of f){const[y,m]=p.split(": ");y&&m&&(h[y.toLowerCase()]=m)}(l=u.onIntercept)==null||l.call(u,{response:{status:t.status,statusText:t.statusText,responseText:t.responseText,responseURL:t.responseURL,headers:h},payload:a,requestHeaders:g,url:d})}}),t.addEventListener("error",()=>{var l;for(const u of e.targets)u.urlMatcher(d)&&u.methodMatcher(i)&&((l=u.onError)==null||l.call(u,new Error(`XHR Error: ${t.statusText}`)))}),t.send=l=>(a=l,c.call(t,l)),t}window.XMLHttpRequest=n}}class Z{constructor(){this.events=[],this.interceptorXHR=new Y,this.interceptorFetch=new V,this.interceptorApolloCache=new K}addEvent(e){e.type==="dom"?(J({target:{target:e.target,event:e.onEvent,threshold:e.threshold}}),this.events.push({options:e})):e.type==="xhr"?(this.interceptorXHR.addTarget(e),this.events.push({options:e})):e.type==="fetch"?(this.interceptorFetch.addTarget(e),this.events.push({options:e})):e.type==="apollo-cache"&&(this.interceptorApolloCache.addTarget(e),this.events.push({options:e}))}clear(){this.events=[],this.interceptorXHR.clear(),this.interceptorFetch.clear()}}const Q=5;function ee(r){var t,s;const e=document.querySelectorAll(".MenuCategoryCarousels__carousel");for(const c of Array.from(e)){const o=c.querySelector(".MenuCategoryCarousels__subtitle__main");if((t=o==null?void 0:o.textContent)!=null&&t.toLowerCase().includes(r.toLowerCase()))return c}const n=document.querySelectorAll(".MenuCatalog");for(const c of Array.from(n)){const o=c.querySelector(".MenuCatalog__title");if((s=o==null?void 0:o.textContent)!=null&&s.toLowerCase().includes(r.toLowerCase()))return c}return null}async function te(r){try{const e=S(),n=r.map(()=>({type:"banners",slots:1,slotId:"sponsored-listing-banner",opaqueUserId:e,deviceType:I.deviceType}));return await T({auctions:n})}catch{return}}function ne(r,e){const n=[];for(const t of r)e[t]&&n.push(e[t].product_id);return n}function L(r,e){const n=e.find(t=>t.value.includes(r));if(n)return n;for(const t of e){const s=L(r,t.children);if(s)return s}return null}function re({resolvedBidId:r,imageUrl:e,productName:n}){const t=document.createElement("div");t.setAttribute("data-ts-resolved-id",r),t.style.display="flex",t.style.justifyContent="center";const s=document.createElement("img");return s.src=e,s.alt=n,s.style.height="160px",s.style.width="fit-content",t.addEventListener("click",()=>{C.event("clicks",{resolvedBidId:r})}),t.appendChild(s),t}async function se(r,e){var n;try{const t=JSON.parse(r),s=window.location.pathname.split("/").pop();if(!s)return;const c=L(s,t.data.categories);if(!c)return;let o=c.children.slice(0,Q);o.length===0&&c.product_ids.length>0&&(o=[c]);const i=o.map(a=>({products_ids:ne(a.product_ids,t.data.products),slotsNumber:e,category:a})),d=await te(i);if(!d)return;for(const a of d.results){if(a.resultType!=="banners"||a.winners.length===0)continue;const g=d.results.indexOf(a),l=i[g];if(!l)continue;const u=ee(l.category.name);if(!u)continue;const h=u.querySelectorAll(".MenuItem");if(h)for(const f of a.winners){const p=Object.values(t.data.products).find(v=>v.product_id===f.id);if(!p)continue;const y=l.category.product_ids.findIndex(v=>v===p.id);if(y===-1)continue;const m=u.querySelector("[data-ts-resolved-id]");let w;if(m?w=m.parentElement:w=h[y],!w)continue;if(!m){const v=(n=f.asset)==null?void 0:n[0];if(!v)continue;const pe=re({resolvedBidId:f.resolvedBidId,imageUrl:v.url,productName:p.name}),N=w.querySelector("img.MenuItem__image");if(!N)continue;w.replaceChild(pe,N);const q=w.querySelector(".MenuItem__sizes");q&&q.remove()}const E=h[f.rank-1];if(E)try{const v=E.parentElement;v&&v.insertBefore(w,E)}catch{return}}}return}catch{return}}async function oe(r){try{const e=S(),n=r.map(()=>({type:"banners",slots:1,slotId:"sponsored-listing-banner",opaqueUserId:e,deviceType:I.deviceType}));return await T({auctions:n})}catch{return}}function ie({resolvedBidId:r,imageUrl:e,productName:n}){const t=document.createElement("div");t.setAttribute("data-ts-resolved-id",r),t.style.display="flex",t.style.justifyContent="center";const s=document.createElement("img");return s.src=e,s.alt=n,s.style.height="160px",s.style.width="fit-content",t.addEventListener("click",()=>{C.event("clicks",{resolvedBidId:r})}),t.appendChild(s),t}async function ce(r,e){var n;try{const t=JSON.parse(r);if(!t.data.search)return;const s=t.data.search.ids.filter(a=>a!==null),c=[];for(const a of s)t.data.products[a]&&c.push(t.data.products[a].product_id);const o=await oe([{products_ids:c,slotsNumber:e}]);if(!o||!o.results)return;const i=document.querySelector(".MenuCatalog__container");if(!i)return;const d=i.querySelectorAll(".MenuItem");if(!d)return;for(const a of o.results)if(a.resultType==="banners"&&a.winners.length!==0)for(const g of a.winners){const l=Object.values(t.data.products).find(y=>(y==null?void 0:y.product_id)===g.id);if(!l)continue;const u=s.findIndex(y=>y===l.id);if(u===-1)continue;const h=i.querySelector("[data-ts-resolved-id]");let f;if(h?f=h.parentElement:f=d[u],!f)continue;if(!h){const y=(n=g.asset)==null?void 0:n[0];if(!y)continue;const m=ie({resolvedBidId:g.resolvedBidId,imageUrl:y.url,productName:l.name}),w=f.querySelector("img.MenuItem__image");if(!w)continue;f.replaceChild(m,w);const E=f.querySelector(".MenuItem__sizes");E&&E.remove()}const p=d[g.rank-1];if(p)try{const y=p.parentElement;y&&y.insertBefore(f,p)}catch{return}}return}catch{return}}function M({responseText:r}){try{const e=JSON.parse(r);if(Object.keys(e.data.products).length===0)return;_("v1/products",{method:"POST",body:JSON.stringify({data:{products:e.data.products}})})}catch{return}}async function ae({orderId:r,clientId:e,authorization:n}){try{return(await fetch(`/api/customer/orders/recent/${r}?include_merchant=true&client_id=${e}`,{headers:{Authorization:n}})).json()}catch{return null}}async function de({responseText:r,requestHeaders:e,url:n}){var g;const t=Object.keys(e).find(l=>l.toLowerCase()==="authorization");if(!t)return;const s=e[t],c=n.match(/[?&]client_id=([^&]+)/),o=c?c[1]:null;if(!o)return;const{orders:i}=JSON.parse(r);if(!i)return;const d=await Promise.all(i.map(async l=>await ae({orderId:l.orderId.toString(),clientId:o,authorization:s}))),a=[];for(const l of d)if((g=l==null?void 0:l.order)!=null&&g.cart)for(const u of l.order.cart)a.push({productId:u.id,unitPrice:Number.parseFloat(u.unit_price),quantity:u.quantity});C.event("purchases",{items:a})}function le(){return[{type:"xhr",urlMatcher:e=>{const n=e.includes("/api/data/search"),t=e.includes("keyword=");return!!(n&&t)},methodMatcher:e=>e==="GET",onIntercept:async({response:e})=>{ce(e.responseText,1),I.enabledCatalogIngestion&&M({responseText:e.responseText})}},{type:"xhr",urlMatcher:e=>{const n=e.includes("/api/data/search"),t=e.includes("keyword=");return!!(n&&!t)},methodMatcher:e=>e==="GET",onIntercept:async({response:e})=>{se(e.responseText,1),I.enabledCatalogIngestion&&M({responseText:e.responseText})}},{type:"xhr",urlMatcher:e=>e.includes("/api/customer/checkout"),methodMatcher:e=>e==="GET",onIntercept:async({response:e,requestHeaders:n,url:t})=>{de({responseText:e.responseText,requestHeaders:n,url:t})}}]}function ue(){return[]}function he(r){switch(r){case"TS1003581":return le();case"TS1004020":return ue();default:return}}class fe{constructor(){this.config=I,this.eventCollector=new Z}init(e){this.config.setAppId(e.appId),e.debug&&this.config.setDebug(e.debug),e.cookieName&&this.config.setCookieName(e.cookieName),e.userId&&this.config.setUserId(e.userId),e.baseURL&&this.config.setBaseURL(e.baseURL),this.preload()}preload(){const e=this.config.getAppId();if(!e)return;this.eventCollector.addEvent({type:"dom",target:"[data-ts-resolved-id]",onEvent:t=>{const s=t.getAttribute("data-ts-resolved-id");s&&C.event("impressions",{resolvedBidId:s})}});const n=he(e);if(n)for(const t of n)this.eventCollector.addEvent(t)}identify(e){this.config.setUserId(e.userId)}auctions(e){e.type==="banners"&&this.eventCollector.addEvent({type:"dom",target:e.target.selector,onEvent:n=>{X({target:{target:n,width:e.target.width,height:e.target.height,position:e.target.position},auction:e.auction})},threshold:0})}}const U=new fe;window.toppie=U,b.toppie=U,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});