@builtonveya/analytics-web 4.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -4
- package/dist/cjs/core/VeyaAnalyticsCore.js +6 -5
- package/dist/cjs/core/VeyaAnalyticsCore.js.map +1 -1
- package/dist/cjs/web/VeyaAnalyticsWeb.js +21 -4
- package/dist/cjs/web/VeyaAnalyticsWeb.js.map +1 -1
- package/dist/esm/core/VeyaAnalyticsCore.d.ts +1 -3
- package/dist/esm/core/VeyaAnalyticsCore.d.ts.map +1 -1
- package/dist/esm/core/VeyaAnalyticsCore.js +6 -5
- package/dist/esm/core/VeyaAnalyticsCore.js.map +1 -1
- package/dist/esm/web/VeyaAnalyticsWeb.d.ts +1 -1
- package/dist/esm/web/VeyaAnalyticsWeb.d.ts.map +1 -1
- package/dist/esm/web/VeyaAnalyticsWeb.js +21 -4
- package/dist/esm/web/VeyaAnalyticsWeb.js.map +1 -1
- package/dist/veya-analytics.js +12 -6
- package/dist/veya-analytics.js.map +2 -2
- package/dist/veya-analytics.min.js +2 -2
- package/dist/veya-analytics.min.js.map +3 -3
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! @builtonveya/analytics-web v4.0.
|
|
2
|
-
"use strict";var VeyaAnalyticsSDK=(()=>{var p=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var O=(r,t,e)=>t in r?p(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var A=(r,t)=>{for(var e in t)p(r,e,{get:t[e],enumerable:!0})},E=(r,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of D(t))!R.call(r,n)&&n!==e&&p(r,n,{get:()=>t[n],enumerable:!(i=C(t,n))||i.enumerable});return r};var F=r=>E(p({},"__esModule",{value:!0}),r);var s=(r,t,e)=>O(r,typeof t!="symbol"?t+"":t,e);var M={};A(M,{VeyaAnalyticsCore:()=>d,VeyaAnalyticsWeb:()=>h,default:()=>T,generateUUID:()=>a,getTimestamp:()=>u});var x={tenantSlug:"",tenantId:"",storeId:"",storeName:"",endpoint:"https://analytics.builtonveya.com/v1/events",aiEndpoint:"https://analytics.veya.io/v1/classify",batchSize:10,flushInterval:5e3,sessionTimeout:18e5,debug:!1,autoDetect:!0,autoTrackProducts:!0,autoTrackCart:!0,interceptOloApi:!1,useAiClassification:!0,confidenceThreshold:.7,platform:"web"};function a(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let t=Math.random()*16|0;return(r==="x"?t:t&3|8).toString(16)})}function u(){return new Date().toISOString()}var d=class{constructor(){s(this,"config");s(this,"initialized",!1);s(this,"initPromise",null);s(this,"eventQueue",[]);s(this,"flushTimer",null);s(this,"sessionId","");s(this,"visitorId","");s(this,"customerId",null);s(this,"sessionData",{is_logged_in:!1,login_method:null,logged_in_at:null,login_funnel_step:null,experiment_assignments:{}});s(this,"cartState",{items:[],itemCount:0,total:0});s(this,"deviceInfo",null);s(this,"currentScreenName","");s(this,"currentPageType","");s(this,"currentFunnelStep",null);s(this,"storage",null);this.config={...x}}init(t){return this.initPromise?(this.initialized&&this.log("warn","SDK already initialized"),this.initPromise):(this.initPromise=this.runInit(t).catch(e=>{throw this.initialized||(this.initPromise=null),e}),this.initPromise)}async runInit(t){if(!t.tenantSlug&&!t.tenantId)throw new Error("VeyaAnalytics: tenantSlug is required");this.config={...x,...t},this.config.tenantSlug||(this.config.tenantSlug=this.config.tenantId),await this.initVisitor();let e=await this.initSession();this.deviceInfo=await this.getDeviceInfo(),this.startFlushTimer(),this.initialized=!0,e&&this.trackSessionStart(),this.log("info","VeyaAnalytics initialized",{tenantSlug:this.config.tenantSlug,visitorId:this.visitorId,sessionId:this.sessionId,platform:this.config.platform,newSession:e});try{await this.onInitialized()}catch(i){this.log("error","Platform setup failed",i)}return this}async onInitialized(){}async initVisitor(){if(!this.storage){this.visitorId=a();return}let t=await this.storage.getItem("veya_visitor_id");t?this.visitorId=t:(this.visitorId=a(),await this.storage.setItem("veya_visitor_id",this.visitorId))}async initSession(){if(!this.storage)return this.sessionId=a(),!0;let t=await this.storage.getItem("veya_session"),e=Date.now();if(t)try{let i=JSON.parse(t);if(e-i.lastActivity<this.config.sessionTimeout)return this.sessionId=i.sessionId,this.sessionData={...this.sessionData,...i.data},await this.saveSession(),!1}catch{}return this.sessionId=a(),await this.saveSession(),!0}async saveSession(){this.storage&&await this.storage.setItem("veya_session",JSON.stringify({sessionId:this.sessionId,lastActivity:Date.now(),data:this.sessionData}))}async getDeviceInfo(){return{device_type:"unknown",platform:this.config.platform||"unknown",os:"unknown",screen_width:0,screen_height:0,language:"en",timezone:"UTC"}}track(t,e={}){if(!this.initialized)return this.log("warn","SDK not initialized"),this;let i=this.buildEvent(t,e);return this.queueEvent(i),this.log("debug","Event tracked",i),this}buildEvent(t,e){var i,n;return{event_id:a(),event_name:t,event_category:e.category||this.inferCategory(t),event_timestamp:u(),tenant_id:this.config.tenantSlug||this.config.tenantId||"",tenant_slug:this.config.tenantSlug||this.config.tenantId||"",session_id:this.sessionId,visitor_id:this.visitorId,customer_id:this.customerId||void 0,store_id:this.config.storeId||e.store_id,store_name:this.config.storeName||e.store_name,page_url:e.page_url,page_title:e.page_title,page_type:e.page_type||this.currentPageType,screen_name:e.screen_name||this.currentScreenName,referrer:e.referrer,...this.deviceInfo,is_logged_in:this.sessionData.is_logged_in,login_method:this.sessionData.login_method||void 0,funnel_step:e.funnel_step||((i=this.currentFunnelStep)==null?void 0:i.name),funnel_step_number:e.funnel_step_number||((n=this.currentFunnelStep)==null?void 0:n.number),cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,experiment_assignments:this.sessionData.experiment_assignments,properties:this.sanitizeProperties(e)}}inferCategory(t){return t.includes("cart")?"cart":t.includes("checkout")||t.includes("order")?"checkout":t.includes("product")||t.includes("menu")?"catalog":t.includes("login")||t.includes("auth")?"auth":t.includes("error")?"error":t.includes("screen")||t.includes("page")||t.includes("session")?"navigation":"engagement"}sanitizeProperties(t){let e={...t};return delete e.category,delete e.page_type,delete e.store_id,delete e.page_url,delete e.page_title,delete e.screen_name,delete e.referrer,delete e.funnel_step,delete e.funnel_step_number,["email","phone","password","ssn","credit_card","cvv"].forEach(n=>delete e[n]),e}trackSessionStart(){this.track("session_start",{platform:this.config.platform})}trackSessionEnd(){this.track("session_end",{}),this.flush(!0)}screenView(t,e={}){return this.currentScreenName=t,this.currentPageType=this.inferPageType(t),this.updateFunnelStep(this.currentPageType),this.track("screen_view",{screen_name:t,page_type:this.currentPageType,...e})}pageView(t={}){let e=t.pageType||t.page_type||"unknown";return this.currentPageType=e,this.updateFunnelStep(e),this.track("page_view",{page_type:e,...t})}inferPageType(t){let e=t.toLowerCase();return e.includes("menu")||e.includes("order")||e.includes("food")?"menu":e.includes("cart")||e.includes("basket")||e.includes("bag")?"cart":e.includes("checkout")||e.includes("payment")?"checkout":e.includes("confirm")||e.includes("success")||e.includes("thank")?"confirmation":e.includes("product")||e.includes("item")||e.includes("detail")?"product":e.includes("location")||e.includes("store")?"location":e.includes("account")||e.includes("profile")||e.includes("login")?"account":e.includes("reward")||e.includes("loyalty")||e.includes("point")?"rewards":e.includes("home")||e.includes("landing")?"home":"other"}updateFunnelStep(t){let e={home:{name:"landing",number:1},location:{name:"location",number:1},menu:{name:"menu",number:2},product:{name:"menu",number:2},cart:{name:"cart",number:3},checkout:{name:"checkout",number:4},confirmation:{name:"confirmation",number:5}};this.currentFunnelStep=e[t]||null}productView(t,e={}){return this.track("product_view",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,...e})}productClick(t,e={}){return this.track("product_click",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,...e})}addToCart(t,e=1,i={}){return this.cartState.itemCount+=e,this.cartState.total+=(t.price||0)*e,this.cartState.items.push({...t,quantity:e}),this.track("add_to_cart",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,quantity:e,...i})}removeFromCart(t,e=1,i={}){return this.cartState.itemCount=Math.max(0,this.cartState.itemCount-e),this.cartState.total=Math.max(0,this.cartState.total-(t.price||0)*e),this.track("remove_from_cart",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,quantity:e,...i})}updateCartQuantity(t,e,i){let n=i-e;return this.cartState.itemCount+=n,this.cartState.total+=(t.price||0)*n,this.track("update_cart_quantity",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,old_quantity:e,new_quantity:i})}setCart(t){return this.cartState={items:t.items||[],itemCount:t.itemCount||0,total:t.total||0},this}viewCart(t={}){return this.track("cart_view",{cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,...t})}checkoutStart(t={}){return this.updateFunnelStep("checkout"),this.track("checkout_start",{cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,...t})}checkoutStep(t,e={}){return this.track("checkout_step",{checkout_step:t,...e})}addPaymentInfo(t,e={}){return this.track("add_payment_info",{payment_method:t,funnel_step:"checkout_payment",funnel_step_number:4,...e})}checkoutComplete(t,e={}){this.updateFunnelStep("confirmation");let i=this.track("checkout_complete",{order_id:t.id||t.order_id,olo_order_id:t.olo_order_id,order_total:t.total,subtotal:t.subtotal,tax:t.tax,tip:t.tip,item_count:t.itemCount||t.item_count,order_type:t.orderType||t.order_type,payment_method:t.paymentMethod||t.payment_method,...e});return this.cartState={items:[],itemCount:0,total:0},i}loginAttempt(t,e={}){var i;return this.track("login_attempt",{login_method:t,funnel_step:(i=this.currentFunnelStep)==null?void 0:i.name,...e})}loginSuccess(t,e,i={}){var n,o;return this.sessionData.is_logged_in=!0,this.sessionData.login_method=t,this.sessionData.logged_in_at=u(),this.sessionData.login_funnel_step=((n=this.currentFunnelStep)==null?void 0:n.name)||null,e&&(this.customerId=e),this.saveSession(),this.track("login_success",{login_method:t,customer_id:e,funnel_step:(o=this.currentFunnelStep)==null?void 0:o.name,...i})}loginFailure(t,e,i={}){return this.track("login_failure",{login_method:t,error_message:e,...i})}logout(t={}){let e=this.customerId;return this.sessionData.is_logged_in=!1,this.customerId=null,this.saveSession(),this.track("logout",{previous_customer_id:e,...t})}identify(t,e={}){return this.customerId=t,this.sessionData.is_logged_in=!0,this.saveSession(),this.track("identify",{customer_id:t,traits:this.sanitizeProperties(e)})}storeSelect(t,e={}){let i=t.id||t.store_id,n=t.name||t.store_name;return i&&(this.config.storeId=i),n&&(this.config.storeName=n),this.track("store_select",{store_id:i,store_name:n,...e})}setStore(t,e){return this.config.storeId=t,e&&(this.config.storeName=e),this}search(t,e,i={}){return this.track("search",{search_query:t,result_count:e,...i})}loyaltyLogin(t,e={}){let i=t.id||t.customer_id;return i&&(this.customerId=i),this.track("loyalty_login",{customer_id:i,loyalty_tier:t.tier,points_balance:t.points,...e})}rewardView(t,e={}){return this.track("reward_view",{reward_id:t.id,reward_name:t.name,reward_value:t.value,points_required:t.points_required,...e})}rewardApply(t,e={}){return this.track("reward_apply",{reward_id:t.id,reward_name:t.name,reward_value:t.value,points_used:t.points_used,...e})}rewardRemove(t,e={}){return this.track("reward_remove",{reward_id:t.id,reward_name:t.name,...e})}promoApply(t,e={}){return this.track("promo_apply",{promo_code:t.code,discount_amount:t.discount,success:t.success,error_message:t.error,...e})}promoRemove(t,e={}){return this.track("promo_remove",{promo_code:t,...e})}setExperiment(t,e){return this.sessionData.experiment_assignments[t]=e,this.saveSession(),this.track("experiment_assigned",{experiment_key:t,variant_key:e})}error(t,e,i={}){return this.track("error",{error_type:t,error_message:e,...i})}queueEvent(t){this.eventQueue.push(t),this.eventQueue.length>=this.config.batchSize&&this.flush()}startFlushTimer(){this.flushTimer=setInterval(()=>{this.eventQueue.length>0&&this.flush()},this.config.flushInterval)}async flush(t=!1){if(this.eventQueue.length===0)return;let e=[...this.eventQueue];this.eventQueue=[];let i={batch_id:a(),tenant_slug:this.config.tenantSlug||this.config.tenantId,events:e,sent_at:u()};try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}),this.log("debug","Flushed events",{count:e.length})}catch(n){this.log("error","Failed to send events",n),this.eventQueue=[...e,...this.eventQueue]}}getSessionId(){return this.sessionId}getVisitorId(){return this.visitorId}getCustomerId(){return this.customerId}isLoggedIn(){return this.sessionData.is_logged_in}log(t,e,i){if(!this.config.debug&&t==="debug")return;let n="[VeyaAnalytics]";t==="error"?console.error(n,e,i||""):t==="warn"?console.warn(n,e,i||""):console.log(n,e,i||"")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush(!0)}};var y=class{async getItem(t){try{return localStorage.getItem(t)}catch{return null}}async setItem(t,e){try{localStorage.setItem(t,e)}catch{}}async removeItem(t){try{localStorage.removeItem(t)}catch{}}},V={menu:{urlPatterns:[/\/menu/i,/\/order/i,/\/food/i,/\/products/i],domSignals:["[data-product]",".menu-item",".product-card",".food-item"],titlePatterns:[/menu/i,/order/i,/food/i]},cart:{urlPatterns:[/\/cart/i,/\/basket/i,/\/bag/i],domSignals:[".cart-item",".basket-item","[data-cart]",".cart-summary"],titlePatterns:[/cart/i,/basket/i,/your order/i]},checkout:{urlPatterns:[/\/checkout/i,/\/payment/i,/\/pay\b/i],domSignals:["[data-checkout]",".checkout-form",".payment-form"],titlePatterns:[/checkout/i,/payment/i]},confirmation:{urlPatterns:[/\/confirm/i,/\/thank/i,/\/success/i],domSignals:[".confirmation",".order-confirmed",".thank-you"],titlePatterns:[/thank/i,/confirm/i,/success/i]},product:{urlPatterns:[/\/product\//i,/\/item\//i],domSignals:[".product-detail",".item-detail"],titlePatterns:[]},location:{urlPatterns:[/\/location/i,/\/store/i,/\/find/i],domSignals:[".store-locator",".location-picker"],titlePatterns:[/location/i,/find.*store/i]},account:{urlPatterns:[/\/account/i,/\/profile/i,/\/login/i,/\/signin/i],domSignals:[".login-form",".account-page"],titlePatterns:[/account/i,/sign in/i,/log in/i]},rewards:{urlPatterns:[/\/reward/i,/\/loyalty/i,/\/points/i],domSignals:[".rewards",".loyalty",".points-balance"],titlePatterns:[/reward/i,/loyalty/i]},home:{urlPatterns:[/^\/$/,/\/home/i],domSignals:[".hero",".home-banner"],titlePatterns:[]}},L=[25,50,75,100],h=class extends d{constructor(){super();this.pageDetectionCache=new Map;this.productTracker=null;this.cartTracker=null;this.networkInterceptor=null;this.pageStartedAt=Date.now();this.scrollDepthsFired=new Set;this.scrollCheckPending=!1;this.storage=new y}init(e){return super.init({...e,platform:"web"})}async onInitialized(){this.pageStartedAt=Date.now(),this.config.autoDetect&&this.setupPageChangeDetection(),this.config.autoTrackProducts&&(this.productTracker=new v(this),this.productTracker.init()),this.config.autoTrackCart&&(this.cartTracker=new b(this),this.cartTracker.init()),this.config.interceptOloApi&&(this.networkInterceptor=new w(this,this.config),this.networkInterceptor.init()),this.setupBrowserListeners(),this.config.autoDetect&&this.trackCurrentPage()}async getDeviceInfo(){let e=navigator.userAgent;return{device_type:this.getDeviceType(),platform:"web",os:this.getOS(),os_version:this.getOSVersion(),screen_width:window.screen.width,screen_height:window.screen.height,language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}getDeviceType(){let e=navigator.userAgent.toLowerCase(),i=window.innerWidth;return/ipad|tablet|playbook|silk/i.test(e)||i>=768&&i<1024?"tablet":/mobile|iphone|ipod|android|blackberry/i.test(e)||i<768?"mobile":"desktop"}getOS(){let e=navigator.userAgent;return/Windows/.test(e)?"Windows":/Mac OS X/.test(e)?"macOS":/Android/.test(e)?"Android":/iOS|iPhone|iPad/.test(e)?"iOS":/Linux/.test(e)?"Linux":"unknown"}getOSVersion(){let i=navigator.userAgent.match(/(?:Windows NT|Mac OS X|Android|iOS)\s*([\d._]+)/i);return i?i[1].replace(/_/g,"."):"unknown"}setupPageChangeDetection(){let e=window.location.href,i=()=>{window.location.href!==e&&(e=window.location.href,this.pageDetectionCache.clear(),this.trackCurrentPage(),this.productTracker&&this.productTracker.reset())};window.addEventListener("popstate",i);let n=history.pushState,o=history.replaceState;history.pushState=function(){n.apply(this,arguments),i()},history.replaceState=function(){o.apply(this,arguments),i()},window.addEventListener("hashchange",i)}detectPageType(){let e=window.location.pathname+document.title;if(this.pageDetectionCache.has(e))return this.pageDetectionCache.get(e);let i=window.location.href.toLowerCase(),n=window.location.pathname.toLowerCase(),o=document.title.toLowerCase(),k={};for(let[_,c]of Object.entries(V)){let m=0;for(let l of c.urlPatterns)if(l.test(n)){m+=40;break}let I=0;for(let l of c.domSignals)try{document.querySelector(l)&&I++}catch{}c.domSignals.length>0&&(m+=I/c.domSignals.length*40);for(let l of c.titlePatterns)if(l.test(o)){m+=20;break}k[_]=m/100}let P="unknown",g=0;for(let[_,c]of Object.entries(k))c>g&&(g=c,P=_);let f={type:g>=(this.config.confidenceThreshold||.7)?P:"unknown",confidence:g};return this.pageDetectionCache.set(e,f),this.currentPageType=f.type,f}trackCurrentPage(){let e=this.detectPageType();this.pageView({page_url:window.location.href,page_title:document.title,page_type:e.type,page_type_confidence:e.confidence,referrer:document.referrer,...this.getUTMParams()})}pageView(e={}){return this.pageStartedAt=Date.now(),this.scrollDepthsFired.clear(),super.pageView(e)}getUTMParams(){let e=new URLSearchParams(window.location.search);return{utm_source:e.get("utm_source"),utm_medium:e.get("utm_medium"),utm_campaign:e.get("utm_campaign"),utm_term:e.get("utm_term"),utm_content:e.get("utm_content")}}setupBrowserListeners(){document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(this.track("page_hidden",{time_on_page:this.timeOnPage()}),this.flush(!0)):document.visibilityState==="visible"&&this.track("page_visible")}),window.addEventListener("beforeunload",()=>{this.track("page_unload",{time_on_page:this.timeOnPage()}),this.flush(!0)}),window.addEventListener("scroll",()=>{this.scrollCheckPending||(this.scrollCheckPending=!0,setTimeout(()=>{this.scrollCheckPending=!1,this.checkScrollDepth()},100))},{passive:!0}),window.addEventListener("error",e=>{this.error("javascript",e.message,{filename:e.filename,lineno:e.lineno,colno:e.colno})}),window.addEventListener("unhandledrejection",e=>{var i;this.error("promise_rejection",((i=e.reason)==null?void 0:i.message)||String(e.reason))})}timeOnPage(){return Math.max(0,Date.now()-this.pageStartedAt)}checkScrollDepth(){let e=document.documentElement.scrollHeight-window.innerHeight;if(e<=0)return;let i=Math.min(100,Math.round(window.scrollY/e*100));for(let n of L)i>=n&&!this.scrollDepthsFired.has(n)&&(this.scrollDepthsFired.add(n),this.track("scroll_depth",{depth:n}))}async flush(e=!1){if(this.eventQueue.length===0)return;let i=[...this.eventQueue];this.eventQueue=[];let n={batch_id:a(),tenant_slug:this.config.tenantSlug||this.config.tenantId,events:i,sent_at:u()};if(e&&navigator.sendBeacon)navigator.sendBeacon(this.config.endpoint,JSON.stringify(n));else try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0})}catch{this.eventQueue=[...i,...this.eventQueue]}}destroy(){this.productTracker&&this.productTracker.destroy(),this.cartTracker&&this.cartTracker.destroy(),this.networkInterceptor&&this.networkInterceptor.destroy(),super.destroy()}},v=class{constructor(t){this.viewedProducts=new Set;this.observer=null;this.intersectionObserver=null;this.sdk=t}init(){this.intersectionObserver=new IntersectionObserver(this.handleIntersection.bind(this),{threshold:.5}),this.scanForProducts(),this.observer=new MutationObserver(()=>{setTimeout(()=>this.scanForProducts(),500)}),this.observer.observe(document.body,{childList:!0,subtree:!0})}scanForProducts(){let t=["[data-product-id]","[data-product]",".product-card",".menu-item",".food-item"];for(let e of t)try{document.querySelectorAll(e).forEach(i=>{var n;i.dataset.veyaTracked||(i.dataset.veyaTracked="true",(n=this.intersectionObserver)==null||n.observe(i))})}catch{}}handleIntersection(t){t.forEach(e=>{if(e.isIntersecting){let i=this.extractProductData(e.target);i.name&&!this.viewedProducts.has(i.id||i.name)&&(this.viewedProducts.add(i.id||i.name),this.sdk.productView(i,{auto:!0}))}})}extractProductData(t){var e,i;return{id:t.dataset.productId||t.dataset.id||t.id,name:t.dataset.productName||t.dataset.name||((i=(e=t.querySelector(".product-name, .item-name, h2, h3"))==null?void 0:e.textContent)==null?void 0:i.trim()),category:t.dataset.category,price:parseFloat(t.dataset.price||"0")||null}}reset(){this.viewedProducts.clear(),this.scanForProducts()}destroy(){var t,e;(t=this.observer)==null||t.disconnect(),(e=this.intersectionObserver)==null||e.disconnect()}},b=class{constructor(t){this.observer=null;this.sdk=t}init(){let t=[".cart",".basket","#cart","[data-cart]"];this.observer=new MutationObserver(()=>{});for(let e of t){let i=document.querySelector(e);if(i){this.observer.observe(i,{childList:!0,subtree:!0});break}}}destroy(){var t;(t=this.observer)==null||t.disconnect()}},w=class{constructor(t,e){this.originalFetch=null;this.sdk=t,this.config=e}init(){this.originalFetch=window.fetch;let t=this;window.fetch=function(e,i){let n=typeof e=="string"?e:e instanceof URL?e.toString():e.url;return t.originalFetch.apply(window,[e,i]).then(o=>(t.handleResponse(n,o.clone()),o))}}async handleResponse(t,e){if(this.isOloApi(t))try{let i=await e.json();t.includes("order")&&i.id&&this.sdk.checkoutComplete({id:i.id,olo_order_id:i.id,total:i.total,orderType:i.deliveryMode||i.type},{auto:!0}),t.includes("basket")&&i.products&&this.sdk.setCart({items:i.products,total:i.total||i.subtotal,itemCount:i.products.reduce((n,o)=>n+(o.quantity||1),0)})}catch{}}isOloApi(t){return[/\/basket/i,/\/order/i,/olo\.com/i].some(i=>i.test(t))}destroy(){this.originalFetch&&(window.fetch=this.originalFetch)}},S=new h;typeof window!="undefined"&&(window.VeyaAnalytics=S,window.veya=S);var T=S;return F(M);})();
|
|
1
|
+
/*! @builtonveya/analytics-web v4.0.2 — https://github.com/adam-3owl/veya-analytics-api */
|
|
2
|
+
"use strict";var VeyaAnalyticsSDK=(()=>{var p=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var O=(r,t,e)=>t in r?p(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var A=(r,t)=>{for(var e in t)p(r,e,{get:t[e],enumerable:!0})},E=(r,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of D(t))!R.call(r,n)&&n!==e&&p(r,n,{get:()=>t[n],enumerable:!(i=C(t,n))||i.enumerable});return r};var F=r=>E(p({},"__esModule",{value:!0}),r);var s=(r,t,e)=>O(r,typeof t!="symbol"?t+"":t,e);var M={};A(M,{VeyaAnalyticsCore:()=>u,VeyaAnalyticsWeb:()=>h,default:()=>x,generateUUID:()=>a,getTimestamp:()=>d});var T={tenantSlug:"",tenantId:"",storeId:"",storeName:"",endpoint:"https://analytics.builtonveya.com/v1/events",batchSize:10,flushInterval:5e3,sessionTimeout:18e5,debug:!1,autoDetect:!0,autoTrackProducts:!0,autoTrackCart:!0,interceptOloApi:!1,confidenceThreshold:.7,platform:"web"};function a(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let t=Math.random()*16|0;return(r==="x"?t:t&3|8).toString(16)})}function d(){return new Date().toISOString()}var u=class{constructor(){s(this,"config");s(this,"initialized",!1);s(this,"initPromise",null);s(this,"eventQueue",[]);s(this,"flushTimer",null);s(this,"sessionId","");s(this,"visitorId","");s(this,"customerId",null);s(this,"sessionData",{is_logged_in:!1,login_method:null,logged_in_at:null,login_funnel_step:null,experiment_assignments:{}});s(this,"cartState",{items:[],itemCount:0,total:0});s(this,"deviceInfo",null);s(this,"currentScreenName","");s(this,"currentPageType","");s(this,"currentFunnelStep",null);s(this,"storage",null);this.config={...T}}init(t){return this.initPromise?(this.initialized&&this.log("warn","SDK already initialized"),this.initPromise):(this.initPromise=this.runInit(t).catch(e=>{throw this.initialized||(this.initPromise=null),e}),this.initPromise)}async runInit(t){if(!t.tenantSlug&&!t.tenantId)throw new Error("VeyaAnalytics: tenantSlug is required");this.config={...T,...t},this.config.tenantSlug||(this.config.tenantSlug=this.config.tenantId),await this.initVisitor();let e=await this.initSession();this.deviceInfo=await this.getDeviceInfo(),this.startFlushTimer(),this.initialized=!0,e&&this.trackSessionStart(),this.log("info","VeyaAnalytics initialized",{tenantSlug:this.config.tenantSlug,visitorId:this.visitorId,sessionId:this.sessionId,platform:this.config.platform,newSession:e});try{await this.onInitialized()}catch(i){this.log("error","Platform setup failed",i)}return this}async onInitialized(){}async initVisitor(){if(!this.storage){this.visitorId=a();return}let t=await this.storage.getItem("veya_visitor_id");t?this.visitorId=t:(this.visitorId=a(),await this.storage.setItem("veya_visitor_id",this.visitorId))}async initSession(){if(!this.storage)return this.sessionId=a(),!0;let t=await this.storage.getItem("veya_session"),e=Date.now();if(t)try{let i=JSON.parse(t);if(e-i.lastActivity<this.config.sessionTimeout)return this.sessionId=i.sessionId,this.sessionData={...this.sessionData,...i.data},await this.saveSession(),!1}catch{}return this.sessionId=a(),await this.saveSession(),!0}async saveSession(){this.storage&&await this.storage.setItem("veya_session",JSON.stringify({sessionId:this.sessionId,lastActivity:Date.now(),data:this.sessionData}))}async getDeviceInfo(){return{device_type:"unknown",platform:this.config.platform||"unknown",os:"unknown",screen_width:0,screen_height:0,language:"en",timezone:"UTC"}}track(t,e={}){if(!this.initialized)return this.log("warn","SDK not initialized"),this;let i=this.buildEvent(t,e);return this.queueEvent(i),this.log("debug","Event tracked",i),this}buildEvent(t,e){var i,n;return{event_id:a(),event_name:t,event_category:e.category||this.inferCategory(t),event_timestamp:d(),tenant_id:this.config.tenantSlug||this.config.tenantId||"",tenant_slug:this.config.tenantSlug||this.config.tenantId||"",session_id:this.sessionId,visitor_id:this.visitorId,customer_id:this.customerId||void 0,store_id:this.config.storeId||e.store_id,store_name:this.config.storeName||e.store_name,page_url:e.page_url,page_title:e.page_title,page_type:e.page_type||this.currentPageType,screen_name:e.screen_name||this.currentScreenName,referrer:e.referrer,...this.deviceInfo,is_logged_in:this.sessionData.is_logged_in,login_method:this.sessionData.login_method||void 0,funnel_step:e.funnel_step||((i=this.currentFunnelStep)==null?void 0:i.name),funnel_step_number:e.funnel_step_number||((n=this.currentFunnelStep)==null?void 0:n.number),cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,experiment_assignments:this.sessionData.experiment_assignments,properties:this.sanitizeProperties(e)}}inferCategory(t){return t.includes("cart")?"cart":t.includes("checkout")||t.includes("order")?"checkout":t.includes("product")||t.includes("menu")?"catalog":t.includes("login")||t.includes("auth")?"auth":t.includes("error")?"error":t.includes("screen")||t.includes("page")||t.includes("session")?"navigation":"engagement"}sanitizeProperties(t){let e={...t};return delete e.category,delete e.page_type,delete e.store_id,delete e.page_url,delete e.page_title,delete e.screen_name,delete e.referrer,delete e.funnel_step,delete e.funnel_step_number,["email","phone","password","ssn","credit_card","cvv","address","street","postal_code","zip"].forEach(n=>delete e[n]),e}trackSessionStart(){this.track("session_start",{platform:this.config.platform})}trackSessionEnd(){this.track("session_end",{}),this.flush(!0)}screenView(t,e={}){return this.currentScreenName=t,this.currentPageType=this.inferPageType(t),this.updateFunnelStep(this.currentPageType),this.track("screen_view",{screen_name:t,page_type:this.currentPageType,...e})}pageView(t={}){let e=t.pageType||t.page_type||"unknown";return this.currentPageType=e,this.updateFunnelStep(e),this.track("page_view",{page_type:e,...t})}inferPageType(t){let e=t.toLowerCase();return e.includes("menu")||e.includes("order")||e.includes("food")?"menu":e.includes("cart")||e.includes("basket")||e.includes("bag")?"cart":e.includes("checkout")||e.includes("payment")?"checkout":e.includes("confirm")||e.includes("success")||e.includes("thank")?"confirmation":e.includes("product")||e.includes("item")||e.includes("detail")?"product":e.includes("location")||e.includes("store")?"location":e.includes("account")||e.includes("profile")||e.includes("login")?"account":e.includes("reward")||e.includes("loyalty")||e.includes("point")?"rewards":e.includes("home")||e.includes("landing")?"home":"other"}updateFunnelStep(t){let e={home:{name:"landing",number:1},location:{name:"location",number:1},menu:{name:"menu",number:2},product:{name:"menu",number:2},cart:{name:"cart",number:3},checkout:{name:"checkout",number:4},confirmation:{name:"confirmation",number:5}};this.currentFunnelStep=e[t]||null}productView(t,e={}){return this.track("product_view",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,...e})}productClick(t,e={}){return this.track("product_click",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,...e})}addToCart(t,e=1,i={}){return this.cartState.itemCount+=e,this.cartState.total+=(t.price||0)*e,this.cartState.items.push({...t,quantity:e}),this.track("add_to_cart",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,quantity:e,...i})}removeFromCart(t,e=1,i={}){return this.cartState.itemCount=Math.max(0,this.cartState.itemCount-e),this.cartState.total=Math.max(0,this.cartState.total-(t.price||0)*e),this.track("remove_from_cart",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,product_category:t.category,product_price:t.price,quantity:e,...i})}updateCartQuantity(t,e,i){let n=i-e;return this.cartState.itemCount+=n,this.cartState.total+=(t.price||0)*n,this.track("update_cart_quantity",{product_id:t.id||t.product_id,product_name:t.name||t.product_name,old_quantity:e,new_quantity:i})}setCart(t){return this.cartState={items:t.items||[],itemCount:t.itemCount||0,total:t.total||0},this}viewCart(t={}){return this.track("cart_view",{cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,...t})}checkoutStart(t={}){return this.updateFunnelStep("checkout"),this.track("checkout_start",{cart_value:this.cartState.total,cart_item_count:this.cartState.itemCount,...t})}checkoutStep(t,e={}){return this.track("checkout_step",{checkout_step:t,...e})}addPaymentInfo(t,e={}){return this.track("add_payment_info",{payment_method:t,funnel_step:"checkout_payment",funnel_step_number:4,...e})}checkoutComplete(t,e={}){this.updateFunnelStep("confirmation");let i=this.track("checkout_complete",{order_id:t.id||t.order_id,olo_order_id:t.olo_order_id,order_total:t.total,subtotal:t.subtotal,tax:t.tax,tip:t.tip,item_count:t.itemCount||t.item_count,order_type:t.orderType||t.order_type,payment_method:t.paymentMethod||t.payment_method,...e});return this.cartState={items:[],itemCount:0,total:0},i}loginAttempt(t,e={}){var i;return this.track("login_attempt",{login_method:t,funnel_step:(i=this.currentFunnelStep)==null?void 0:i.name,...e})}loginSuccess(t,e,i={}){var n,o;return this.sessionData.is_logged_in=!0,this.sessionData.login_method=t,this.sessionData.logged_in_at=d(),this.sessionData.login_funnel_step=((n=this.currentFunnelStep)==null?void 0:n.name)||null,e&&(this.customerId=e),this.saveSession(),this.track("login_success",{login_method:t,customer_id:e,funnel_step:(o=this.currentFunnelStep)==null?void 0:o.name,...i})}loginFailure(t,e,i={}){return this.track("login_failure",{login_method:t,error_message:e,...i})}logout(t={}){let e=this.customerId;return this.sessionData.is_logged_in=!1,this.customerId=null,this.saveSession(),this.track("logout",{previous_customer_id:e,...t})}identify(t,e={}){return this.customerId=t,this.sessionData.is_logged_in=!0,this.saveSession(),this.track("identify",{customer_id:t,traits:this.sanitizeProperties(e)})}storeSelect(t,e={}){let i=t.id||t.store_id,n=t.name||t.store_name;return i&&(this.config.storeId=i),n&&(this.config.storeName=n),this.track("store_select",{store_id:i,store_name:n,...e})}setStore(t,e){return this.config.storeId=t,e&&(this.config.storeName=e),this}search(t,e,i={}){return this.track("search",{search_query:t,result_count:e,...i})}loyaltyLogin(t,e={}){let i=t.id||t.customer_id;return i&&(this.customerId=i),this.track("loyalty_login",{customer_id:i,loyalty_tier:t.tier,points_balance:t.points,...e})}rewardView(t,e={}){return this.track("reward_view",{reward_id:t.id,reward_name:t.name,reward_value:t.value,points_required:t.points_required,...e})}rewardApply(t,e={}){return this.track("reward_apply",{reward_id:t.id,reward_name:t.name,reward_value:t.value,points_used:t.points_used,...e})}rewardRemove(t,e={}){return this.track("reward_remove",{reward_id:t.id,reward_name:t.name,...e})}promoApply(t,e={}){return this.track("promo_apply",{promo_code:t.code,discount_amount:t.discount,success:t.success,error_message:t.error,...e})}promoRemove(t,e={}){return this.track("promo_remove",{promo_code:t,...e})}setExperiment(t,e){return this.sessionData.experiment_assignments[t]=e,this.saveSession(),this.track("experiment_assigned",{experiment_key:t,variant_key:e})}error(t,e,i={}){return this.track("error",{error_type:t,error_message:e,...i})}queueEvent(t){this.eventQueue.push(t),this.eventQueue.length>=this.config.batchSize&&this.flush()}startFlushTimer(){this.flushTimer=setInterval(()=>{this.eventQueue.length>0&&this.flush()},this.config.flushInterval)}async flush(t=!1){if(this.eventQueue.length===0)return;let e=[...this.eventQueue];this.eventQueue=[];let i={batch_id:a(),tenant_slug:this.config.tenantSlug||this.config.tenantId,events:e,sent_at:d()};try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}),this.log("debug","Flushed events",{count:e.length})}catch(n){this.log("error","Failed to send events",n),this.eventQueue=[...e,...this.eventQueue]}}getSessionId(){return this.sessionId}getVisitorId(){return this.visitorId}getCustomerId(){return this.customerId}isLoggedIn(){return this.sessionData.is_logged_in}log(t,e,i){if(!this.config.debug&&t==="debug")return;let n="[VeyaAnalytics]";t==="error"?console.error(n,e,i||""):t==="warn"?console.warn(n,e,i||""):console.log(n,e,i||"")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush(!0)}};var y=class{async getItem(t){try{return localStorage.getItem(t)}catch{return null}}async setItem(t,e){try{localStorage.setItem(t,e)}catch{}}async removeItem(t){try{localStorage.removeItem(t)}catch{}}},V={menu:{urlPatterns:[/\/menu/i,/\/order/i,/\/food/i,/\/products/i],domSignals:["[data-product]",".menu-item",".product-card",".food-item"],titlePatterns:[/menu/i,/order/i,/food/i]},cart:{urlPatterns:[/\/cart/i,/\/basket/i,/\/bag/i],domSignals:[".cart-item",".basket-item","[data-cart]",".cart-summary"],titlePatterns:[/cart/i,/basket/i,/your order/i]},checkout:{urlPatterns:[/\/checkout/i,/\/payment/i,/\/pay\b/i],domSignals:["[data-checkout]",".checkout-form",".payment-form"],titlePatterns:[/checkout/i,/payment/i]},confirmation:{urlPatterns:[/\/confirm/i,/\/thank/i,/\/success/i],domSignals:[".confirmation",".order-confirmed",".thank-you"],titlePatterns:[/thank/i,/confirm/i,/success/i]},product:{urlPatterns:[/\/product\//i,/\/item\//i],domSignals:[".product-detail",".item-detail"],titlePatterns:[]},location:{urlPatterns:[/\/location/i,/\/store/i,/\/find/i],domSignals:[".store-locator",".location-picker"],titlePatterns:[/location/i,/find.*store/i]},account:{urlPatterns:[/\/account/i,/\/profile/i,/\/login/i,/\/signin/i],domSignals:[".login-form",".account-page"],titlePatterns:[/account/i,/sign in/i,/log in/i]},rewards:{urlPatterns:[/\/reward/i,/\/loyalty/i,/\/points/i],domSignals:[".rewards",".loyalty",".points-balance"],titlePatterns:[/reward/i,/loyalty/i]},home:{urlPatterns:[/^\/$/,/\/home/i],domSignals:[".hero",".home-banner"],titlePatterns:[]}},L=[25,50,75,100],h=class extends u{constructor(){super();this.pageDetectionCache=new Map;this.productTracker=null;this.cartTracker=null;this.networkInterceptor=null;this.pageStartedAt=Date.now();this.scrollDepthsFired=new Set;this.scrollCheckPending=!1;this.storage=new y}init(e){return super.init({...e,platform:"web"})}async onInitialized(){this.pageStartedAt=Date.now(),this.config.autoDetect&&this.setupPageChangeDetection(),this.config.autoTrackProducts&&(this.productTracker=new v(this),this.productTracker.init()),this.config.autoTrackCart&&(this.cartTracker=new w(this),this.cartTracker.init()),this.config.interceptOloApi&&(this.networkInterceptor=new b(this,this.config),this.networkInterceptor.init()),this.setupBrowserListeners(),this.config.autoDetect&&this.trackCurrentPage()}async getDeviceInfo(){let e=navigator.userAgent;return{device_type:this.getDeviceType(),platform:"web",os:this.getOS(),os_version:this.getOSVersion(),screen_width:window.screen.width,screen_height:window.screen.height,language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}}getDeviceType(){let e=navigator.userAgent.toLowerCase(),i=window.innerWidth;return/ipad|tablet|playbook|silk/i.test(e)||i>=768&&i<1024?"tablet":/mobile|iphone|ipod|android|blackberry/i.test(e)||i<768?"mobile":"desktop"}getOS(){let e=navigator.userAgent;return/Windows/.test(e)?"Windows":/Mac OS X/.test(e)?"macOS":/Android/.test(e)?"Android":/iOS|iPhone|iPad/.test(e)?"iOS":/Linux/.test(e)?"Linux":"unknown"}getOSVersion(){let i=navigator.userAgent.match(/(?:Windows NT|Mac OS X|Android|iOS)\s*([\d._]+)/i);return i?i[1].replace(/_/g,"."):"unknown"}setupPageChangeDetection(){let e=window.location.href,i=()=>{window.location.href!==e&&(e=window.location.href,this.pageDetectionCache.clear(),this.trackCurrentPage(),this.productTracker&&this.productTracker.reset())};window.addEventListener("popstate",i);let n=history.pushState,o=history.replaceState;history.pushState=function(){n.apply(this,arguments),i()},history.replaceState=function(){o.apply(this,arguments),i()},window.addEventListener("hashchange",i)}detectPageType(){let e=window.location.pathname+document.title;if(this.pageDetectionCache.has(e))return this.pageDetectionCache.get(e);let i=window.location.href.toLowerCase(),n=window.location.pathname.toLowerCase(),o=document.title.toLowerCase(),k={};for(let[_,c]of Object.entries(V)){let m=0;for(let l of c.urlPatterns)if(l.test(n)){m+=40;break}let I=0;for(let l of c.domSignals)try{document.querySelector(l)&&I++}catch{}c.domSignals.length>0&&(m+=I/c.domSignals.length*40);for(let l of c.titlePatterns)if(l.test(o)){m+=20;break}k[_]=m/100}let P="unknown",g=0;for(let[_,c]of Object.entries(k))c>g&&(g=c,P=_);let f={type:g>=(this.config.confidenceThreshold||.7)?P:"unknown",confidence:g};return this.pageDetectionCache.set(e,f),this.currentPageType=f.type,f}trackCurrentPage(){let e=this.detectPageType();this.pageView({page_url:window.location.href,page_title:document.title,page_type:e.type,page_type_confidence:e.confidence,referrer:document.referrer,...this.getUTMParams()})}pageView(e={}){return this.pageStartedAt=Date.now(),this.scrollDepthsFired.clear(),super.pageView(e)}getUTMParams(){let e=new URLSearchParams(window.location.search);return{utm_source:e.get("utm_source"),utm_medium:e.get("utm_medium"),utm_campaign:e.get("utm_campaign"),utm_term:e.get("utm_term"),utm_content:e.get("utm_content")}}setupBrowserListeners(){document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?(this.track("page_hidden",{time_on_page:this.timeOnPage()}),this.flush(!0)):document.visibilityState==="visible"&&this.track("page_visible")}),window.addEventListener("pagehide",e=>{this.track("page_unload",{time_on_page:this.timeOnPage(),persisted:e.persisted}),this.flush(!0)}),window.addEventListener("pageshow",e=>{e.persisted&&(this.pageStartedAt=Date.now(),this.scrollDepthsFired.clear(),this.config.autoDetect&&this.trackCurrentPage())}),window.addEventListener("scroll",()=>{this.scrollCheckPending||(this.scrollCheckPending=!0,setTimeout(()=>{this.scrollCheckPending=!1,this.checkScrollDepth()},100))},{passive:!0}),window.addEventListener("error",e=>{this.error("javascript",e.message,{filename:e.filename,lineno:e.lineno,colno:e.colno})}),window.addEventListener("unhandledrejection",e=>{var i;this.error("promise_rejection",((i=e.reason)==null?void 0:i.message)||String(e.reason))})}timeOnPage(){return Math.max(0,Date.now()-this.pageStartedAt)}checkScrollDepth(){let e=document.documentElement.scrollHeight-window.innerHeight;if(e<=0)return;let i=Math.min(100,Math.round(window.scrollY/e*100));for(let n of L)i>=n&&!this.scrollDepthsFired.has(n)&&(this.scrollDepthsFired.add(n),this.track("scroll_depth",{depth:n}))}async flush(e=!1){if(this.eventQueue.length===0)return;let i=[...this.eventQueue];this.eventQueue=[];let n={batch_id:a(),tenant_slug:this.config.tenantSlug||this.config.tenantId,events:i,sent_at:d()};if(e&&navigator.sendBeacon)navigator.sendBeacon(this.config.endpoint,JSON.stringify(n));else try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),keepalive:!0})}catch{this.eventQueue=[...i,...this.eventQueue]}}destroy(){this.productTracker&&this.productTracker.destroy(),this.cartTracker&&this.cartTracker.destroy(),this.networkInterceptor&&this.networkInterceptor.destroy(),super.destroy()}},v=class{constructor(t){this.viewedProducts=new Set;this.observer=null;this.intersectionObserver=null;this.sdk=t}init(){this.intersectionObserver=new IntersectionObserver(this.handleIntersection.bind(this),{threshold:.5}),this.scanForProducts(),this.observer=new MutationObserver(()=>{setTimeout(()=>this.scanForProducts(),500)}),this.observer.observe(document.body,{childList:!0,subtree:!0})}scanForProducts(){let t=["[data-product-id]","[data-product]",".product-card",".menu-item",".food-item"];for(let e of t)try{document.querySelectorAll(e).forEach(i=>{var n;i.dataset.veyaTracked||(i.dataset.veyaTracked="true",(n=this.intersectionObserver)==null||n.observe(i))})}catch{}}handleIntersection(t){t.forEach(e=>{if(e.isIntersecting){let i=this.extractProductData(e.target);i.name&&!this.viewedProducts.has(i.id||i.name)&&(this.viewedProducts.add(i.id||i.name),this.sdk.productView(i,{auto:!0}))}})}extractProductData(t){var e,i;return{id:t.dataset.productId||t.dataset.id||t.id,name:t.dataset.productName||t.dataset.name||((i=(e=t.querySelector(".product-name, .item-name, h2, h3"))==null?void 0:e.textContent)==null?void 0:i.trim()),category:t.dataset.category,price:parseFloat(t.dataset.price||"0")||null}}reset(){this.viewedProducts.clear(),this.scanForProducts()}destroy(){var t,e;(t=this.observer)==null||t.disconnect(),(e=this.intersectionObserver)==null||e.disconnect()}},w=class{constructor(t){this.observer=null;this.sdk=t}init(){let t=[".cart",".basket","#cart","[data-cart]"];this.observer=new MutationObserver(()=>{});for(let e of t){let i=document.querySelector(e);if(i){this.observer.observe(i,{childList:!0,subtree:!0});break}}}destroy(){var t;(t=this.observer)==null||t.disconnect()}},b=class{constructor(t,e){this.originalFetch=null;this.sdk=t,this.config=e}init(){this.originalFetch=window.fetch;let t=this;window.fetch=function(e,i){let n=typeof e=="string"?e:e instanceof URL?e.toString():e.url;return t.originalFetch.apply(window,[e,i]).then(o=>(t.handleResponse(n,o.clone()),o))}}async handleResponse(t,e){if(this.isOloApi(t))try{let i=await e.json();t.includes("order")&&i.id&&this.sdk.checkoutComplete({id:i.id,olo_order_id:i.id,total:i.total,orderType:i.deliveryMode||i.type},{auto:!0}),t.includes("basket")&&i.products&&this.sdk.setCart({items:i.products,total:i.total||i.subtotal,itemCount:i.products.reduce((n,o)=>n+(o.quantity||1),0)})}catch{}}isOloApi(t){return[/\/basket/i,/\/order/i,/olo\.com/i].some(i=>i.test(t))}destroy(){this.originalFetch&&(window.fetch=this.originalFetch)}},S=new h;typeof window!="undefined"&&(window.VeyaAnalytics=S,window.veya=S);var x=S;return F(M);})();
|
|
3
3
|
//# sourceMappingURL=veya-analytics.min.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.ts", "../../core/VeyaAnalyticsCore.ts", "../VeyaAnalyticsWeb.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Veya Analytics SDK for the web (browsers)\n *\n * @example\n * ```ts\n * import veya from '@builtonveya/analytics-web';\n *\n * await veya.init({ tenantSlug: 'your-tenant-slug' });\n * veya.addToCart({ id: 'sku-1', name: 'Workout Smoothie', price: 12.95 }, 1);\n * ```\n *\n * The default export is a ready-made singleton; `VeyaAnalyticsWeb` is exported for\n * consumers that want their own instance. Importing this module is safe in server-side\n * rendering: it only touches `window` when one exists (to expose `window.veya` for\n * script-tag users), and nothing runs against the DOM until `init()` is called.\n */\nexport { default, VeyaAnalyticsWeb } from './VeyaAnalyticsWeb.js';\nexport { VeyaAnalyticsCore, generateUUID, getTimestamp } from '../core/VeyaAnalyticsCore.js';\nexport type {\n VeyaConfig,\n Product,\n CartState,\n Order,\n SessionData,\n DeviceInfo,\n Event,\n StorageAdapter,\n} from '../core/VeyaAnalyticsCore.js';\n", "/**\n * Veya Analytics SDK - Core\n * Platform-agnostic core that works on Web and React Native\n * \n * @version 4.0.1\n */\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface VeyaConfig {\n tenantSlug?: string;\n tenantId?: string;\n storeId?: string;\n storeName?: string;\n endpoint?: string;\n aiEndpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n sessionTimeout?: number;\n debug?: boolean;\n autoDetect?: boolean;\n autoTrackProducts?: boolean;\n autoTrackCart?: boolean;\n interceptOloApi?: boolean;\n useAiClassification?: boolean;\n confidenceThreshold?: number;\n platform?: 'web' | 'ios' | 'android';\n}\n\nexport interface Product {\n id?: string;\n product_id?: string;\n name?: string;\n product_name?: string;\n category?: string;\n price?: number;\n quantity?: number;\n [key: string]: any;\n}\n\nexport interface CartState {\n items: Product[];\n itemCount: number;\n total: number;\n}\n\nexport interface Order {\n id?: string;\n order_id?: string;\n olo_order_id?: string;\n total?: number;\n subtotal?: number;\n tax?: number;\n tip?: number;\n itemCount?: number;\n item_count?: number;\n orderType?: string;\n order_type?: string;\n paymentMethod?: string;\n payment_method?: string;\n [key: string]: any;\n}\n\nexport interface SessionData {\n is_logged_in: boolean;\n login_method: string | null;\n logged_in_at: string | null;\n login_funnel_step: string | null;\n experiment_assignments: Record<string, string>;\n}\n\nexport interface DeviceInfo {\n device_type: string;\n platform: string;\n os: string;\n os_version?: string;\n app_version?: string;\n screen_width: number;\n screen_height: number;\n language: string;\n timezone: string;\n}\n\nexport interface Event {\n event_id: string;\n event_name: string;\n event_category?: string;\n event_timestamp: string;\n tenant_id: string;\n tenant_slug: string;\n session_id: string;\n visitor_id: string;\n customer_id?: string;\n store_id?: string;\n store_name?: string;\n page_url?: string;\n page_title?: string;\n page_type?: string;\n screen_name?: string;\n referrer?: string;\n device_type?: string;\n platform?: string;\n os?: string;\n os_version?: string;\n app_version?: string;\n screen_width?: number;\n screen_height?: number;\n language?: string;\n timezone?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_term?: string;\n utm_content?: string;\n is_logged_in?: boolean;\n login_method?: string;\n funnel_step?: string;\n funnel_step_number?: number;\n cart_value?: number;\n cart_item_count?: number;\n experiment_assignments?: Record<string, string>;\n properties?: Record<string, any>;\n}\n\n// Storage interface - implemented differently for web vs React Native\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n// ============================================================================\n// DEFAULT CONFIG\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<VeyaConfig> = {\n tenantSlug: '',\n tenantId: '',\n storeId: '',\n storeName: '',\n endpoint: 'https://analytics.builtonveya.com/v1/events',\n aiEndpoint: 'https://analytics.veya.io/v1/classify',\n batchSize: 10,\n flushInterval: 5000,\n sessionTimeout: 30 * 60 * 1000,\n debug: false,\n autoDetect: true,\n autoTrackProducts: true,\n autoTrackCart: true,\n // Opt-in: patches window.fetch and reads order/basket responses as placed orders\n interceptOloApi: false,\n useAiClassification: true,\n confidenceThreshold: 0.7,\n platform: 'web'\n};\n\n// ============================================================================\n// UTILITIES\n// ============================================================================\n\nexport function generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\nexport function getTimestamp(): string {\n return new Date().toISOString();\n}\n\n// ============================================================================\n// CORE ANALYTICS CLASS\n// ============================================================================\n\nexport class VeyaAnalyticsCore {\n protected config: Required<VeyaConfig>;\n protected initialized: boolean = false;\n // The in-flight (or completed) init run, shared by every init() call \u2014 see init()\n private initPromise: Promise<this> | null = null;\n protected eventQueue: Event[] = [];\n protected flushTimer: any = null;\n \n // Identifiers\n protected sessionId: string = '';\n protected visitorId: string = '';\n protected customerId: string | null = null;\n \n // State\n protected sessionData: SessionData = {\n is_logged_in: false,\n login_method: null,\n logged_in_at: null,\n login_funnel_step: null,\n experiment_assignments: {}\n };\n \n protected cartState: CartState = {\n items: [],\n itemCount: 0,\n total: 0\n };\n \n protected deviceInfo: DeviceInfo | null = null;\n protected currentScreenName: string = '';\n protected currentPageType: string = '';\n protected currentFunnelStep: { name: string; number: number } | null = null;\n \n // Storage adapter - must be set by platform-specific implementation\n protected storage: StorageAdapter | null = null;\n\n constructor() {\n this.config = { ...DEFAULT_CONFIG };\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n /**\n * Initialize the SDK. Safe to call more than once: a call made while another is still in\n * flight shares that run (React StrictMode's double effects, or two call sites, can't set up\n * listeners or send session_start twice), and a call after a successful init resolves at once.\n * A failed init (e.g. a missing tenantSlug) can be retried with corrected options.\n *\n * Platform SDKs set their platform by overriding init() and passing it through, and do their\n * own setup in onInitialized(), which runs exactly once.\n */\n init(options: VeyaConfig): Promise<this> {\n if (this.initPromise) {\n if (this.initialized) this.log('warn', 'SDK already initialized');\n return this.initPromise;\n }\n this.initPromise = this.runInit(options).catch((error) => {\n if (!this.initialized) this.initPromise = null; // allow a corrected retry\n throw error;\n });\n return this.initPromise;\n }\n\n private async runInit(options: VeyaConfig): Promise<this> {\n if (!options.tenantSlug && !options.tenantId) {\n throw new Error('VeyaAnalytics: tenantSlug is required');\n }\n\n this.config = { ...DEFAULT_CONFIG, ...options };\n // Sync: tenantSlug takes precedence, fall back to tenantId\n if (!this.config.tenantSlug) {\n this.config.tenantSlug = this.config.tenantId;\n }\n\n // Initialize visitor and session\n await this.initVisitor();\n const isNewSession = await this.initSession();\n\n // Get device info (implemented by platform-specific class)\n this.deviceInfo = await this.getDeviceInfo();\n\n // Start flush timer\n this.startFlushTimer();\n\n // Mark initialized BEFORE the first track(): track() drops events until this is set, which\n // is why session_start was never sent before 4.0.1.\n this.initialized = true;\n\n // A session starts once. A resumed session (a full page load or app launch within the\n // session timeout) must not send session_start again.\n if (isNewSession) {\n this.trackSessionStart();\n }\n\n this.log('info', 'VeyaAnalytics initialized', {\n tenantSlug: this.config.tenantSlug,\n visitorId: this.visitorId,\n sessionId: this.sessionId,\n platform: this.config.platform,\n newSession: isNewSession\n });\n\n // Platform setup (listeners, auto-tracking, initial page view). A failure here must not\n // break the host app: the core is already usable, so log it and carry on.\n try {\n await this.onInitialized();\n } catch (error) {\n this.log('error', 'Platform setup failed', error);\n }\n\n return this;\n }\n\n /** Platform hook: runs exactly once per instance, after the core is initialized. */\n protected async onInitialized(): Promise<void> {}\n\n protected async initVisitor(): Promise<void> {\n if (!this.storage) {\n this.visitorId = generateUUID();\n return;\n }\n\n const stored = await this.storage.getItem('veya_visitor_id');\n if (stored) {\n this.visitorId = stored;\n } else {\n this.visitorId = generateUUID();\n await this.storage.setItem('veya_visitor_id', this.visitorId);\n }\n }\n\n /** Resolves true when a new session was started, false when a stored one was resumed. */\n protected async initSession(): Promise<boolean> {\n if (!this.storage) {\n this.sessionId = generateUUID();\n return true;\n }\n\n const stored = await this.storage.getItem('veya_session');\n const now = Date.now();\n\n if (stored) {\n try {\n const sessionData = JSON.parse(stored);\n if ((now - sessionData.lastActivity) < this.config.sessionTimeout) {\n this.sessionId = sessionData.sessionId;\n this.sessionData = { ...this.sessionData, ...sessionData.data };\n await this.saveSession();\n return false;\n }\n } catch (e) {}\n }\n\n // New session\n this.sessionId = generateUUID();\n await this.saveSession();\n return true;\n }\n\n protected async saveSession(): Promise<void> {\n if (!this.storage) return;\n\n await this.storage.setItem('veya_session', JSON.stringify({\n sessionId: this.sessionId,\n lastActivity: Date.now(),\n data: this.sessionData\n }));\n }\n\n // Override in platform-specific implementations\n protected async getDeviceInfo(): Promise<DeviceInfo> {\n return {\n device_type: 'unknown',\n platform: this.config.platform || 'unknown',\n os: 'unknown',\n screen_width: 0,\n screen_height: 0,\n language: 'en',\n timezone: 'UTC'\n };\n }\n\n // ============================================================================\n // CORE TRACKING\n // ============================================================================\n\n track(eventName: string, properties: Record<string, any> = {}): this {\n if (!this.initialized) {\n this.log('warn', 'SDK not initialized');\n return this;\n }\n\n const event = this.buildEvent(eventName, properties);\n this.queueEvent(event);\n this.log('debug', 'Event tracked', event);\n\n return this;\n }\n\n protected buildEvent(eventName: string, properties: Record<string, any>): Event {\n return {\n event_id: generateUUID(),\n event_name: eventName,\n event_category: properties.category || this.inferCategory(eventName),\n event_timestamp: getTimestamp(),\n \n // Identifiers\n tenant_id: this.config.tenantSlug || this.config.tenantId || '',\n tenant_slug: this.config.tenantSlug || this.config.tenantId || '',\n session_id: this.sessionId,\n visitor_id: this.visitorId,\n customer_id: this.customerId || undefined,\n store_id: this.config.storeId || properties.store_id,\n store_name: this.config.storeName || properties.store_name,\n\n // Context\n page_url: properties.page_url,\n page_title: properties.page_title,\n page_type: properties.page_type || this.currentPageType,\n screen_name: properties.screen_name || this.currentScreenName,\n referrer: properties.referrer,\n \n // Device info\n ...this.deviceInfo,\n \n // Session state\n is_logged_in: this.sessionData.is_logged_in,\n login_method: this.sessionData.login_method || undefined,\n \n // Funnel\n funnel_step: properties.funnel_step || this.currentFunnelStep?.name,\n funnel_step_number: properties.funnel_step_number || this.currentFunnelStep?.number,\n \n // Cart\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n \n // Experiments\n experiment_assignments: this.sessionData.experiment_assignments,\n \n // Custom properties\n properties: this.sanitizeProperties(properties)\n };\n }\n\n protected inferCategory(eventName: string): string {\n if (eventName.includes('cart')) return 'cart';\n if (eventName.includes('checkout') || eventName.includes('order')) return 'checkout';\n if (eventName.includes('product') || eventName.includes('menu')) return 'catalog';\n if (eventName.includes('login') || eventName.includes('auth')) return 'auth';\n if (eventName.includes('error')) return 'error';\n if (eventName.includes('screen') || eventName.includes('page') || eventName.includes('session')) return 'navigation';\n return 'engagement';\n }\n\n protected sanitizeProperties(properties: Record<string, any>): Record<string, any> {\n const sanitized = { ...properties };\n \n // Remove internal properties\n delete sanitized.category;\n delete sanitized.page_type;\n delete sanitized.store_id;\n delete sanitized.page_url;\n delete sanitized.page_title;\n delete sanitized.screen_name;\n delete sanitized.referrer;\n delete sanitized.funnel_step;\n delete sanitized.funnel_step_number;\n \n // Remove PII\n const piiFields = ['email', 'phone', 'password', 'ssn', 'credit_card', 'cvv'];\n piiFields.forEach(field => delete sanitized[field]);\n \n return sanitized;\n }\n\n // ============================================================================\n // SESSION TRACKING\n // ============================================================================\n\n protected trackSessionStart(): void {\n this.track('session_start', {\n platform: this.config.platform\n });\n }\n\n trackSessionEnd(): void {\n this.track('session_end', {});\n this.flush(true);\n }\n\n // ============================================================================\n // SCREEN / PAGE TRACKING\n // ============================================================================\n\n screenView(screenName: string, properties: Record<string, any> = {}): this {\n this.currentScreenName = screenName;\n this.currentPageType = this.inferPageType(screenName);\n this.updateFunnelStep(this.currentPageType);\n\n return this.track('screen_view', {\n screen_name: screenName,\n page_type: this.currentPageType,\n ...properties\n });\n }\n\n pageView(properties: Record<string, any> = {}): this {\n const pageType = properties.pageType || properties.page_type || 'unknown';\n this.currentPageType = pageType;\n this.updateFunnelStep(pageType);\n\n return this.track('page_view', {\n page_type: pageType,\n ...properties\n });\n }\n\n protected inferPageType(screenName: string): string {\n const name = screenName.toLowerCase();\n \n if (name.includes('menu') || name.includes('order') || name.includes('food')) return 'menu';\n if (name.includes('cart') || name.includes('basket') || name.includes('bag')) return 'cart';\n if (name.includes('checkout') || name.includes('payment')) return 'checkout';\n if (name.includes('confirm') || name.includes('success') || name.includes('thank')) return 'confirmation';\n if (name.includes('product') || name.includes('item') || name.includes('detail')) return 'product';\n if (name.includes('location') || name.includes('store')) return 'location';\n if (name.includes('account') || name.includes('profile') || name.includes('login')) return 'account';\n if (name.includes('reward') || name.includes('loyalty') || name.includes('point')) return 'rewards';\n if (name.includes('home') || name.includes('landing')) return 'home';\n \n return 'other';\n }\n\n protected updateFunnelStep(pageType: string): void {\n const funnelMap: Record<string, { name: string; number: number }> = {\n home: { name: 'landing', number: 1 },\n location: { name: 'location', number: 1 },\n menu: { name: 'menu', number: 2 },\n product: { name: 'menu', number: 2 },\n cart: { name: 'cart', number: 3 },\n checkout: { name: 'checkout', number: 4 },\n confirmation: { name: 'confirmation', number: 5 }\n };\n\n this.currentFunnelStep = funnelMap[pageType] || null;\n }\n\n // ============================================================================\n // PRODUCT TRACKING\n // ============================================================================\n\n productView(product: Product, properties: Record<string, any> = {}): this {\n return this.track('product_view', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n ...properties\n });\n }\n\n productClick(product: Product, properties: Record<string, any> = {}): this {\n return this.track('product_click', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n ...properties\n });\n }\n\n // ============================================================================\n // CART TRACKING\n // ============================================================================\n\n addToCart(product: Product, quantity: number = 1, properties: Record<string, any> = {}): this {\n this.cartState.itemCount += quantity;\n this.cartState.total += (product.price || 0) * quantity;\n this.cartState.items.push({ ...product, quantity });\n\n return this.track('add_to_cart', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n quantity,\n ...properties\n });\n }\n\n removeFromCart(product: Product, quantity: number = 1, properties: Record<string, any> = {}): this {\n this.cartState.itemCount = Math.max(0, this.cartState.itemCount - quantity);\n this.cartState.total = Math.max(0, this.cartState.total - (product.price || 0) * quantity);\n\n return this.track('remove_from_cart', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n quantity,\n ...properties\n });\n }\n\n updateCartQuantity(product: Product, oldQuantity: number, newQuantity: number): this {\n const diff = newQuantity - oldQuantity;\n this.cartState.itemCount += diff;\n this.cartState.total += (product.price || 0) * diff;\n\n return this.track('update_cart_quantity', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n old_quantity: oldQuantity,\n new_quantity: newQuantity\n });\n }\n\n setCart(cart: Partial<CartState>): this {\n this.cartState = {\n items: cart.items || [],\n itemCount: cart.itemCount || 0,\n total: cart.total || 0\n };\n return this;\n }\n\n viewCart(properties: Record<string, any> = {}): this {\n return this.track('cart_view', {\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n ...properties\n });\n }\n\n // ============================================================================\n // CHECKOUT TRACKING\n // ============================================================================\n\n checkoutStart(properties: Record<string, any> = {}): this {\n this.updateFunnelStep('checkout');\n return this.track('checkout_start', {\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n ...properties\n });\n }\n\n checkoutStep(step: string, properties: Record<string, any> = {}): this {\n return this.track('checkout_step', {\n checkout_step: step,\n ...properties\n });\n }\n\n /**\n * The shopper chose or entered a payment method. Sends add_payment_info with\n * { payment_method } at funnel step checkout_payment (4); the cart value and item count ride\n * on the event itself, as on every event (matching the v1 bundle's addPaymentInfo).\n */\n addPaymentInfo(paymentMethod: string, properties: Record<string, any> = {}): this {\n return this.track('add_payment_info', {\n payment_method: paymentMethod,\n funnel_step: 'checkout_payment',\n funnel_step_number: 4,\n ...properties\n });\n }\n\n checkoutComplete(order: Order, properties: Record<string, any> = {}): this {\n this.updateFunnelStep('confirmation');\n\n const event = this.track('checkout_complete', {\n order_id: order.id || order.order_id,\n olo_order_id: order.olo_order_id,\n order_total: order.total,\n subtotal: order.subtotal,\n tax: order.tax,\n tip: order.tip,\n item_count: order.itemCount || order.item_count,\n order_type: order.orderType || order.order_type,\n payment_method: order.paymentMethod || order.payment_method,\n ...properties\n });\n\n // Clear cart\n this.cartState = { items: [], itemCount: 0, total: 0 };\n\n return event;\n }\n\n // ============================================================================\n // AUTH TRACKING\n // ============================================================================\n\n loginAttempt(method: string, properties: Record<string, any> = {}): this {\n return this.track('login_attempt', {\n login_method: method,\n funnel_step: this.currentFunnelStep?.name,\n ...properties\n });\n }\n\n loginSuccess(method: string, customerId?: string, properties: Record<string, any> = {}): this {\n this.sessionData.is_logged_in = true;\n this.sessionData.login_method = method;\n this.sessionData.logged_in_at = getTimestamp();\n this.sessionData.login_funnel_step = this.currentFunnelStep?.name || null;\n \n if (customerId) {\n this.customerId = customerId;\n }\n\n this.saveSession();\n\n return this.track('login_success', {\n login_method: method,\n customer_id: customerId,\n funnel_step: this.currentFunnelStep?.name,\n ...properties\n });\n }\n\n loginFailure(method: string, error?: string, properties: Record<string, any> = {}): this {\n return this.track('login_failure', {\n login_method: method,\n error_message: error,\n ...properties\n });\n }\n\n logout(properties: Record<string, any> = {}): this {\n const previousCustomerId = this.customerId;\n \n this.sessionData.is_logged_in = false;\n this.customerId = null;\n this.saveSession();\n\n return this.track('logout', {\n previous_customer_id: previousCustomerId,\n ...properties\n });\n }\n\n identify(customerId: string, traits: Record<string, any> = {}): this {\n this.customerId = customerId;\n this.sessionData.is_logged_in = true;\n this.saveSession();\n\n return this.track('identify', {\n customer_id: customerId,\n traits: this.sanitizeProperties(traits)\n });\n }\n\n // ============================================================================\n // STORE SELECTION\n // ============================================================================\n\n storeSelect(store: { id?: string; store_id?: string; name?: string; store_name?: string }, properties: Record<string, any> = {}): this {\n const storeId = store.id || store.store_id;\n const storeName = store.name || store.store_name;\n if (storeId) {\n this.config.storeId = storeId;\n }\n if (storeName) {\n // Persist so every subsequent event carries the name (the warehouse\n // resolves location names via ANY_VALUE(store_name) per store_id).\n this.config.storeName = storeName;\n }\n\n return this.track('store_select', {\n store_id: storeId,\n store_name: storeName,\n ...properties\n });\n }\n\n setStore(storeId: string, storeName?: string): this {\n this.config.storeId = storeId;\n if (storeName) {\n this.config.storeName = storeName;\n }\n return this;\n }\n\n // ============================================================================\n // SEARCH\n // ============================================================================\n\n search(query: string, resultCount?: number, properties: Record<string, any> = {}): this {\n return this.track('search', {\n search_query: query,\n result_count: resultCount,\n ...properties\n });\n }\n\n // ============================================================================\n // LOYALTY / REWARDS\n // ============================================================================\n\n loyaltyLogin(customer: { id?: string; customer_id?: string; tier?: string; points?: number }, properties: Record<string, any> = {}): this {\n const customerId = customer.id || customer.customer_id;\n if (customerId) {\n this.customerId = customerId;\n }\n\n return this.track('loyalty_login', {\n customer_id: customerId,\n loyalty_tier: customer.tier,\n points_balance: customer.points,\n ...properties\n });\n }\n\n rewardView(reward: { id: string; name: string; value?: number; points_required?: number }, properties: Record<string, any> = {}): this {\n return this.track('reward_view', {\n reward_id: reward.id,\n reward_name: reward.name,\n reward_value: reward.value,\n points_required: reward.points_required,\n ...properties\n });\n }\n\n rewardApply(reward: { id: string; name: string; value?: number; points_used?: number }, properties: Record<string, any> = {}): this {\n return this.track('reward_apply', {\n reward_id: reward.id,\n reward_name: reward.name,\n reward_value: reward.value,\n points_used: reward.points_used,\n ...properties\n });\n }\n\n rewardRemove(reward: { id: string; name: string }, properties: Record<string, any> = {}): this {\n return this.track('reward_remove', {\n reward_id: reward.id,\n reward_name: reward.name,\n ...properties\n });\n }\n\n // ============================================================================\n // PROMO CODES\n // ============================================================================\n\n promoApply(promo: { code: string; discount?: number; success: boolean; error?: string }, properties: Record<string, any> = {}): this {\n return this.track('promo_apply', {\n promo_code: promo.code,\n discount_amount: promo.discount,\n success: promo.success,\n error_message: promo.error,\n ...properties\n });\n }\n\n promoRemove(promoCode: string, properties: Record<string, any> = {}): this {\n return this.track('promo_remove', {\n promo_code: promoCode,\n ...properties\n });\n }\n\n // ============================================================================\n // EXPERIMENTS\n // ============================================================================\n\n setExperiment(experimentKey: string, variantKey: string): this {\n this.sessionData.experiment_assignments[experimentKey] = variantKey;\n this.saveSession();\n\n return this.track('experiment_assigned', {\n experiment_key: experimentKey,\n variant_key: variantKey\n });\n }\n\n // ============================================================================\n // ERRORS\n // ============================================================================\n\n error(errorType: string, errorMessage: string, context: Record<string, any> = {}): this {\n return this.track('error', {\n error_type: errorType,\n error_message: errorMessage,\n ...context\n });\n }\n\n // ============================================================================\n // QUEUE & FLUSH\n // ============================================================================\n\n protected queueEvent(event: Event): void {\n this.eventQueue.push(event);\n\n if (this.eventQueue.length >= this.config.batchSize) {\n this.flush();\n }\n }\n\n protected startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n if (this.eventQueue.length > 0) {\n this.flush();\n }\n }, this.config.flushInterval);\n }\n\n async flush(sync: boolean = false): Promise<void> {\n if (this.eventQueue.length === 0) return;\n\n const events = [...this.eventQueue];\n this.eventQueue = [];\n\n const payload = {\n batch_id: generateUUID(),\n tenant_slug: this.config.tenantSlug || this.config.tenantId,\n events,\n sent_at: getTimestamp()\n };\n\n try {\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload)\n });\n this.log('debug', 'Flushed events', { count: events.length });\n } catch (error) {\n this.log('error', 'Failed to send events', error);\n // Re-queue events\n this.eventQueue = [...events, ...this.eventQueue];\n }\n }\n\n // ============================================================================\n // UTILITIES\n // ============================================================================\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n getVisitorId(): string {\n return this.visitorId;\n }\n\n getCustomerId(): string | null {\n return this.customerId;\n }\n\n isLoggedIn(): boolean {\n return this.sessionData.is_logged_in;\n }\n\n protected log(level: string, message: string, data?: any): void {\n if (!this.config.debug && level === 'debug') return;\n \n const prefix = '[VeyaAnalytics]';\n if (level === 'error') {\n console.error(prefix, message, data || '');\n } else if (level === 'warn') {\n console.warn(prefix, message, data || '');\n } else {\n console.log(prefix, message, data || '');\n }\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n }\n this.flush(true);\n }\n}\n\nexport default VeyaAnalyticsCore;\n", "/**\n * Veya Analytics SDK - Web\n * \n * Smart analytics for web browsers with auto-detection\n * \n * @version 4.0.1\n */\n\nimport { \n VeyaAnalyticsCore, \n VeyaConfig, \n DeviceInfo,\n StorageAdapter,\n generateUUID,\n getTimestamp\n} from '../core/VeyaAnalyticsCore.js';\n\n// ============================================================================\n// LOCAL STORAGE ADAPTER\n// ============================================================================\n\nclass LocalStorageAdapter implements StorageAdapter {\n async getItem(key: string): Promise<string | null> {\n try {\n return localStorage.getItem(key);\n } catch (e) {\n return null;\n }\n }\n\n async setItem(key: string, value: string): Promise<void> {\n try {\n localStorage.setItem(key, value);\n } catch (e) {}\n }\n\n async removeItem(key: string): Promise<void> {\n try {\n localStorage.removeItem(key);\n } catch (e) {}\n }\n}\n\n// ============================================================================\n// PAGE DETECTOR\n// ============================================================================\n\nconst PAGE_PATTERNS: Record<string, { urlPatterns: RegExp[]; domSignals: string[]; titlePatterns: RegExp[] }> = {\n menu: {\n urlPatterns: [/\\/menu/i, /\\/order/i, /\\/food/i, /\\/products/i],\n domSignals: ['[data-product]', '.menu-item', '.product-card', '.food-item'],\n titlePatterns: [/menu/i, /order/i, /food/i]\n },\n cart: {\n urlPatterns: [/\\/cart/i, /\\/basket/i, /\\/bag/i],\n domSignals: ['.cart-item', '.basket-item', '[data-cart]', '.cart-summary'],\n titlePatterns: [/cart/i, /basket/i, /your order/i]\n },\n checkout: {\n urlPatterns: [/\\/checkout/i, /\\/payment/i, /\\/pay\\b/i],\n domSignals: ['[data-checkout]', '.checkout-form', '.payment-form'],\n titlePatterns: [/checkout/i, /payment/i]\n },\n confirmation: {\n urlPatterns: [/\\/confirm/i, /\\/thank/i, /\\/success/i],\n domSignals: ['.confirmation', '.order-confirmed', '.thank-you'],\n titlePatterns: [/thank/i, /confirm/i, /success/i]\n },\n product: {\n urlPatterns: [/\\/product\\//i, /\\/item\\//i],\n domSignals: ['.product-detail', '.item-detail'],\n titlePatterns: []\n },\n location: {\n urlPatterns: [/\\/location/i, /\\/store/i, /\\/find/i],\n domSignals: ['.store-locator', '.location-picker'],\n titlePatterns: [/location/i, /find.*store/i]\n },\n account: {\n urlPatterns: [/\\/account/i, /\\/profile/i, /\\/login/i, /\\/signin/i],\n domSignals: ['.login-form', '.account-page'],\n titlePatterns: [/account/i, /sign in/i, /log in/i]\n },\n rewards: {\n urlPatterns: [/\\/reward/i, /\\/loyalty/i, /\\/points/i],\n domSignals: ['.rewards', '.loyalty', '.points-balance'],\n titlePatterns: [/reward/i, /loyalty/i]\n },\n home: {\n urlPatterns: [/^\\/$/, /\\/home/i],\n domSignals: ['.hero', '.home-banner'],\n titlePatterns: []\n }\n};\n\n// ============================================================================\n// WEB ANALYTICS CLASS\n// ============================================================================\n\n// Scroll-depth thresholds (percent of the scrollable distance); each fires once per page view\nconst SCROLL_DEPTHS = [25, 50, 75, 100];\n\nexport class VeyaAnalyticsWeb extends VeyaAnalyticsCore {\n private pageDetectionCache: Map<string, { type: string; confidence: number }> = new Map();\n private productTracker: ProductTracker | null = null;\n private cartTracker: CartTracker | null = null;\n private networkInterceptor: NetworkInterceptor | null = null;\n\n // Page-level state for time_on_page and scroll depth; both reset on every page view\n private pageStartedAt: number = Date.now();\n private scrollDepthsFired: Set<number> = new Set();\n private scrollCheckPending: boolean = false;\n\n constructor() {\n super();\n this.storage = new LocalStorageAdapter();\n }\n\n init(options: VeyaConfig): Promise<this> {\n return super.init({ ...options, platform: 'web' });\n }\n\n // Runs exactly once, after the core is initialized (see VeyaAnalyticsCore.init)\n protected async onInitialized(): Promise<void> {\n this.pageStartedAt = Date.now();\n\n // Setup auto-detection if enabled\n if (this.config.autoDetect) {\n this.setupPageChangeDetection();\n }\n\n if (this.config.autoTrackProducts) {\n this.productTracker = new ProductTracker(this);\n this.productTracker.init();\n }\n\n if (this.config.autoTrackCart) {\n this.cartTracker = new CartTracker(this);\n this.cartTracker.init();\n }\n\n if (this.config.interceptOloApi) {\n this.networkInterceptor = new NetworkInterceptor(this, this.config);\n this.networkInterceptor.init();\n }\n\n // Setup browser event listeners\n this.setupBrowserListeners();\n\n // Track the initial page only when the SDK owns page views. With autoDetect off the app\n // sends its own page_view, and tracking one here as well doubled every full page load.\n if (this.config.autoDetect) {\n this.trackCurrentPage();\n }\n }\n\n protected async getDeviceInfo(): Promise<DeviceInfo> {\n const ua = navigator.userAgent;\n \n return {\n device_type: this.getDeviceType(),\n platform: 'web',\n os: this.getOS(),\n os_version: this.getOSVersion(),\n screen_width: window.screen.width,\n screen_height: window.screen.height,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n };\n }\n\n private getDeviceType(): string {\n const ua = navigator.userAgent.toLowerCase();\n const width = window.innerWidth;\n \n if (/ipad|tablet|playbook|silk/i.test(ua) || (width >= 768 && width < 1024)) {\n return 'tablet';\n }\n if (/mobile|iphone|ipod|android|blackberry/i.test(ua) || width < 768) {\n return 'mobile';\n }\n return 'desktop';\n }\n\n private getOS(): string {\n const ua = navigator.userAgent;\n if (/Windows/.test(ua)) return 'Windows';\n if (/Mac OS X/.test(ua)) return 'macOS';\n if (/Android/.test(ua)) return 'Android';\n if (/iOS|iPhone|iPad/.test(ua)) return 'iOS';\n if (/Linux/.test(ua)) return 'Linux';\n return 'unknown';\n }\n\n private getOSVersion(): string {\n const ua = navigator.userAgent;\n const match = ua.match(/(?:Windows NT|Mac OS X|Android|iOS)\\s*([\\d._]+)/i);\n return match ? match[1].replace(/_/g, '.') : 'unknown';\n }\n\n // ============================================================================\n // PAGE DETECTION\n // ============================================================================\n\n private setupPageChangeDetection(): void {\n let lastUrl = window.location.href;\n\n const handleUrlChange = () => {\n if (window.location.href !== lastUrl) {\n lastUrl = window.location.href;\n this.pageDetectionCache.clear();\n this.trackCurrentPage();\n \n if (this.productTracker) {\n this.productTracker.reset();\n }\n }\n };\n\n window.addEventListener('popstate', handleUrlChange);\n \n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n history.pushState = function() {\n originalPushState.apply(this, arguments as any);\n handleUrlChange();\n };\n\n history.replaceState = function() {\n originalReplaceState.apply(this, arguments as any);\n handleUrlChange();\n };\n\n window.addEventListener('hashchange', handleUrlChange);\n }\n\n private detectPageType(): { type: string; confidence: number } {\n const cacheKey = window.location.pathname + document.title;\n \n if (this.pageDetectionCache.has(cacheKey)) {\n return this.pageDetectionCache.get(cacheKey)!;\n }\n\n const url = window.location.href.toLowerCase();\n const path = window.location.pathname.toLowerCase();\n const title = document.title.toLowerCase();\n\n const scores: Record<string, number> = {};\n\n for (const [pageType, patterns] of Object.entries(PAGE_PATTERNS)) {\n let score = 0;\n\n // URL matching (40%)\n for (const pattern of patterns.urlPatterns) {\n if (pattern.test(path)) {\n score += 40;\n break;\n }\n }\n\n // DOM signals (40%)\n let domMatches = 0;\n for (const selector of patterns.domSignals) {\n try {\n if (document.querySelector(selector)) domMatches++;\n } catch (e) {}\n }\n if (patterns.domSignals.length > 0) {\n score += (domMatches / patterns.domSignals.length) * 40;\n }\n\n // Title matching (20%)\n for (const pattern of patterns.titlePatterns) {\n if (pattern.test(title)) {\n score += 20;\n break;\n }\n }\n\n scores[pageType] = score / 100;\n }\n\n let bestType = 'unknown';\n let bestScore = 0;\n\n for (const [type, score] of Object.entries(scores)) {\n if (score > bestScore) {\n bestScore = score;\n bestType = type;\n }\n }\n\n const result = {\n type: bestScore >= (this.config.confidenceThreshold || 0.7) ? bestType : 'unknown',\n confidence: bestScore\n };\n\n this.pageDetectionCache.set(cacheKey, result);\n this.currentPageType = result.type;\n\n return result;\n }\n\n private trackCurrentPage(): void {\n const detection = this.detectPageType();\n \n this.pageView({\n page_url: window.location.href,\n page_title: document.title,\n page_type: detection.type,\n page_type_confidence: detection.confidence,\n referrer: document.referrer,\n ...this.getUTMParams()\n });\n }\n\n // Every page view (SDK-detected or sent by the app) starts a new page: time_on_page restarts and\n // the scroll-depth thresholds can fire again.\n pageView(properties: Record<string, any> = {}): this {\n this.pageStartedAt = Date.now();\n this.scrollDepthsFired.clear();\n return super.pageView(properties);\n }\n\n private getUTMParams(): Record<string, string | null> {\n const params = new URLSearchParams(window.location.search);\n return {\n utm_source: params.get('utm_source'),\n utm_medium: params.get('utm_medium'),\n utm_campaign: params.get('utm_campaign'),\n utm_term: params.get('utm_term'),\n utm_content: params.get('utm_content')\n };\n }\n\n // ============================================================================\n // BROWSER LISTENERS\n // ============================================================================\n\n private setupBrowserListeners(): void {\n // Tab hidden / shown. page_hidden carries how long the current page has been open (ms since\n // the last page view); page_visible carries nothing extra.\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n this.track('page_hidden', { time_on_page: this.timeOnPage() });\n this.flush(true);\n } else if (document.visibilityState === 'visible') {\n this.track('page_visible');\n }\n });\n\n // Leaving the page. This is not session_end: every full navigation unloads the page while\n // the session carries on (4.0.0 sent session_end here).\n window.addEventListener('beforeunload', () => {\n this.track('page_unload', { time_on_page: this.timeOnPage() });\n this.flush(true);\n });\n\n // Scroll depth. Checked at most every 100ms, and always after the last scroll event of a\n // burst, so the final position is measured even when scrolling fast.\n window.addEventListener('scroll', () => {\n if (this.scrollCheckPending) return;\n this.scrollCheckPending = true;\n setTimeout(() => {\n this.scrollCheckPending = false;\n this.checkScrollDepth();\n }, 100);\n }, { passive: true });\n\n // Errors\n window.addEventListener('error', (e) => {\n this.error('javascript', e.message, {\n filename: e.filename,\n lineno: e.lineno,\n colno: e.colno\n });\n });\n\n window.addEventListener('unhandledrejection', (e) => {\n this.error('promise_rejection', e.reason?.message || String(e.reason));\n });\n }\n\n private timeOnPage(): number {\n return Math.max(0, Date.now() - this.pageStartedAt);\n }\n\n // Fires every threshold at or below the current depth that hasn't fired yet on this page, so a\n // fast scroll that jumps past several thresholds still reports each of them once.\n private checkScrollDepth(): void {\n const scrollable = document.documentElement.scrollHeight - window.innerHeight;\n if (scrollable <= 0) return; // the page doesn't scroll: nothing to measure (and no divide by zero)\n\n const percent = Math.min(100, Math.round((window.scrollY / scrollable) * 100));\n for (const depth of SCROLL_DEPTHS) {\n if (percent >= depth && !this.scrollDepthsFired.has(depth)) {\n this.scrollDepthsFired.add(depth);\n this.track('scroll_depth', { depth });\n }\n }\n }\n\n // ============================================================================\n // FLUSH OVERRIDE FOR WEB\n // ============================================================================\n\n async flush(sync: boolean = false): Promise<void> {\n if (this.eventQueue.length === 0) return;\n\n const events = [...this.eventQueue];\n this.eventQueue = [];\n\n const payload = {\n batch_id: generateUUID(),\n tenant_slug: this.config.tenantSlug || this.config.tenantId,\n events,\n sent_at: getTimestamp()\n };\n\n if (sync && navigator.sendBeacon) {\n navigator.sendBeacon(this.config.endpoint, JSON.stringify(payload));\n } else {\n try {\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n keepalive: true\n });\n } catch (error) {\n this.eventQueue = [...events, ...this.eventQueue];\n }\n }\n }\n\n destroy(): void {\n if (this.productTracker) this.productTracker.destroy();\n if (this.cartTracker) this.cartTracker.destroy();\n if (this.networkInterceptor) this.networkInterceptor.destroy();\n super.destroy();\n }\n}\n\n// ============================================================================\n// PRODUCT TRACKER\n// ============================================================================\n\nclass ProductTracker {\n private sdk: VeyaAnalyticsWeb;\n private viewedProducts: Set<string> = new Set();\n private observer: MutationObserver | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb) {\n this.sdk = sdk;\n }\n\n init(): void {\n this.intersectionObserver = new IntersectionObserver(\n this.handleIntersection.bind(this),\n { threshold: 0.5 }\n );\n\n this.scanForProducts();\n\n this.observer = new MutationObserver(() => {\n setTimeout(() => this.scanForProducts(), 500);\n });\n\n this.observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n private scanForProducts(): void {\n const selectors = [\n '[data-product-id]',\n '[data-product]',\n '.product-card',\n '.menu-item',\n '.food-item'\n ];\n\n for (const selector of selectors) {\n try {\n document.querySelectorAll(selector).forEach(el => {\n if (!(el as HTMLElement).dataset.veyaTracked) {\n (el as HTMLElement).dataset.veyaTracked = 'true';\n this.intersectionObserver?.observe(el);\n }\n });\n } catch (e) {}\n }\n }\n\n private handleIntersection(entries: IntersectionObserverEntry[]): void {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n const product = this.extractProductData(entry.target as HTMLElement);\n if (product.name && !this.viewedProducts.has(product.id || product.name)) {\n this.viewedProducts.add(product.id || product.name);\n this.sdk.productView(product, { auto: true });\n }\n }\n });\n }\n\n private extractProductData(element: HTMLElement): any {\n return {\n id: element.dataset.productId || element.dataset.id || element.id,\n name: element.dataset.productName || element.dataset.name || \n element.querySelector('.product-name, .item-name, h2, h3')?.textContent?.trim(),\n category: element.dataset.category,\n price: parseFloat(element.dataset.price || '0') || null\n };\n }\n\n reset(): void {\n this.viewedProducts.clear();\n this.scanForProducts();\n }\n\n destroy(): void {\n this.observer?.disconnect();\n this.intersectionObserver?.disconnect();\n }\n}\n\n// ============================================================================\n// CART TRACKER\n// ============================================================================\n\nclass CartTracker {\n private sdk: VeyaAnalyticsWeb;\n private observer: MutationObserver | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb) {\n this.sdk = sdk;\n }\n\n init(): void {\n const cartSelectors = ['.cart', '.basket', '#cart', '[data-cart]'];\n\n this.observer = new MutationObserver(() => {\n // Cart changed - could extract and compare state\n });\n\n for (const selector of cartSelectors) {\n const cartEl = document.querySelector(selector);\n if (cartEl) {\n this.observer.observe(cartEl, {\n childList: true,\n subtree: true\n });\n break;\n }\n }\n }\n\n destroy(): void {\n this.observer?.disconnect();\n }\n}\n\n// ============================================================================\n// NETWORK INTERCEPTOR\n// ============================================================================\n\nclass NetworkInterceptor {\n private sdk: VeyaAnalyticsWeb;\n private config: any;\n private originalFetch: typeof fetch | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb, config: any) {\n this.sdk = sdk;\n this.config = config;\n }\n\n init(): void {\n this.originalFetch = window.fetch;\n const self = this;\n\n window.fetch = function(input: RequestInfo | URL, init?: RequestInit) {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n \n return self.originalFetch!.apply(window, [input, init])\n .then(response => {\n self.handleResponse(url, response.clone());\n return response;\n });\n };\n }\n\n private async handleResponse(url: string, response: Response): Promise<void> {\n if (!this.isOloApi(url)) return;\n\n try {\n const data = await response.json();\n \n // Detect order completion\n if (url.includes('order') && data.id) {\n this.sdk.checkoutComplete({\n id: data.id,\n olo_order_id: data.id,\n total: data.total,\n orderType: data.deliveryMode || data.type\n }, { auto: true });\n }\n\n // Detect basket updates\n if (url.includes('basket') && data.products) {\n this.sdk.setCart({\n items: data.products,\n total: data.total || data.subtotal,\n itemCount: data.products.reduce((sum: number, p: any) => sum + (p.quantity || 1), 0)\n });\n }\n } catch (e) {}\n }\n\n private isOloApi(url: string): boolean {\n const patterns = [/\\/basket/i, /\\/order/i, /olo\\.com/i];\n return patterns.some(p => p.test(url));\n }\n\n destroy(): void {\n if (this.originalFetch) {\n window.fetch = this.originalFetch;\n }\n }\n}\n\n// ============================================================================\n// SINGLETON & EXPORT\n// ============================================================================\n\nconst veya = new VeyaAnalyticsWeb();\n\n// Expose to window for script tag usage\nif (typeof window !== 'undefined') {\n (window as any).VeyaAnalytics = veya;\n (window as any).veya = veya;\n}\n\nexport default veya;\nexport type { VeyaConfig };\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["index_exports", "__export", "VeyaAnalyticsCore", "VeyaAnalyticsWeb", "VeyaAnalyticsWeb_default", "generateUUID", "getTimestamp", "DEFAULT_CONFIG", "generateUUID", "c", "r", "getTimestamp", "VeyaAnalyticsCore", "__publicField", "options", "error", "isNewSession", "stored", "now", "sessionData", "eventName", "properties", "event", "_a", "_b", "sanitized", "field", "screenName", "pageType", "name", "funnelMap", "product", "quantity", "oldQuantity", "newQuantity", "diff", "cart", "step", "paymentMethod", "order", "method", "customerId", "previousCustomerId", "traits", "store", "storeId", "storeName", "query", "resultCount", "customer", "reward", "promo", "promoCode", "experimentKey", "variantKey", "errorType", "errorMessage", "context", "sync", "events", "payload", "level", "message", "data", "prefix", "LocalStorageAdapter", "key", "value", "PAGE_PATTERNS", "SCROLL_DEPTHS", "VeyaAnalyticsWeb", "VeyaAnalyticsCore", "options", "ProductTracker", "CartTracker", "NetworkInterceptor", "ua", "width", "match", "lastUrl", "handleUrlChange", "originalPushState", "originalReplaceState", "cacheKey", "url", "path", "title", "scores", "pageType", "patterns", "score", "pattern", "domMatches", "selector", "bestType", "bestScore", "type", "result", "detection", "properties", "params", "_a", "scrollable", "percent", "depth", "sync", "events", "payload", "generateUUID", "getTimestamp", "sdk", "selectors", "el", "entries", "entry", "product", "element", "_b", "cartSelectors", "cartEl", "config", "self", "input", "init", "response", "data", "sum", "p", "veya", "VeyaAnalyticsWeb_default"]
|
|
4
|
+
"sourcesContent": ["/**\n * Veya Analytics SDK for the web (browsers)\n *\n * @example\n * ```ts\n * import veya from '@builtonveya/analytics-web';\n *\n * await veya.init({ tenantSlug: 'your-tenant-slug' });\n * veya.addToCart({ id: 'sku-1', name: 'Workout Smoothie', price: 12.95 }, 1);\n * ```\n *\n * The default export is a ready-made singleton; `VeyaAnalyticsWeb` is exported for\n * consumers that want their own instance. Importing this module is safe in server-side\n * rendering: it only touches `window` when one exists (to expose `window.veya` for\n * script-tag users), and nothing runs against the DOM until `init()` is called.\n */\nexport { default, VeyaAnalyticsWeb } from './VeyaAnalyticsWeb.js';\nexport { VeyaAnalyticsCore, generateUUID, getTimestamp } from '../core/VeyaAnalyticsCore.js';\nexport type {\n VeyaConfig,\n Product,\n CartState,\n Order,\n SessionData,\n DeviceInfo,\n Event,\n StorageAdapter,\n} from '../core/VeyaAnalyticsCore.js';\n", "/**\n * Veya Analytics SDK - Core\n * Platform-agnostic core that works on Web and React Native\n * \n * @version 4.0.2\n */\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface VeyaConfig {\n tenantSlug?: string;\n tenantId?: string;\n storeId?: string;\n storeName?: string;\n endpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n sessionTimeout?: number;\n debug?: boolean;\n autoDetect?: boolean;\n autoTrackProducts?: boolean;\n autoTrackCart?: boolean;\n interceptOloApi?: boolean;\n confidenceThreshold?: number;\n platform?: 'web' | 'ios' | 'android';\n}\n\nexport interface Product {\n id?: string;\n product_id?: string;\n name?: string;\n product_name?: string;\n category?: string;\n price?: number;\n quantity?: number;\n [key: string]: any;\n}\n\nexport interface CartState {\n items: Product[];\n itemCount: number;\n total: number;\n}\n\nexport interface Order {\n id?: string;\n order_id?: string;\n olo_order_id?: string;\n total?: number;\n subtotal?: number;\n tax?: number;\n tip?: number;\n itemCount?: number;\n item_count?: number;\n orderType?: string;\n order_type?: string;\n paymentMethod?: string;\n payment_method?: string;\n [key: string]: any;\n}\n\nexport interface SessionData {\n is_logged_in: boolean;\n login_method: string | null;\n logged_in_at: string | null;\n login_funnel_step: string | null;\n experiment_assignments: Record<string, string>;\n}\n\nexport interface DeviceInfo {\n device_type: string;\n platform: string;\n os: string;\n os_version?: string;\n app_version?: string;\n screen_width: number;\n screen_height: number;\n language: string;\n timezone: string;\n}\n\nexport interface Event {\n event_id: string;\n event_name: string;\n event_category?: string;\n event_timestamp: string;\n tenant_id: string;\n tenant_slug: string;\n session_id: string;\n visitor_id: string;\n customer_id?: string;\n store_id?: string;\n store_name?: string;\n page_url?: string;\n page_title?: string;\n page_type?: string;\n screen_name?: string;\n referrer?: string;\n device_type?: string;\n platform?: string;\n os?: string;\n os_version?: string;\n app_version?: string;\n screen_width?: number;\n screen_height?: number;\n language?: string;\n timezone?: string;\n utm_source?: string;\n utm_medium?: string;\n utm_campaign?: string;\n utm_term?: string;\n utm_content?: string;\n is_logged_in?: boolean;\n login_method?: string;\n funnel_step?: string;\n funnel_step_number?: number;\n cart_value?: number;\n cart_item_count?: number;\n experiment_assignments?: Record<string, string>;\n properties?: Record<string, any>;\n}\n\n// Storage interface - implemented differently for web vs React Native\nexport interface StorageAdapter {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n// ============================================================================\n// DEFAULT CONFIG\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<VeyaConfig> = {\n tenantSlug: '',\n tenantId: '',\n storeId: '',\n storeName: '',\n endpoint: 'https://analytics.builtonveya.com/v1/events',\n batchSize: 10,\n flushInterval: 5000,\n sessionTimeout: 30 * 60 * 1000,\n debug: false,\n autoDetect: true,\n autoTrackProducts: true,\n autoTrackCart: true,\n // Opt-in: patches window.fetch and reads order/basket responses as placed orders\n interceptOloApi: false,\n confidenceThreshold: 0.7,\n platform: 'web'\n};\n\n// ============================================================================\n// UTILITIES\n// ============================================================================\n\nexport function generateUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\nexport function getTimestamp(): string {\n return new Date().toISOString();\n}\n\n// ============================================================================\n// CORE ANALYTICS CLASS\n// ============================================================================\n\nexport class VeyaAnalyticsCore {\n protected config: Required<VeyaConfig>;\n protected initialized: boolean = false;\n // The in-flight (or completed) init run, shared by every init() call \u2014 see init()\n private initPromise: Promise<this> | null = null;\n protected eventQueue: Event[] = [];\n protected flushTimer: any = null;\n \n // Identifiers\n protected sessionId: string = '';\n protected visitorId: string = '';\n protected customerId: string | null = null;\n \n // State\n protected sessionData: SessionData = {\n is_logged_in: false,\n login_method: null,\n logged_in_at: null,\n login_funnel_step: null,\n experiment_assignments: {}\n };\n \n protected cartState: CartState = {\n items: [],\n itemCount: 0,\n total: 0\n };\n \n protected deviceInfo: DeviceInfo | null = null;\n protected currentScreenName: string = '';\n protected currentPageType: string = '';\n protected currentFunnelStep: { name: string; number: number } | null = null;\n \n // Storage adapter - must be set by platform-specific implementation\n protected storage: StorageAdapter | null = null;\n\n constructor() {\n this.config = { ...DEFAULT_CONFIG };\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n /**\n * Initialize the SDK. Safe to call more than once: a call made while another is still in\n * flight shares that run (React StrictMode's double effects, or two call sites, can't set up\n * listeners or send session_start twice), and a call after a successful init resolves at once.\n * A failed init (e.g. a missing tenantSlug) can be retried with corrected options.\n *\n * Platform SDKs set their platform by overriding init() and passing it through, and do their\n * own setup in onInitialized(), which runs exactly once.\n */\n init(options: VeyaConfig): Promise<this> {\n if (this.initPromise) {\n if (this.initialized) this.log('warn', 'SDK already initialized');\n return this.initPromise;\n }\n this.initPromise = this.runInit(options).catch((error) => {\n if (!this.initialized) this.initPromise = null; // allow a corrected retry\n throw error;\n });\n return this.initPromise;\n }\n\n private async runInit(options: VeyaConfig): Promise<this> {\n if (!options.tenantSlug && !options.tenantId) {\n throw new Error('VeyaAnalytics: tenantSlug is required');\n }\n\n this.config = { ...DEFAULT_CONFIG, ...options };\n // Sync: tenantSlug takes precedence, fall back to tenantId\n if (!this.config.tenantSlug) {\n this.config.tenantSlug = this.config.tenantId;\n }\n\n // Initialize visitor and session\n await this.initVisitor();\n const isNewSession = await this.initSession();\n\n // Get device info (implemented by platform-specific class)\n this.deviceInfo = await this.getDeviceInfo();\n\n // Start flush timer\n this.startFlushTimer();\n\n // Mark initialized BEFORE the first track(): track() drops events until this is set, which\n // is why session_start was never sent before 4.0.1.\n this.initialized = true;\n\n // A session starts once. A resumed session (a full page load or app launch within the\n // session timeout) must not send session_start again.\n if (isNewSession) {\n this.trackSessionStart();\n }\n\n this.log('info', 'VeyaAnalytics initialized', {\n tenantSlug: this.config.tenantSlug,\n visitorId: this.visitorId,\n sessionId: this.sessionId,\n platform: this.config.platform,\n newSession: isNewSession\n });\n\n // Platform setup (listeners, auto-tracking, initial page view). A failure here must not\n // break the host app: the core is already usable, so log it and carry on.\n try {\n await this.onInitialized();\n } catch (error) {\n this.log('error', 'Platform setup failed', error);\n }\n\n return this;\n }\n\n /** Platform hook: runs exactly once per instance, after the core is initialized. */\n protected async onInitialized(): Promise<void> {}\n\n protected async initVisitor(): Promise<void> {\n if (!this.storage) {\n this.visitorId = generateUUID();\n return;\n }\n\n const stored = await this.storage.getItem('veya_visitor_id');\n if (stored) {\n this.visitorId = stored;\n } else {\n this.visitorId = generateUUID();\n await this.storage.setItem('veya_visitor_id', this.visitorId);\n }\n }\n\n /** Resolves true when a new session was started, false when a stored one was resumed. */\n protected async initSession(): Promise<boolean> {\n if (!this.storage) {\n this.sessionId = generateUUID();\n return true;\n }\n\n const stored = await this.storage.getItem('veya_session');\n const now = Date.now();\n\n if (stored) {\n try {\n const sessionData = JSON.parse(stored);\n if ((now - sessionData.lastActivity) < this.config.sessionTimeout) {\n this.sessionId = sessionData.sessionId;\n this.sessionData = { ...this.sessionData, ...sessionData.data };\n await this.saveSession();\n return false;\n }\n } catch (e) {}\n }\n\n // New session\n this.sessionId = generateUUID();\n await this.saveSession();\n return true;\n }\n\n protected async saveSession(): Promise<void> {\n if (!this.storage) return;\n\n await this.storage.setItem('veya_session', JSON.stringify({\n sessionId: this.sessionId,\n lastActivity: Date.now(),\n data: this.sessionData\n }));\n }\n\n // Override in platform-specific implementations\n protected async getDeviceInfo(): Promise<DeviceInfo> {\n return {\n device_type: 'unknown',\n platform: this.config.platform || 'unknown',\n os: 'unknown',\n screen_width: 0,\n screen_height: 0,\n language: 'en',\n timezone: 'UTC'\n };\n }\n\n // ============================================================================\n // CORE TRACKING\n // ============================================================================\n\n track(eventName: string, properties: Record<string, any> = {}): this {\n if (!this.initialized) {\n this.log('warn', 'SDK not initialized');\n return this;\n }\n\n const event = this.buildEvent(eventName, properties);\n this.queueEvent(event);\n this.log('debug', 'Event tracked', event);\n\n return this;\n }\n\n protected buildEvent(eventName: string, properties: Record<string, any>): Event {\n return {\n event_id: generateUUID(),\n event_name: eventName,\n event_category: properties.category || this.inferCategory(eventName),\n event_timestamp: getTimestamp(),\n \n // Identifiers\n tenant_id: this.config.tenantSlug || this.config.tenantId || '',\n tenant_slug: this.config.tenantSlug || this.config.tenantId || '',\n session_id: this.sessionId,\n visitor_id: this.visitorId,\n customer_id: this.customerId || undefined,\n store_id: this.config.storeId || properties.store_id,\n store_name: this.config.storeName || properties.store_name,\n\n // Context\n page_url: properties.page_url,\n page_title: properties.page_title,\n page_type: properties.page_type || this.currentPageType,\n screen_name: properties.screen_name || this.currentScreenName,\n referrer: properties.referrer,\n \n // Device info\n ...this.deviceInfo,\n \n // Session state\n is_logged_in: this.sessionData.is_logged_in,\n login_method: this.sessionData.login_method || undefined,\n \n // Funnel\n funnel_step: properties.funnel_step || this.currentFunnelStep?.name,\n funnel_step_number: properties.funnel_step_number || this.currentFunnelStep?.number,\n \n // Cart\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n \n // Experiments\n experiment_assignments: this.sessionData.experiment_assignments,\n \n // Custom properties\n properties: this.sanitizeProperties(properties)\n };\n }\n\n protected inferCategory(eventName: string): string {\n if (eventName.includes('cart')) return 'cart';\n if (eventName.includes('checkout') || eventName.includes('order')) return 'checkout';\n if (eventName.includes('product') || eventName.includes('menu')) return 'catalog';\n if (eventName.includes('login') || eventName.includes('auth')) return 'auth';\n if (eventName.includes('error')) return 'error';\n if (eventName.includes('screen') || eventName.includes('page') || eventName.includes('session')) return 'navigation';\n return 'engagement';\n }\n\n protected sanitizeProperties(properties: Record<string, any>): Record<string, any> {\n const sanitized = { ...properties };\n \n // Remove internal properties\n delete sanitized.category;\n delete sanitized.page_type;\n delete sanitized.store_id;\n delete sanitized.page_url;\n delete sanitized.page_title;\n delete sanitized.screen_name;\n delete sanitized.referrer;\n delete sanitized.funnel_step;\n delete sanitized.funnel_step_number;\n \n // Remove PII. A backstop, not a scrubber: it drops these exact top-level keys only (so not\n // delivery_address, postalCode or nested objects). The address keys catch an address sent\n // by mistake, as the iOS app's delivery_unavailable events do with `address`. `query` is left\n // alone on purpose: search and location-search events use it for what was typed.\n const piiFields = ['email', 'phone', 'password', 'ssn', 'credit_card', 'cvv', 'address', 'street', 'postal_code', 'zip'];\n piiFields.forEach(field => delete sanitized[field]);\n \n return sanitized;\n }\n\n // ============================================================================\n // SESSION TRACKING\n // ============================================================================\n\n protected trackSessionStart(): void {\n this.track('session_start', {\n platform: this.config.platform\n });\n }\n\n trackSessionEnd(): void {\n this.track('session_end', {});\n this.flush(true);\n }\n\n // ============================================================================\n // SCREEN / PAGE TRACKING\n // ============================================================================\n\n screenView(screenName: string, properties: Record<string, any> = {}): this {\n this.currentScreenName = screenName;\n this.currentPageType = this.inferPageType(screenName);\n this.updateFunnelStep(this.currentPageType);\n\n return this.track('screen_view', {\n screen_name: screenName,\n page_type: this.currentPageType,\n ...properties\n });\n }\n\n pageView(properties: Record<string, any> = {}): this {\n const pageType = properties.pageType || properties.page_type || 'unknown';\n this.currentPageType = pageType;\n this.updateFunnelStep(pageType);\n\n return this.track('page_view', {\n page_type: pageType,\n ...properties\n });\n }\n\n protected inferPageType(screenName: string): string {\n const name = screenName.toLowerCase();\n \n if (name.includes('menu') || name.includes('order') || name.includes('food')) return 'menu';\n if (name.includes('cart') || name.includes('basket') || name.includes('bag')) return 'cart';\n if (name.includes('checkout') || name.includes('payment')) return 'checkout';\n if (name.includes('confirm') || name.includes('success') || name.includes('thank')) return 'confirmation';\n if (name.includes('product') || name.includes('item') || name.includes('detail')) return 'product';\n if (name.includes('location') || name.includes('store')) return 'location';\n if (name.includes('account') || name.includes('profile') || name.includes('login')) return 'account';\n if (name.includes('reward') || name.includes('loyalty') || name.includes('point')) return 'rewards';\n if (name.includes('home') || name.includes('landing')) return 'home';\n \n return 'other';\n }\n\n protected updateFunnelStep(pageType: string): void {\n const funnelMap: Record<string, { name: string; number: number }> = {\n home: { name: 'landing', number: 1 },\n location: { name: 'location', number: 1 },\n menu: { name: 'menu', number: 2 },\n product: { name: 'menu', number: 2 },\n cart: { name: 'cart', number: 3 },\n checkout: { name: 'checkout', number: 4 },\n confirmation: { name: 'confirmation', number: 5 }\n };\n\n this.currentFunnelStep = funnelMap[pageType] || null;\n }\n\n // ============================================================================\n // PRODUCT TRACKING\n // ============================================================================\n\n productView(product: Product, properties: Record<string, any> = {}): this {\n return this.track('product_view', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n ...properties\n });\n }\n\n productClick(product: Product, properties: Record<string, any> = {}): this {\n return this.track('product_click', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n ...properties\n });\n }\n\n // ============================================================================\n // CART TRACKING\n // ============================================================================\n\n addToCart(product: Product, quantity: number = 1, properties: Record<string, any> = {}): this {\n this.cartState.itemCount += quantity;\n this.cartState.total += (product.price || 0) * quantity;\n this.cartState.items.push({ ...product, quantity });\n\n return this.track('add_to_cart', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n quantity,\n ...properties\n });\n }\n\n removeFromCart(product: Product, quantity: number = 1, properties: Record<string, any> = {}): this {\n this.cartState.itemCount = Math.max(0, this.cartState.itemCount - quantity);\n this.cartState.total = Math.max(0, this.cartState.total - (product.price || 0) * quantity);\n\n return this.track('remove_from_cart', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n product_category: product.category,\n product_price: product.price,\n quantity,\n ...properties\n });\n }\n\n updateCartQuantity(product: Product, oldQuantity: number, newQuantity: number): this {\n const diff = newQuantity - oldQuantity;\n this.cartState.itemCount += diff;\n this.cartState.total += (product.price || 0) * diff;\n\n return this.track('update_cart_quantity', {\n product_id: product.id || product.product_id,\n product_name: product.name || product.product_name,\n old_quantity: oldQuantity,\n new_quantity: newQuantity\n });\n }\n\n setCart(cart: Partial<CartState>): this {\n this.cartState = {\n items: cart.items || [],\n itemCount: cart.itemCount || 0,\n total: cart.total || 0\n };\n return this;\n }\n\n viewCart(properties: Record<string, any> = {}): this {\n return this.track('cart_view', {\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n ...properties\n });\n }\n\n // ============================================================================\n // CHECKOUT TRACKING\n // ============================================================================\n\n checkoutStart(properties: Record<string, any> = {}): this {\n this.updateFunnelStep('checkout');\n return this.track('checkout_start', {\n cart_value: this.cartState.total,\n cart_item_count: this.cartState.itemCount,\n ...properties\n });\n }\n\n checkoutStep(step: string, properties: Record<string, any> = {}): this {\n return this.track('checkout_step', {\n checkout_step: step,\n ...properties\n });\n }\n\n /**\n * The shopper chose or entered a payment method. Sends add_payment_info with\n * { payment_method } at funnel step checkout_payment (4); the cart value and item count ride\n * on the event itself, as on every event (matching the v1 bundle's addPaymentInfo).\n */\n addPaymentInfo(paymentMethod: string, properties: Record<string, any> = {}): this {\n return this.track('add_payment_info', {\n payment_method: paymentMethod,\n funnel_step: 'checkout_payment',\n funnel_step_number: 4,\n ...properties\n });\n }\n\n checkoutComplete(order: Order, properties: Record<string, any> = {}): this {\n this.updateFunnelStep('confirmation');\n\n const event = this.track('checkout_complete', {\n order_id: order.id || order.order_id,\n olo_order_id: order.olo_order_id,\n order_total: order.total,\n subtotal: order.subtotal,\n tax: order.tax,\n tip: order.tip,\n item_count: order.itemCount || order.item_count,\n order_type: order.orderType || order.order_type,\n payment_method: order.paymentMethod || order.payment_method,\n ...properties\n });\n\n // Clear cart\n this.cartState = { items: [], itemCount: 0, total: 0 };\n\n return event;\n }\n\n // ============================================================================\n // AUTH TRACKING\n // ============================================================================\n\n loginAttempt(method: string, properties: Record<string, any> = {}): this {\n return this.track('login_attempt', {\n login_method: method,\n funnel_step: this.currentFunnelStep?.name,\n ...properties\n });\n }\n\n loginSuccess(method: string, customerId?: string, properties: Record<string, any> = {}): this {\n this.sessionData.is_logged_in = true;\n this.sessionData.login_method = method;\n this.sessionData.logged_in_at = getTimestamp();\n this.sessionData.login_funnel_step = this.currentFunnelStep?.name || null;\n \n if (customerId) {\n this.customerId = customerId;\n }\n\n this.saveSession();\n\n return this.track('login_success', {\n login_method: method,\n customer_id: customerId,\n funnel_step: this.currentFunnelStep?.name,\n ...properties\n });\n }\n\n loginFailure(method: string, error?: string, properties: Record<string, any> = {}): this {\n return this.track('login_failure', {\n login_method: method,\n error_message: error,\n ...properties\n });\n }\n\n logout(properties: Record<string, any> = {}): this {\n const previousCustomerId = this.customerId;\n \n this.sessionData.is_logged_in = false;\n this.customerId = null;\n this.saveSession();\n\n return this.track('logout', {\n previous_customer_id: previousCustomerId,\n ...properties\n });\n }\n\n identify(customerId: string, traits: Record<string, any> = {}): this {\n this.customerId = customerId;\n this.sessionData.is_logged_in = true;\n this.saveSession();\n\n return this.track('identify', {\n customer_id: customerId,\n traits: this.sanitizeProperties(traits)\n });\n }\n\n // ============================================================================\n // STORE SELECTION\n // ============================================================================\n\n storeSelect(store: { id?: string; store_id?: string; name?: string; store_name?: string }, properties: Record<string, any> = {}): this {\n const storeId = store.id || store.store_id;\n const storeName = store.name || store.store_name;\n if (storeId) {\n this.config.storeId = storeId;\n }\n if (storeName) {\n // Persist so every subsequent event carries the name (the warehouse\n // resolves location names via ANY_VALUE(store_name) per store_id).\n this.config.storeName = storeName;\n }\n\n return this.track('store_select', {\n store_id: storeId,\n store_name: storeName,\n ...properties\n });\n }\n\n setStore(storeId: string, storeName?: string): this {\n this.config.storeId = storeId;\n if (storeName) {\n this.config.storeName = storeName;\n }\n return this;\n }\n\n // ============================================================================\n // SEARCH\n // ============================================================================\n\n search(query: string, resultCount?: number, properties: Record<string, any> = {}): this {\n return this.track('search', {\n search_query: query,\n result_count: resultCount,\n ...properties\n });\n }\n\n // ============================================================================\n // LOYALTY / REWARDS\n // ============================================================================\n\n loyaltyLogin(customer: { id?: string; customer_id?: string; tier?: string; points?: number }, properties: Record<string, any> = {}): this {\n const customerId = customer.id || customer.customer_id;\n if (customerId) {\n this.customerId = customerId;\n }\n\n return this.track('loyalty_login', {\n customer_id: customerId,\n loyalty_tier: customer.tier,\n points_balance: customer.points,\n ...properties\n });\n }\n\n rewardView(reward: { id: string; name: string; value?: number; points_required?: number }, properties: Record<string, any> = {}): this {\n return this.track('reward_view', {\n reward_id: reward.id,\n reward_name: reward.name,\n reward_value: reward.value,\n points_required: reward.points_required,\n ...properties\n });\n }\n\n rewardApply(reward: { id: string; name: string; value?: number; points_used?: number }, properties: Record<string, any> = {}): this {\n return this.track('reward_apply', {\n reward_id: reward.id,\n reward_name: reward.name,\n reward_value: reward.value,\n points_used: reward.points_used,\n ...properties\n });\n }\n\n rewardRemove(reward: { id: string; name: string }, properties: Record<string, any> = {}): this {\n return this.track('reward_remove', {\n reward_id: reward.id,\n reward_name: reward.name,\n ...properties\n });\n }\n\n // ============================================================================\n // PROMO CODES\n // ============================================================================\n\n promoApply(promo: { code: string; discount?: number; success: boolean; error?: string }, properties: Record<string, any> = {}): this {\n return this.track('promo_apply', {\n promo_code: promo.code,\n discount_amount: promo.discount,\n success: promo.success,\n error_message: promo.error,\n ...properties\n });\n }\n\n promoRemove(promoCode: string, properties: Record<string, any> = {}): this {\n return this.track('promo_remove', {\n promo_code: promoCode,\n ...properties\n });\n }\n\n // ============================================================================\n // EXPERIMENTS\n // ============================================================================\n\n setExperiment(experimentKey: string, variantKey: string): this {\n this.sessionData.experiment_assignments[experimentKey] = variantKey;\n this.saveSession();\n\n return this.track('experiment_assigned', {\n experiment_key: experimentKey,\n variant_key: variantKey\n });\n }\n\n // ============================================================================\n // ERRORS\n // ============================================================================\n\n error(errorType: string, errorMessage: string, context: Record<string, any> = {}): this {\n return this.track('error', {\n error_type: errorType,\n error_message: errorMessage,\n ...context\n });\n }\n\n // ============================================================================\n // QUEUE & FLUSH\n // ============================================================================\n\n protected queueEvent(event: Event): void {\n this.eventQueue.push(event);\n\n if (this.eventQueue.length >= this.config.batchSize) {\n this.flush();\n }\n }\n\n protected startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n if (this.eventQueue.length > 0) {\n this.flush();\n }\n }, this.config.flushInterval);\n }\n\n async flush(sync: boolean = false): Promise<void> {\n if (this.eventQueue.length === 0) return;\n\n const events = [...this.eventQueue];\n this.eventQueue = [];\n\n const payload = {\n batch_id: generateUUID(),\n tenant_slug: this.config.tenantSlug || this.config.tenantId,\n events,\n sent_at: getTimestamp()\n };\n\n try {\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload)\n });\n this.log('debug', 'Flushed events', { count: events.length });\n } catch (error) {\n this.log('error', 'Failed to send events', error);\n // Re-queue events\n this.eventQueue = [...events, ...this.eventQueue];\n }\n }\n\n // ============================================================================\n // UTILITIES\n // ============================================================================\n\n getSessionId(): string {\n return this.sessionId;\n }\n\n getVisitorId(): string {\n return this.visitorId;\n }\n\n getCustomerId(): string | null {\n return this.customerId;\n }\n\n isLoggedIn(): boolean {\n return this.sessionData.is_logged_in;\n }\n\n protected log(level: string, message: string, data?: any): void {\n if (!this.config.debug && level === 'debug') return;\n \n const prefix = '[VeyaAnalytics]';\n if (level === 'error') {\n console.error(prefix, message, data || '');\n } else if (level === 'warn') {\n console.warn(prefix, message, data || '');\n } else {\n console.log(prefix, message, data || '');\n }\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n }\n this.flush(true);\n }\n}\n\nexport default VeyaAnalyticsCore;\n", "/**\n * Veya Analytics SDK - Web\n * \n * Smart analytics for web browsers with auto-detection\n * \n * @version 4.0.2\n */\n\nimport { \n VeyaAnalyticsCore, \n VeyaConfig, \n DeviceInfo,\n StorageAdapter,\n generateUUID,\n getTimestamp\n} from '../core/VeyaAnalyticsCore.js';\n\n// ============================================================================\n// LOCAL STORAGE ADAPTER\n// ============================================================================\n\nclass LocalStorageAdapter implements StorageAdapter {\n async getItem(key: string): Promise<string | null> {\n try {\n return localStorage.getItem(key);\n } catch (e) {\n return null;\n }\n }\n\n async setItem(key: string, value: string): Promise<void> {\n try {\n localStorage.setItem(key, value);\n } catch (e) {}\n }\n\n async removeItem(key: string): Promise<void> {\n try {\n localStorage.removeItem(key);\n } catch (e) {}\n }\n}\n\n// ============================================================================\n// PAGE DETECTOR\n// ============================================================================\n\nconst PAGE_PATTERNS: Record<string, { urlPatterns: RegExp[]; domSignals: string[]; titlePatterns: RegExp[] }> = {\n menu: {\n urlPatterns: [/\\/menu/i, /\\/order/i, /\\/food/i, /\\/products/i],\n domSignals: ['[data-product]', '.menu-item', '.product-card', '.food-item'],\n titlePatterns: [/menu/i, /order/i, /food/i]\n },\n cart: {\n urlPatterns: [/\\/cart/i, /\\/basket/i, /\\/bag/i],\n domSignals: ['.cart-item', '.basket-item', '[data-cart]', '.cart-summary'],\n titlePatterns: [/cart/i, /basket/i, /your order/i]\n },\n checkout: {\n urlPatterns: [/\\/checkout/i, /\\/payment/i, /\\/pay\\b/i],\n domSignals: ['[data-checkout]', '.checkout-form', '.payment-form'],\n titlePatterns: [/checkout/i, /payment/i]\n },\n confirmation: {\n urlPatterns: [/\\/confirm/i, /\\/thank/i, /\\/success/i],\n domSignals: ['.confirmation', '.order-confirmed', '.thank-you'],\n titlePatterns: [/thank/i, /confirm/i, /success/i]\n },\n product: {\n urlPatterns: [/\\/product\\//i, /\\/item\\//i],\n domSignals: ['.product-detail', '.item-detail'],\n titlePatterns: []\n },\n location: {\n urlPatterns: [/\\/location/i, /\\/store/i, /\\/find/i],\n domSignals: ['.store-locator', '.location-picker'],\n titlePatterns: [/location/i, /find.*store/i]\n },\n account: {\n urlPatterns: [/\\/account/i, /\\/profile/i, /\\/login/i, /\\/signin/i],\n domSignals: ['.login-form', '.account-page'],\n titlePatterns: [/account/i, /sign in/i, /log in/i]\n },\n rewards: {\n urlPatterns: [/\\/reward/i, /\\/loyalty/i, /\\/points/i],\n domSignals: ['.rewards', '.loyalty', '.points-balance'],\n titlePatterns: [/reward/i, /loyalty/i]\n },\n home: {\n urlPatterns: [/^\\/$/, /\\/home/i],\n domSignals: ['.hero', '.home-banner'],\n titlePatterns: []\n }\n};\n\n// ============================================================================\n// WEB ANALYTICS CLASS\n// ============================================================================\n\n// Scroll-depth thresholds (percent of the scrollable distance); each fires once per page view\nconst SCROLL_DEPTHS = [25, 50, 75, 100];\n\nexport class VeyaAnalyticsWeb extends VeyaAnalyticsCore {\n private pageDetectionCache: Map<string, { type: string; confidence: number }> = new Map();\n private productTracker: ProductTracker | null = null;\n private cartTracker: CartTracker | null = null;\n private networkInterceptor: NetworkInterceptor | null = null;\n\n // Page-level state for time_on_page and scroll depth; both reset on every page view\n private pageStartedAt: number = Date.now();\n private scrollDepthsFired: Set<number> = new Set();\n private scrollCheckPending: boolean = false;\n\n constructor() {\n super();\n this.storage = new LocalStorageAdapter();\n }\n\n init(options: VeyaConfig): Promise<this> {\n return super.init({ ...options, platform: 'web' });\n }\n\n // Runs exactly once, after the core is initialized (see VeyaAnalyticsCore.init)\n protected async onInitialized(): Promise<void> {\n this.pageStartedAt = Date.now();\n\n // Setup auto-detection if enabled\n if (this.config.autoDetect) {\n this.setupPageChangeDetection();\n }\n\n if (this.config.autoTrackProducts) {\n this.productTracker = new ProductTracker(this);\n this.productTracker.init();\n }\n\n if (this.config.autoTrackCart) {\n this.cartTracker = new CartTracker(this);\n this.cartTracker.init();\n }\n\n if (this.config.interceptOloApi) {\n this.networkInterceptor = new NetworkInterceptor(this, this.config);\n this.networkInterceptor.init();\n }\n\n // Setup browser event listeners\n this.setupBrowserListeners();\n\n // Track the initial page only when the SDK owns page views. With autoDetect off the app\n // sends its own page_view, and tracking one here as well doubled every full page load.\n if (this.config.autoDetect) {\n this.trackCurrentPage();\n }\n }\n\n protected async getDeviceInfo(): Promise<DeviceInfo> {\n const ua = navigator.userAgent;\n \n return {\n device_type: this.getDeviceType(),\n platform: 'web',\n os: this.getOS(),\n os_version: this.getOSVersion(),\n screen_width: window.screen.width,\n screen_height: window.screen.height,\n language: navigator.language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone\n };\n }\n\n private getDeviceType(): string {\n const ua = navigator.userAgent.toLowerCase();\n const width = window.innerWidth;\n \n if (/ipad|tablet|playbook|silk/i.test(ua) || (width >= 768 && width < 1024)) {\n return 'tablet';\n }\n if (/mobile|iphone|ipod|android|blackberry/i.test(ua) || width < 768) {\n return 'mobile';\n }\n return 'desktop';\n }\n\n private getOS(): string {\n const ua = navigator.userAgent;\n if (/Windows/.test(ua)) return 'Windows';\n if (/Mac OS X/.test(ua)) return 'macOS';\n if (/Android/.test(ua)) return 'Android';\n if (/iOS|iPhone|iPad/.test(ua)) return 'iOS';\n if (/Linux/.test(ua)) return 'Linux';\n return 'unknown';\n }\n\n private getOSVersion(): string {\n const ua = navigator.userAgent;\n const match = ua.match(/(?:Windows NT|Mac OS X|Android|iOS)\\s*([\\d._]+)/i);\n return match ? match[1].replace(/_/g, '.') : 'unknown';\n }\n\n // ============================================================================\n // PAGE DETECTION\n // ============================================================================\n\n private setupPageChangeDetection(): void {\n let lastUrl = window.location.href;\n\n const handleUrlChange = () => {\n if (window.location.href !== lastUrl) {\n lastUrl = window.location.href;\n this.pageDetectionCache.clear();\n this.trackCurrentPage();\n \n if (this.productTracker) {\n this.productTracker.reset();\n }\n }\n };\n\n window.addEventListener('popstate', handleUrlChange);\n \n const originalPushState = history.pushState;\n const originalReplaceState = history.replaceState;\n\n history.pushState = function() {\n originalPushState.apply(this, arguments as any);\n handleUrlChange();\n };\n\n history.replaceState = function() {\n originalReplaceState.apply(this, arguments as any);\n handleUrlChange();\n };\n\n window.addEventListener('hashchange', handleUrlChange);\n }\n\n private detectPageType(): { type: string; confidence: number } {\n const cacheKey = window.location.pathname + document.title;\n \n if (this.pageDetectionCache.has(cacheKey)) {\n return this.pageDetectionCache.get(cacheKey)!;\n }\n\n const url = window.location.href.toLowerCase();\n const path = window.location.pathname.toLowerCase();\n const title = document.title.toLowerCase();\n\n const scores: Record<string, number> = {};\n\n for (const [pageType, patterns] of Object.entries(PAGE_PATTERNS)) {\n let score = 0;\n\n // URL matching (40%)\n for (const pattern of patterns.urlPatterns) {\n if (pattern.test(path)) {\n score += 40;\n break;\n }\n }\n\n // DOM signals (40%)\n let domMatches = 0;\n for (const selector of patterns.domSignals) {\n try {\n if (document.querySelector(selector)) domMatches++;\n } catch (e) {}\n }\n if (patterns.domSignals.length > 0) {\n score += (domMatches / patterns.domSignals.length) * 40;\n }\n\n // Title matching (20%)\n for (const pattern of patterns.titlePatterns) {\n if (pattern.test(title)) {\n score += 20;\n break;\n }\n }\n\n scores[pageType] = score / 100;\n }\n\n let bestType = 'unknown';\n let bestScore = 0;\n\n for (const [type, score] of Object.entries(scores)) {\n if (score > bestScore) {\n bestScore = score;\n bestType = type;\n }\n }\n\n const result = {\n type: bestScore >= (this.config.confidenceThreshold || 0.7) ? bestType : 'unknown',\n confidence: bestScore\n };\n\n this.pageDetectionCache.set(cacheKey, result);\n this.currentPageType = result.type;\n\n return result;\n }\n\n private trackCurrentPage(): void {\n const detection = this.detectPageType();\n \n this.pageView({\n page_url: window.location.href,\n page_title: document.title,\n page_type: detection.type,\n page_type_confidence: detection.confidence,\n referrer: document.referrer,\n ...this.getUTMParams()\n });\n }\n\n // Every page view (SDK-detected or sent by the app) starts a new page: time_on_page restarts and\n // the scroll-depth thresholds can fire again.\n pageView(properties: Record<string, any> = {}): this {\n this.pageStartedAt = Date.now();\n this.scrollDepthsFired.clear();\n return super.pageView(properties);\n }\n\n private getUTMParams(): Record<string, string | null> {\n const params = new URLSearchParams(window.location.search);\n return {\n utm_source: params.get('utm_source'),\n utm_medium: params.get('utm_medium'),\n utm_campaign: params.get('utm_campaign'),\n utm_term: params.get('utm_term'),\n utm_content: params.get('utm_content')\n };\n }\n\n // ============================================================================\n // BROWSER LISTENERS\n // ============================================================================\n\n private setupBrowserListeners(): void {\n // Tab hidden / shown. page_hidden carries how long the current page has been open (ms since\n // the last page view); page_visible carries nothing extra.\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n this.track('page_hidden', { time_on_page: this.timeOnPage() });\n this.flush(true);\n } else if (document.visibilityState === 'visible') {\n this.track('page_visible');\n }\n });\n\n // Leaving the page. This is not session_end: every full navigation unloads the page while\n // the session carries on (4.0.0 sent session_end here). pagehide, not beforeunload: while a\n // beforeunload listener exists Firefox keeps the page out of its back/forward cache (so Back\n // reloads it instead of restoring it), and pagehide is also the event mobile browsers fire\n // reliably when a tab is closed. It fires too when the page goes into that cache, in which\n // case persisted is true: the page may come back (see pageshow) rather than being gone.\n window.addEventListener('pagehide', (event: PageTransitionEvent) => {\n this.track('page_unload', { time_on_page: this.timeOnPage(), persisted: event.persisted });\n this.flush(true);\n });\n\n // Restored from the back/forward cache: the page reappears as it was left, with no new load\n // and no init, so restart the page timer and the scroll-depth thresholds, and count it as a\n // page view when the SDK owns page views. A normal load fires pageshow too, with persisted\n // false; that one is ignored (the load's own page view, if any, was already sent).\n window.addEventListener('pageshow', (event: PageTransitionEvent) => {\n if (!event.persisted) return;\n this.pageStartedAt = Date.now();\n this.scrollDepthsFired.clear();\n if (this.config.autoDetect) {\n this.trackCurrentPage();\n }\n });\n\n // Scroll depth. Checked at most every 100ms, and always after the last scroll event of a\n // burst, so the final position is measured even when scrolling fast.\n window.addEventListener('scroll', () => {\n if (this.scrollCheckPending) return;\n this.scrollCheckPending = true;\n setTimeout(() => {\n this.scrollCheckPending = false;\n this.checkScrollDepth();\n }, 100);\n }, { passive: true });\n\n // Errors\n window.addEventListener('error', (e) => {\n this.error('javascript', e.message, {\n filename: e.filename,\n lineno: e.lineno,\n colno: e.colno\n });\n });\n\n window.addEventListener('unhandledrejection', (e) => {\n this.error('promise_rejection', e.reason?.message || String(e.reason));\n });\n }\n\n private timeOnPage(): number {\n return Math.max(0, Date.now() - this.pageStartedAt);\n }\n\n // Fires every threshold at or below the current depth that hasn't fired yet on this page, so a\n // fast scroll that jumps past several thresholds still reports each of them once.\n private checkScrollDepth(): void {\n const scrollable = document.documentElement.scrollHeight - window.innerHeight;\n if (scrollable <= 0) return; // the page doesn't scroll: nothing to measure (and no divide by zero)\n\n const percent = Math.min(100, Math.round((window.scrollY / scrollable) * 100));\n for (const depth of SCROLL_DEPTHS) {\n if (percent >= depth && !this.scrollDepthsFired.has(depth)) {\n this.scrollDepthsFired.add(depth);\n this.track('scroll_depth', { depth });\n }\n }\n }\n\n // ============================================================================\n // FLUSH OVERRIDE FOR WEB\n // ============================================================================\n\n async flush(sync: boolean = false): Promise<void> {\n if (this.eventQueue.length === 0) return;\n\n const events = [...this.eventQueue];\n this.eventQueue = [];\n\n const payload = {\n batch_id: generateUUID(),\n tenant_slug: this.config.tenantSlug || this.config.tenantId,\n events,\n sent_at: getTimestamp()\n };\n\n if (sync && navigator.sendBeacon) {\n navigator.sendBeacon(this.config.endpoint, JSON.stringify(payload));\n } else {\n try {\n await fetch(this.config.endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n keepalive: true\n });\n } catch (error) {\n this.eventQueue = [...events, ...this.eventQueue];\n }\n }\n }\n\n destroy(): void {\n if (this.productTracker) this.productTracker.destroy();\n if (this.cartTracker) this.cartTracker.destroy();\n if (this.networkInterceptor) this.networkInterceptor.destroy();\n super.destroy();\n }\n}\n\n// ============================================================================\n// PRODUCT TRACKER\n// ============================================================================\n\nclass ProductTracker {\n private sdk: VeyaAnalyticsWeb;\n private viewedProducts: Set<string> = new Set();\n private observer: MutationObserver | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb) {\n this.sdk = sdk;\n }\n\n init(): void {\n this.intersectionObserver = new IntersectionObserver(\n this.handleIntersection.bind(this),\n { threshold: 0.5 }\n );\n\n this.scanForProducts();\n\n this.observer = new MutationObserver(() => {\n setTimeout(() => this.scanForProducts(), 500);\n });\n\n this.observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n private scanForProducts(): void {\n const selectors = [\n '[data-product-id]',\n '[data-product]',\n '.product-card',\n '.menu-item',\n '.food-item'\n ];\n\n for (const selector of selectors) {\n try {\n document.querySelectorAll(selector).forEach(el => {\n if (!(el as HTMLElement).dataset.veyaTracked) {\n (el as HTMLElement).dataset.veyaTracked = 'true';\n this.intersectionObserver?.observe(el);\n }\n });\n } catch (e) {}\n }\n }\n\n private handleIntersection(entries: IntersectionObserverEntry[]): void {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n const product = this.extractProductData(entry.target as HTMLElement);\n if (product.name && !this.viewedProducts.has(product.id || product.name)) {\n this.viewedProducts.add(product.id || product.name);\n this.sdk.productView(product, { auto: true });\n }\n }\n });\n }\n\n private extractProductData(element: HTMLElement): any {\n return {\n id: element.dataset.productId || element.dataset.id || element.id,\n name: element.dataset.productName || element.dataset.name || \n element.querySelector('.product-name, .item-name, h2, h3')?.textContent?.trim(),\n category: element.dataset.category,\n price: parseFloat(element.dataset.price || '0') || null\n };\n }\n\n reset(): void {\n this.viewedProducts.clear();\n this.scanForProducts();\n }\n\n destroy(): void {\n this.observer?.disconnect();\n this.intersectionObserver?.disconnect();\n }\n}\n\n// ============================================================================\n// CART TRACKER\n// ============================================================================\n\nclass CartTracker {\n private sdk: VeyaAnalyticsWeb;\n private observer: MutationObserver | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb) {\n this.sdk = sdk;\n }\n\n init(): void {\n const cartSelectors = ['.cart', '.basket', '#cart', '[data-cart]'];\n\n this.observer = new MutationObserver(() => {\n // Cart changed - could extract and compare state\n });\n\n for (const selector of cartSelectors) {\n const cartEl = document.querySelector(selector);\n if (cartEl) {\n this.observer.observe(cartEl, {\n childList: true,\n subtree: true\n });\n break;\n }\n }\n }\n\n destroy(): void {\n this.observer?.disconnect();\n }\n}\n\n// ============================================================================\n// NETWORK INTERCEPTOR\n// ============================================================================\n\nclass NetworkInterceptor {\n private sdk: VeyaAnalyticsWeb;\n private config: any;\n private originalFetch: typeof fetch | null = null;\n\n constructor(sdk: VeyaAnalyticsWeb, config: any) {\n this.sdk = sdk;\n this.config = config;\n }\n\n init(): void {\n this.originalFetch = window.fetch;\n const self = this;\n\n window.fetch = function(input: RequestInfo | URL, init?: RequestInit) {\n const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n \n return self.originalFetch!.apply(window, [input, init])\n .then(response => {\n self.handleResponse(url, response.clone());\n return response;\n });\n };\n }\n\n private async handleResponse(url: string, response: Response): Promise<void> {\n if (!this.isOloApi(url)) return;\n\n try {\n const data = await response.json();\n \n // Detect order completion\n if (url.includes('order') && data.id) {\n this.sdk.checkoutComplete({\n id: data.id,\n olo_order_id: data.id,\n total: data.total,\n orderType: data.deliveryMode || data.type\n }, { auto: true });\n }\n\n // Detect basket updates\n if (url.includes('basket') && data.products) {\n this.sdk.setCart({\n items: data.products,\n total: data.total || data.subtotal,\n itemCount: data.products.reduce((sum: number, p: any) => sum + (p.quantity || 1), 0)\n });\n }\n } catch (e) {}\n }\n\n private isOloApi(url: string): boolean {\n const patterns = [/\\/basket/i, /\\/order/i, /olo\\.com/i];\n return patterns.some(p => p.test(url));\n }\n\n destroy(): void {\n if (this.originalFetch) {\n window.fetch = this.originalFetch;\n }\n }\n}\n\n// ============================================================================\n// SINGLETON & EXPORT\n// ============================================================================\n\nconst veya = new VeyaAnalyticsWeb();\n\n// Expose to window for script tag usage\nif (typeof window !== 'undefined') {\n (window as any).VeyaAnalytics = veya;\n (window as any).veya = veya;\n}\n\nexport default veya;\nexport type { VeyaConfig };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["index_exports", "__export", "VeyaAnalyticsCore", "VeyaAnalyticsWeb", "VeyaAnalyticsWeb_default", "generateUUID", "getTimestamp", "DEFAULT_CONFIG", "generateUUID", "c", "r", "getTimestamp", "VeyaAnalyticsCore", "__publicField", "options", "error", "isNewSession", "stored", "now", "sessionData", "eventName", "properties", "event", "_a", "_b", "sanitized", "field", "screenName", "pageType", "name", "funnelMap", "product", "quantity", "oldQuantity", "newQuantity", "diff", "cart", "step", "paymentMethod", "order", "method", "customerId", "previousCustomerId", "traits", "store", "storeId", "storeName", "query", "resultCount", "customer", "reward", "promo", "promoCode", "experimentKey", "variantKey", "errorType", "errorMessage", "context", "sync", "events", "payload", "level", "message", "data", "prefix", "LocalStorageAdapter", "key", "value", "PAGE_PATTERNS", "SCROLL_DEPTHS", "VeyaAnalyticsWeb", "VeyaAnalyticsCore", "options", "ProductTracker", "CartTracker", "NetworkInterceptor", "ua", "width", "match", "lastUrl", "handleUrlChange", "originalPushState", "originalReplaceState", "cacheKey", "url", "path", "title", "scores", "pageType", "patterns", "score", "pattern", "domMatches", "selector", "bestType", "bestScore", "type", "result", "detection", "properties", "params", "event", "_a", "scrollable", "percent", "depth", "sync", "events", "payload", "generateUUID", "getTimestamp", "sdk", "selectors", "el", "entries", "entry", "product", "element", "_b", "cartSelectors", "cartEl", "config", "self", "input", "init", "response", "data", "sum", "p", "veya", "VeyaAnalyticsWeb_default"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@builtonveya/analytics-web",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "Veya Analytics SDK for the web - auto-detecting page, product and cart tracking for restaurant ordering sites",
|
|
5
5
|
"main": "dist/cjs/web/index.js",
|
|
6
6
|
"module": "dist/esm/web/index.js",
|