@li2/analytics 0.3.4 → 0.4.0-beta.1

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.
Files changed (45) hide show
  1. package/dist/auto-events.global.js +1 -1
  2. package/dist/auto-events.js +1 -1
  3. package/dist/auto-events.mjs +1 -1
  4. package/dist/chunk-4EC35KD3.mjs +1 -0
  5. package/dist/chunk-5TDT656N.mjs +0 -0
  6. package/dist/chunk-772JYJV2.mjs +1 -0
  7. package/dist/chunk-EO7Y3K6L.mjs +1 -0
  8. package/dist/chunk-FF6VDEL5.mjs +1 -1
  9. package/dist/chunk-GS2LGTLM.mjs +1 -0
  10. package/dist/chunk-HWKYLC4Q.mjs +1 -0
  11. package/dist/chunk-KZDID5T3.mjs +1 -0
  12. package/dist/chunk-LZDMBCUK.mjs +1 -0
  13. package/dist/chunk-MURA7RU5.mjs +0 -1
  14. package/dist/chunk-PGNNL26O.mjs +1 -0
  15. package/dist/chunk-PSKG2XOE.mjs +1 -0
  16. package/dist/click-tracker/index.global.js +1 -1
  17. package/dist/click-tracker/index.js +1 -1
  18. package/dist/click-tracker/index.mjs +1 -1
  19. package/dist/{index-DVbXHaIv.d.mts → index-BlPDBYpZ.d.mts} +2 -0
  20. package/dist/{index-DVbXHaIv.d.ts → index-BlPDBYpZ.d.ts} +2 -0
  21. package/dist/index.d.mts +24 -2
  22. package/dist/index.d.ts +24 -2
  23. package/dist/index.global.js +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.mjs +1 -1
  26. package/dist/interaction-batch-sender-E3M77C4U.mjs +1 -0
  27. package/dist/interaction-batch-sender-GVPPBMES.mjs +1 -0
  28. package/dist/interaction-batch-sender-PLC6EBSJ.mjs +1 -0
  29. package/dist/interaction-batch-sender-S4752CBB.mjs +0 -0
  30. package/dist/outbound.global.js +1 -1
  31. package/dist/outbound.js +1 -1
  32. package/dist/outbound.mjs +1 -1
  33. package/dist/pageview/index.d.mts +1 -1
  34. package/dist/pageview/index.d.ts +1 -1
  35. package/dist/pageview/index.global.js +1 -1
  36. package/dist/pageview/index.js +1 -1
  37. package/dist/pageview/index.mjs +1 -1
  38. package/dist/scroll-tracker-YQKUW7A7.mjs +1 -0
  39. package/dist/toolbar/index.d.mts +4 -3
  40. package/dist/toolbar/index.d.ts +4 -3
  41. package/dist/toolbar/index.global.js +51 -2
  42. package/dist/toolbar/index.js +51 -2
  43. package/dist/toolbar/index.mjs +51 -2
  44. package/package.json +1 -1
  45. package/dist/chunk-6HT4HNX2.mjs +0 -1
@@ -1 +1 @@
1
- "use strict";var d=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var w=(i,e)=>{for(var t in e)d(i,t,{get:e[t],enumerable:!0})},_=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of x(e))!y.call(i,o)&&o!==t&&d(i,o,{get:()=>e[o],enumerable:!(n=C(e,o))||n.enumerable});return i};var T=i=>_(d({},"__esModule",{value:!0}),i);var R={};w(R,{ClickTracker:()=>f,DEFAULT_CLICK_TRACKER_CONFIG:()=>N});module.exports=T(R);var a="li2_vid",g="li2_sid",p="li2_la",c=class{constructor(e){this.config=e,this.visitorId=this.resolveVisitorId(),this.sessionId=this.resolveSessionId()}getVisitorId(){return this.visitorId}getSessionId(){return this.isSessionExpired()&&this.createNewSession(),this.sessionId}touch(){let e=Date.now();this.setStorage(p,e.toString(),"session")}createNewSession(){this.sessionId=this.generateId("sess"),this.setStorage(g,this.sessionId,"session"),this.touch()}resolveVisitorId(){let e=this.getStorage(a,"local");return!e&&!this.config.cookieLessMode&&(e=this.getCookie(a)),e||(e=this.generateId("vis")),this.setStorage(a,e,"local"),this.config.cookieLessMode||this.setCookie(a,e,365),e}resolveSessionId(){let e=this.getStorage(g,"session");return(!e||this.isSessionExpired())&&(e=this.generateId("sess"),this.setStorage(g,e,"session"),this.touch()),e}isSessionExpired(){let e=this.getStorage(p,"session");if(!e)return!0;let t=Date.now()-parseInt(e,10),n=this.config.timeout*60*1e3;return t>n}generateId(e){if(typeof crypto<"u"&&crypto.randomUUID)return`${e}_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`;let t=Array.from({length:16},()=>Math.floor(Math.random()*16).toString(16)).join("");return`${e}_${t}`}getStorage(e,t){try{return(t==="local"?localStorage:sessionStorage).getItem(e)}catch{return null}}setStorage(e,t,n){try{(n==="local"?localStorage:sessionStorage).setItem(e,t)}catch{}}getCookie(e){let t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}setCookie(e,t,n){let o=[`${e}=${encodeURIComponent(t)}`,`path=${this.config.cookiePath}`,`max-age=${n*86400}`,"SameSite=Lax"];this.config.cookieDomain&&o.push(`domain=${this.config.cookieDomain}`),window.location.protocol==="https:"&&o.push("Secure"),document.cookie=o.join("; ")}};var L=new Set(["a","button","input","select","textarea","form","label"]),M=new Set(["button","link","tab","menuitem"]);function v(i){let e=i;for(;e&&!(e instanceof HTMLElement);)e=e.parentElement;if(!e)return null;let n=P(e),o=$(n);return{tag:n.tagName.toLowerCase(),text:b(D(n),256),href:H(n),className:b(n.className||"",512),id:n.id||null,selectorPath:U(n),isFixed:o}}function P(i){let e=i,t=0;for(;e&&t<5&&e.tagName!=="BODY";){let n=e.tagName.toLowerCase(),o=e.getAttribute("role");if(L.has(n)||o&&M.has(o))return e;e=e.parentElement,t++}return i}function $(i){let e=i;for(;e&&e!==document.body;){try{let n=window.getComputedStyle(e).getPropertyValue("position");if(n==="fixed"||n==="sticky")return!0}catch{break}e=e.parentElement}return!1}function U(i){let e=[],t=i,n=0;for(;t&&t!==document.body&&n<5;){let o=t.tagName.toLowerCase();t.id&&(o+=`#${t.id}`);let s=t.parentElement;if(s){let r=Array.from(s.children).filter(l=>l.tagName===t.tagName);if(r.length>1){let l=r.indexOf(t)+1;o+=`:nth-of-type(${l})`}}e.unshift(o),t=t.parentElement,n++}return e.join(" > ")}function D(i){return i instanceof HTMLInputElement?i.value||i.placeholder||"":(i.innerText||i.textContent||"").trim()}function H(i){return i instanceof HTMLAnchorElement?i.href||null:i.getAttribute("href")||null}function b(i,e){return i.length<=e?i:i.slice(0,e)}function E(i,e){let t=window.scrollX||document.documentElement.scrollLeft,n=window.scrollY||document.documentElement.scrollTop;return{x:i.clientX+(e?0:t),y:i.clientY+(e?0:n),scrollY:n,pageHeight:document.documentElement.scrollHeight}}var h=class{constructor(e){this.buffer=[];this.timer=null;this.started=!1;this.handleBeforeUnload=null;this.handleVisibilityChange=null;this.config=e}start(){this.started||(this.started=!0,this.timer=setInterval(()=>this.flush(),this.config.batchInterval),this.handleBeforeUnload=()=>this.flush(!0),window.addEventListener("beforeunload",this.handleBeforeUnload),this.handleVisibilityChange=()=>{document.visibilityState==="hidden"&&this.flush(!0)},document.addEventListener("visibilitychange",this.handleVisibilityChange))}stop(){this.started&&(this.started=!1,this.flush(!0),this.timer&&(clearInterval(this.timer),this.timer=null),this.handleBeforeUnload&&(window.removeEventListener("beforeunload",this.handleBeforeUnload),this.handleBeforeUnload=null),this.handleVisibilityChange&&(document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.handleVisibilityChange=null))}add(e){this.buffer.push(e),this.buffer.length>=this.config.batchSize&&this.flush()}getBufferSize(){return this.buffer.length}flush(e=!1){if(this.buffer.length===0)return;let t=this.buffer.splice(0,this.config.batchSize),n={interactions:t},o=`${this.config.apiUrl}/api/v1/track/interaction`,s=JSON.stringify(n);if(e&&navigator.sendBeacon){let r=`${o}?li2_key=${encodeURIComponent(this.config.publishableKey)}`,l=new Blob([s],{type:"application/json"});navigator.sendBeacon(r,l)?this.log(`Beacon sent: ${t.length} interactions`):this.sendViaFetch(o,s,t)}else this.sendViaFetch(o,s,t);this.buffer.length>0&&this.flush(e)}sendViaFetch(e,t,n){fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Li2-Key":this.config.publishableKey},body:t,keepalive:!0}).then(o=>{o.ok?this.log(`Sent: ${n.length} interactions`):(this.log(`Send failed: ${o.status}, re-queuing ${n.length} events`),this.buffer.unshift(...n))}).catch(()=>{this.log(`Network error, re-queuing ${n.length} events`),this.buffer.unshift(...n)})}log(...e){this.config.debug&&console.log("[Li2 InteractionBatchSender]",...e)}};function I(i,e,t){if(!e)return!0;let{mode:n,includePaths:o,excludePaths:s}=e;if(n==="include"){if(!(o&&o.length>0))return t&&console.log(`[PathFilter] mode=include but no includePaths, blocking "${i}"`),!1;let m=o.some(S=>k(i,S));return t&&(m?console.log(`[PathFilter] mode=include: "${i}" matched includePath`):console.log(`[PathFilter] mode=include: "${i}" not in includePaths:`,o)),m}return s&&s.length>0?s.some(u=>k(i,u))?(t&&console.log(`[PathFilter] mode=exclude: "${i}" matched excludePath:`,s),!1):(t&&console.log(`[PathFilter] Path "${i}" allowed by rules`),!0):(t&&console.log(`[PathFilter] No excludePaths, path "${i}" allowed`),!0)}function k(i,e){let n=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*\*|\*/g,o=>o==="**"?".*":"[^/]*");return new RegExp(`^${n}$`).test(i)}var N={batchInterval:5e3,batchSize:50,excludeSelector:null,debug:!1,sessionTimeout:30,cookieLessMode:!1,cookiePath:"/"},F=50,f=class{constructor(e){this.started=!1;this.handleClick=null;this.lastClickTarget=null;this.lastClickTime=0;this.config=e,this.sessionManager=new c({timeout:e.sessionTimeout,cookieLessMode:e.cookieLessMode,cookieDomain:e.cookieDomain,cookiePath:e.cookiePath}),this.batchSender=new h({apiUrl:e.apiUrl,publishableKey:e.publishableKey,batchInterval:e.batchInterval,batchSize:e.batchSize,debug:e.debug})}start(){this.started||(this.started=!0,this.handleClick=e=>this.onDocumentClick(e),document.addEventListener("click",this.handleClick,!0),this.batchSender.start(),this.log("ClickTracker started"))}stop(){this.started&&(this.started=!1,this.handleClick&&(document.removeEventListener("click",this.handleClick,!0),this.handleClick=null),this.batchSender.stop(),this.log("ClickTracker stopped"))}onDocumentClick(e){if(e.button!==0)return;let t=window.location.pathname;if(!I(t,this.config.dataCollectionRules,this.config.debug)){this.log(`Path excluded from tracking: ${t}`);return}let n=Date.now();if(e.target===this.lastClickTarget&&n-this.lastClickTime<F||(this.lastClickTarget=e.target,this.lastClickTime=n,this.shouldExclude(e.target)))return;let o=v(e.target);if(!o)return;let s=E(e,o.isFixed),r={session_id:this.sessionManager.getSessionId(),visitor_id:this.sessionManager.getVisitorId(),li2_cid:this.config.clickId,page_url:window.location.href,page_path:window.location.pathname,x:s.x,y:s.y,target_fixed:o.isFixed,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_height:s.pageHeight,scroll_y:s.scrollY,element_tag:o.tag,element_text:o.text,element_href:o.href,element_class:o.className,element_id:o.id,selector_path:o.selectorPath,interaction_type:"click",timestamp:n};this.sessionManager.touch(),this.batchSender.add(r)}shouldExclude(e){if(!this.config.excludeSelector||!e)return!1;let t=e;for(;t&&t!==document.body;){try{if(t.matches(this.config.excludeSelector))return!0}catch{return this.log(`Invalid excludeSelector: ${this.config.excludeSelector}`),this.config.excludeSelector=null,!1}t=t.parentElement}return!1}log(...e){this.config.debug&&console.log("[Li2 ClickTracker]",...e)}};0&&(module.exports={ClickTracker,DEFAULT_CLICK_TRACKER_CONFIG});
1
+ "use strict";var h=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var T=(i,e)=>{for(var t in e)h(i,t,{get:e[t],enumerable:!0})},L=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of C(e))!_.call(i,s)&&s!==t&&h(i,s,{get:()=>e[s],enumerable:!(n=w(e,s))||n.enumerable});return i};var M=i=>L(h({},"__esModule",{value:!0}),i);var A={};T(A,{ClickTracker:()=>m,DEFAULT_CLICK_TRACKER_CONFIG:()=>F});module.exports=M(A);var a="li2_vid",g="li2_sid",b="li2_la",c=class{constructor(e){this.config=e,this.visitorId=this.resolveVisitorId(),this.sessionId=this.resolveSessionId()}getVisitorId(){return this.visitorId}getSessionId(){return this.isSessionExpired()&&this.createNewSession(),this.sessionId}touch(){let e=Date.now();this.setStorage(b,e.toString(),"session")}createNewSession(){this.sessionId=this.generateId("sess"),this.setStorage(g,this.sessionId,"session"),this.touch()}resolveVisitorId(){let e=this.getStorage(a,"local");return!e&&!this.config.cookieLessMode&&(e=this.getCookie(a)),e||(e=this.generateId("vis")),this.setStorage(a,e,"local"),this.config.cookieLessMode||this.setCookie(a,e,365),e}resolveSessionId(){let e=this.getStorage(g,"session");return(!e||this.isSessionExpired())&&(e=this.generateId("sess"),this.setStorage(g,e,"session"),this.touch()),e}isSessionExpired(){let e=this.getStorage(b,"session");if(!e)return!0;let t=Date.now()-parseInt(e,10),n=this.config.timeout*60*1e3;return t>n}generateId(e){if(typeof crypto<"u"&&crypto.randomUUID)return`${e}_${crypto.randomUUID().replace(/-/g,"").slice(0,16)}`;let t=Array.from({length:16},()=>Math.floor(Math.random()*16).toString(16)).join("");return`${e}_${t}`}getStorage(e,t){try{return(t==="local"?localStorage:sessionStorage).getItem(e)}catch{return null}}setStorage(e,t,n){try{(n==="local"?localStorage:sessionStorage).setItem(e,t)}catch{}}getCookie(e){let t=document.cookie.match(new RegExp(`(?:^|;\\s*)${e}=([^;]*)`));return t?decodeURIComponent(t[1]):null}setCookie(e,t,n){let s=[`${e}=${encodeURIComponent(t)}`,`path=${this.config.cookiePath}`,`max-age=${n*86400}`,"SameSite=Lax"];this.config.cookieDomain&&s.push(`domain=${this.config.cookieDomain}`),window.location.protocol==="https:"&&s.push("Secure"),document.cookie=s.join("; ")}};var P=new Set(["a","button","input","select","textarea","form","label"]),$=new Set(["button","link","tab","menuitem"]);function k(i){let e=i;for(;e&&!(e instanceof HTMLElement);)e=e.parentElement;if(!e)return null;let n=D(e),s=N(n);return{tag:n.tagName.toLowerCase(),text:v(j(n),256),href:H(n),className:v(n.className||"",512),id:n.id||null,selectorPath:U(n),isFixed:s}}function D(i){let e=i,t=0;for(;e&&t<5&&e.tagName!=="BODY";){let n=e.tagName.toLowerCase(),s=e.getAttribute("role");if(P.has(n)||s&&$.has(s))return e;e=e.parentElement,t++}return i}function N(i){let e=i;for(;e&&e!==document.body;){try{let n=window.getComputedStyle(e).getPropertyValue("position");if(n==="fixed"||n==="sticky")return!0}catch{break}e=e.parentElement}return!1}function U(i){let e=[],t=i,n=0;for(;t&&t!==document.body&&n<5;){let s=t.tagName.toLowerCase();t.id&&(s+=`#${t.id}`);let o=t.parentElement;if(o){let r=Array.from(o.children).filter(l=>l.tagName===t.tagName);if(r.length>1){let l=r.indexOf(t)+1;s+=`:nth-of-type(${l})`}}e.unshift(s),t=t.parentElement,n++}return e.join(" > ")}function j(i){return i instanceof HTMLInputElement?i.value||i.placeholder||"":(i.innerText||i.textContent||"").trim()}function H(i){return i instanceof HTMLAnchorElement?i.href||null:i.getAttribute("href")||null}function v(i,e){return i.length<=e?i:i.slice(0,e)}function x(i,e){let t=window.scrollX||document.documentElement.scrollLeft,n=window.scrollY||document.documentElement.scrollTop;return{x:i.clientX+(e?0:t),y:i.clientY+(e?0:n),scrollY:n,pageHeight:document.documentElement.scrollHeight}}var S={name:"@li2/analytics",version:"0.4.0-beta.1",description:"Li2 Analytics SDK for conversion tracking",main:"dist/index.js",module:"dist/index.mjs",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.mjs",require:"./dist/index.js"},"./pageview":{types:"./dist/pageview/index.d.ts",import:"./dist/pageview/index.mjs",require:"./dist/pageview/index.js"},"./click-tracker":{types:"./dist/click-tracker/index.d.ts",import:"./dist/click-tracker/index.mjs",require:"./dist/click-tracker/index.js"},"./toolbar":{types:"./dist/toolbar/index.d.ts",import:"./dist/toolbar/index.mjs",require:"./dist/toolbar/index.js"}},files:["dist"],scripts:{build:"tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics","build:obfuscate":"tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics && node scripts/obfuscate.js",dev:"tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --watch --global-name li2Analytics",demo:"pnpm run build && node demo/server.js","demo:serve":"node demo/server.js",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage",prepublishOnly:"NODE_OPTIONS=--max-old-space-size=4096 pnpm run build:obfuscate"},keywords:["li2","analytics","conversion","tracking"],author:"Li2",license:"MIT",devDependencies:{"@vitest/coverage-v8":"^4.0.18","happy-dom":"^20.6.1","javascript-obfuscator":"^4.1.0",tsup:"^8.0.0",typescript:"^5.0.0",vitest:"^4.0.18"}};var f=S.version;var d=class{constructor(e){this.buffer=[];this.timer=null;this.started=!1;this.handleBeforeUnload=null;this.handleVisibilityChange=null;this.config=e}start(){this.started||(this.started=!0,this.timer=setInterval(()=>this.flush(),this.config.batchInterval),this.handleBeforeUnload=()=>this.flush(!0),window.addEventListener("beforeunload",this.handleBeforeUnload),this.handleVisibilityChange=()=>{document.visibilityState==="hidden"&&this.flush(!0)},document.addEventListener("visibilitychange",this.handleVisibilityChange))}stop(){this.started&&(this.started=!1,this.flush(!0),this.timer&&(clearInterval(this.timer),this.timer=null),this.handleBeforeUnload&&(window.removeEventListener("beforeunload",this.handleBeforeUnload),this.handleBeforeUnload=null),this.handleVisibilityChange&&(document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.handleVisibilityChange=null))}add(e){this.buffer.push(e),this.buffer.length>=this.config.batchSize&&this.flush()}getBufferSize(){return this.buffer.length}flush(e=!1){if(this.buffer.length===0)return;let t=this.buffer.splice(0,this.config.batchSize),n={interactions:t},s=`${this.config.apiUrl}/api/v1/track/interaction`;if(e&&navigator.sendBeacon){let o={...n,sdk_version:f},r=`${s}?li2_key=${encodeURIComponent(this.config.publishableKey)}`,l=new Blob([JSON.stringify(o)],{type:"application/json"});navigator.sendBeacon(r,l)?this.log(`Beacon sent: ${t.length} interactions`):this.sendViaFetch(s,JSON.stringify(n),t)}else{let o=JSON.stringify(n);this.sendViaFetch(s,o,t)}this.buffer.length>0&&this.flush(e)}sendViaFetch(e,t,n){fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Li2-Key":this.config.publishableKey,"X-Li2-SDK-Version":f},body:t,keepalive:!0}).then(s=>{s.ok?this.log(`Sent: ${n.length} interactions`):(this.log(`Send failed: ${s.status}, re-queuing ${n.length} events`),this.buffer.unshift(...n))}).catch(()=>{this.log(`Network error, re-queuing ${n.length} events`),this.buffer.unshift(...n)})}log(...e){this.config.debug&&console.log("[Li2 InteractionBatchSender]",...e)}};function y(i,e,t){if(!e)return!0;let{mode:n,includePaths:s,excludePaths:o}=e;if(n==="include"){if(!(s&&s.length>0))return t&&console.log(`[PathFilter] mode=include but no includePaths, blocking "${i}"`),!1;let p=s.some(I=>E(i,I));return t&&(p?console.log(`[PathFilter] mode=include: "${i}" matched includePath`):console.log(`[PathFilter] mode=include: "${i}" not in includePaths:`,s)),p}return o&&o.length>0?o.some(u=>E(i,u))?(t&&console.log(`[PathFilter] mode=exclude: "${i}" matched excludePath:`,o),!1):(t&&console.log(`[PathFilter] Path "${i}" allowed by rules`),!0):(t&&console.log(`[PathFilter] No excludePaths, path "${i}" allowed`),!0)}function E(i,e){let n=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*\*|\*/g,s=>s==="**"?".*":"[^/]*");return new RegExp(`^${n}$`).test(i)}var F={batchInterval:5e3,batchSize:50,excludeSelector:null,debug:!1,sessionTimeout:30,cookieLessMode:!1,cookiePath:"/"},V=50,m=class{constructor(e){this.started=!1;this.handleClick=null;this.lastClickTarget=null;this.lastClickTime=0;this.config=e,this.sessionManager=new c({timeout:e.sessionTimeout,cookieLessMode:e.cookieLessMode,cookieDomain:e.cookieDomain,cookiePath:e.cookiePath}),this.batchSender=new d({apiUrl:e.apiUrl,publishableKey:e.publishableKey,batchInterval:e.batchInterval,batchSize:e.batchSize,debug:e.debug})}start(){this.started||(this.started=!0,this.handleClick=e=>this.onDocumentClick(e),document.addEventListener("click",this.handleClick,!0),this.batchSender.start(),this.log("ClickTracker started"))}stop(){this.started&&(this.started=!1,this.handleClick&&(document.removeEventListener("click",this.handleClick,!0),this.handleClick=null),this.batchSender.stop(),this.log("ClickTracker stopped"))}onDocumentClick(e){if(e.button!==0)return;let t=window.location.pathname;if(!y(t,this.config.dataCollectionRules,this.config.debug)){this.log(`Path excluded from tracking: ${t}`);return}let n=Date.now();if(e.target===this.lastClickTarget&&n-this.lastClickTime<V||(this.lastClickTarget=e.target,this.lastClickTime=n,this.shouldExclude(e.target)))return;let s=k(e.target);if(!s)return;let o=x(e,s.isFixed),r={session_id:this.sessionManager.getSessionId(),visitor_id:this.sessionManager.getVisitorId(),li2_cid:this.config.clickId,page_url:window.location.href,page_path:window.location.pathname,x:o.x,y:o.y,target_fixed:s.isFixed,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_height:o.pageHeight,scroll_y:o.scrollY,element_tag:s.tag,element_text:s.text,element_href:s.href,element_class:s.className,element_id:s.id,selector_path:s.selectorPath,interaction_type:"click",timestamp:n};this.sessionManager.touch(),this.batchSender.add(r)}shouldExclude(e){if(!this.config.excludeSelector||!e)return!1;let t=e;for(;t&&t!==document.body;){try{if(t.matches(this.config.excludeSelector))return!0}catch{return this.log(`Invalid excludeSelector: ${this.config.excludeSelector}`),this.config.excludeSelector=null,!1}t=t.parentElement}return!1}log(...e){this.config.debug&&console.log("[Li2 ClickTracker]",...e)}};0&&(module.exports={ClickTracker,DEFAULT_CLICK_TRACKER_CONFIG});
@@ -1 +1 @@
1
- import{a,b as c}from"../chunk-6HT4HNX2.mjs";import{a as h}from"../chunk-FF6VDEL5.mjs";function d(s,e){let t=window.scrollX||document.documentElement.scrollLeft,n=window.scrollY||document.documentElement.scrollTop;return{x:s.clientX+(e?0:t),y:s.clientY+(e?0:n),scrollY:n,pageHeight:document.documentElement.scrollHeight}}var o=class{constructor(e){this.buffer=[];this.timer=null;this.started=!1;this.handleBeforeUnload=null;this.handleVisibilityChange=null;this.config=e}start(){this.started||(this.started=!0,this.timer=setInterval(()=>this.flush(),this.config.batchInterval),this.handleBeforeUnload=()=>this.flush(!0),window.addEventListener("beforeunload",this.handleBeforeUnload),this.handleVisibilityChange=()=>{document.visibilityState==="hidden"&&this.flush(!0)},document.addEventListener("visibilitychange",this.handleVisibilityChange))}stop(){this.started&&(this.started=!1,this.flush(!0),this.timer&&(clearInterval(this.timer),this.timer=null),this.handleBeforeUnload&&(window.removeEventListener("beforeunload",this.handleBeforeUnload),this.handleBeforeUnload=null),this.handleVisibilityChange&&(document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.handleVisibilityChange=null))}add(e){this.buffer.push(e),this.buffer.length>=this.config.batchSize&&this.flush()}getBufferSize(){return this.buffer.length}flush(e=!1){if(this.buffer.length===0)return;let t=this.buffer.splice(0,this.config.batchSize),n={interactions:t},i=`${this.config.apiUrl}/api/v1/track/interaction`,r=JSON.stringify(n);if(e&&navigator.sendBeacon){let l=`${i}?li2_key=${encodeURIComponent(this.config.publishableKey)}`,g=new Blob([r],{type:"application/json"});navigator.sendBeacon(l,g)?this.log(`Beacon sent: ${t.length} interactions`):this.sendViaFetch(i,r,t)}else this.sendViaFetch(i,r,t);this.buffer.length>0&&this.flush(e)}sendViaFetch(e,t,n){fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Li2-Key":this.config.publishableKey},body:t,keepalive:!0}).then(i=>{i.ok?this.log(`Sent: ${n.length} interactions`):(this.log(`Send failed: ${i.status}, re-queuing ${n.length} events`),this.buffer.unshift(...n))}).catch(()=>{this.log(`Network error, re-queuing ${n.length} events`),this.buffer.unshift(...n)})}log(...e){this.config.debug&&console.log("[Li2 InteractionBatchSender]",...e)}};var I={batchInterval:5e3,batchSize:50,excludeSelector:null,debug:!1,sessionTimeout:30,cookieLessMode:!1,cookiePath:"/"},f=50,u=class{constructor(e){this.started=!1;this.handleClick=null;this.lastClickTarget=null;this.lastClickTime=0;this.config=e,this.sessionManager=new a({timeout:e.sessionTimeout,cookieLessMode:e.cookieLessMode,cookieDomain:e.cookieDomain,cookiePath:e.cookiePath}),this.batchSender=new o({apiUrl:e.apiUrl,publishableKey:e.publishableKey,batchInterval:e.batchInterval,batchSize:e.batchSize,debug:e.debug})}start(){this.started||(this.started=!0,this.handleClick=e=>this.onDocumentClick(e),document.addEventListener("click",this.handleClick,!0),this.batchSender.start(),this.log("ClickTracker started"))}stop(){this.started&&(this.started=!1,this.handleClick&&(document.removeEventListener("click",this.handleClick,!0),this.handleClick=null),this.batchSender.stop(),this.log("ClickTracker stopped"))}onDocumentClick(e){if(e.button!==0)return;let t=window.location.pathname;if(!c(t,this.config.dataCollectionRules,this.config.debug)){this.log(`Path excluded from tracking: ${t}`);return}let n=Date.now();if(e.target===this.lastClickTarget&&n-this.lastClickTime<f||(this.lastClickTarget=e.target,this.lastClickTime=n,this.shouldExclude(e.target)))return;let i=h(e.target);if(!i)return;let r=d(e,i.isFixed),l={session_id:this.sessionManager.getSessionId(),visitor_id:this.sessionManager.getVisitorId(),li2_cid:this.config.clickId,page_url:window.location.href,page_path:window.location.pathname,x:r.x,y:r.y,target_fixed:i.isFixed,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_height:r.pageHeight,scroll_y:r.scrollY,element_tag:i.tag,element_text:i.text,element_href:i.href,element_class:i.className,element_id:i.id,selector_path:i.selectorPath,interaction_type:"click",timestamp:n};this.sessionManager.touch(),this.batchSender.add(l)}shouldExclude(e){if(!this.config.excludeSelector||!e)return!1;let t=e;for(;t&&t!==document.body;){try{if(t.matches(this.config.excludeSelector))return!0}catch{return this.log(`Invalid excludeSelector: ${this.config.excludeSelector}`),this.config.excludeSelector=null,!1}t=t.parentElement}return!1}log(...e){this.config.debug&&console.log("[Li2 ClickTracker]",...e)}};export{u as ClickTracker,I as DEFAULT_CLICK_TRACKER_CONFIG};
1
+ import{a as s}from"../chunk-772JYJV2.mjs";import{a}from"../chunk-FF6VDEL5.mjs";import{a as c}from"../chunk-GS2LGTLM.mjs";import"../chunk-EO7Y3K6L.mjs";import{a as r}from"../chunk-LZDMBCUK.mjs";function h(l,e){let t=window.scrollX||document.documentElement.scrollLeft,o=window.scrollY||document.documentElement.scrollTop;return{x:l.clientX+(e?0:t),y:l.clientY+(e?0:o),scrollY:o,pageHeight:document.documentElement.scrollHeight}}var x={batchInterval:5e3,batchSize:50,excludeSelector:null,debug:!1,sessionTimeout:30,cookieLessMode:!1,cookiePath:"/"},m=50,d=class{constructor(e){this.started=!1;this.handleClick=null;this.lastClickTarget=null;this.lastClickTime=0;this.config=e,this.sessionManager=new r({timeout:e.sessionTimeout,cookieLessMode:e.cookieLessMode,cookieDomain:e.cookieDomain,cookiePath:e.cookiePath}),this.batchSender=new c({apiUrl:e.apiUrl,publishableKey:e.publishableKey,batchInterval:e.batchInterval,batchSize:e.batchSize,debug:e.debug})}start(){this.started||(this.started=!0,this.handleClick=e=>this.onDocumentClick(e),document.addEventListener("click",this.handleClick,!0),this.batchSender.start(),this.log("ClickTracker started"))}stop(){this.started&&(this.started=!1,this.handleClick&&(document.removeEventListener("click",this.handleClick,!0),this.handleClick=null),this.batchSender.stop(),this.log("ClickTracker stopped"))}onDocumentClick(e){if(e.button!==0)return;let t=window.location.pathname;if(!s(t,this.config.dataCollectionRules,this.config.debug)){this.log(`Path excluded from tracking: ${t}`);return}let o=Date.now();if(e.target===this.lastClickTarget&&o-this.lastClickTime<m||(this.lastClickTarget=e.target,this.lastClickTime=o,this.shouldExclude(e.target)))return;let i=a(e.target);if(!i)return;let n=h(e,i.isFixed),u={session_id:this.sessionManager.getSessionId(),visitor_id:this.sessionManager.getVisitorId(),li2_cid:this.config.clickId,page_url:window.location.href,page_path:window.location.pathname,x:n.x,y:n.y,target_fixed:i.isFixed,viewport_width:window.innerWidth,viewport_height:window.innerHeight,page_height:n.pageHeight,scroll_y:n.scrollY,element_tag:i.tag,element_text:i.text,element_href:i.href,element_class:i.className,element_id:i.id,selector_path:i.selectorPath,interaction_type:"click",timestamp:o};this.sessionManager.touch(),this.batchSender.add(u)}shouldExclude(e){if(!this.config.excludeSelector||!e)return!1;let t=e;for(;t&&t!==document.body;){try{if(t.matches(this.config.excludeSelector))return!0}catch{return this.log(`Invalid excludeSelector: ${this.config.excludeSelector}`),this.config.excludeSelector=null,!1}t=t.parentElement}return!1}log(...e){this.config.debug&&console.log("[Li2 ClickTracker]",...e)}};export{d as ClickTracker,x as DEFAULT_CLICK_TRACKER_CONFIG};
@@ -35,6 +35,8 @@ interface PageviewConfig {
35
35
  cookiePath: string;
36
36
  /** Search query URL parameters to detect (default: ['q', 'query', 'search', 's']) */
37
37
  searchParams: string[];
38
+ /** Optional callback fired on every SPA route change (e.g. to reset scroll tracker) */
39
+ onRouteChange?: () => void;
38
40
  }
39
41
  /** A single pageview event to be sent to the server */
40
42
  interface PageviewEvent {
@@ -35,6 +35,8 @@ interface PageviewConfig {
35
35
  cookiePath: string;
36
36
  /** Search query URL parameters to detect (default: ['q', 'query', 'search', 's']) */
37
37
  searchParams: string[];
38
+ /** Optional callback fired on every SPA route change (e.g. to reset scroll tracker) */
39
+ onRouteChange?: () => void;
38
40
  }
39
41
  /** A single pageview event to be sent to the server */
40
42
  interface PageviewEvent {
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageviewTracker } from './index-DVbXHaIv.mjs';
2
- export { c as PageviewBatchPayload, a as PageviewConfig, b as PageviewEvent } from './index-DVbXHaIv.mjs';
1
+ import { P as PageviewTracker } from './index-BlPDBYpZ.mjs';
2
+ export { c as PageviewBatchPayload, a as PageviewConfig, b as PageviewEvent } from './index-BlPDBYpZ.mjs';
3
3
  export { AnalyticsSettings, AutoEvent, ConditionOperator, ConditionType, EventAction, EventActionType, EventTrigger, TriggerCondition, TriggerType } from './auto-events.mjs';
4
4
  export { ClickTrackerConfig } from './click-tracker/index.mjs';
5
5
  export { E as ElementInfo } from './element-resolver-BnZ_ItHT.mjs';
@@ -46,6 +46,10 @@ interface InteractionEvent {
46
46
  selector_path: string;
47
47
  /** Interaction type (click, scroll, etc.) */
48
48
  interaction_type: string;
49
+ /** Scroll-specific fields (only set when interaction_type = "scroll") */
50
+ scroll_depth_percent?: number;
51
+ scroll_direction?: string;
52
+ time_at_depth?: number;
49
53
  /** Unix timestamp in milliseconds */
50
54
  timestamp: number;
51
55
  }
@@ -212,6 +216,7 @@ declare class Li2Analytics {
212
216
  private cookieOptions;
213
217
  private autoEventTracker;
214
218
  private clickTracker;
219
+ private scrollTracker;
215
220
  pageview: PageviewTracker | null;
216
221
  constructor(config?: Li2Config);
217
222
  private log;
@@ -260,6 +265,23 @@ declare class Li2Analytics {
260
265
  cookieDomain?: string;
261
266
  cookiePath?: string;
262
267
  }): Promise<void>;
268
+ /**
269
+ * Initialize scroll tracking from data-attributes.
270
+ * @internal Called from auto-init block
271
+ */
272
+ initScrollTracking(scrollConfig: Record<string, string>): Promise<void>;
273
+ /**
274
+ * Enable scroll tracking programmatically (for users not using data-attributes)
275
+ */
276
+ enableScrollTracking(options?: {
277
+ milestones?: number[];
278
+ sessionTimeout?: number;
279
+ cookieLessMode?: boolean;
280
+ cookieDomain?: string;
281
+ cookiePath?: string;
282
+ }): Promise<void>;
283
+ /** Reset scroll tracker on SPA navigation (called by PageviewTracker) */
284
+ resetScrollTracker(): void;
263
285
  /**
264
286
  * Manually track a pageview (convenience method)
265
287
  */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PageviewTracker } from './index-DVbXHaIv.js';
2
- export { c as PageviewBatchPayload, a as PageviewConfig, b as PageviewEvent } from './index-DVbXHaIv.js';
1
+ import { P as PageviewTracker } from './index-BlPDBYpZ.js';
2
+ export { c as PageviewBatchPayload, a as PageviewConfig, b as PageviewEvent } from './index-BlPDBYpZ.js';
3
3
  export { AnalyticsSettings, AutoEvent, ConditionOperator, ConditionType, EventAction, EventActionType, EventTrigger, TriggerCondition, TriggerType } from './auto-events.js';
4
4
  export { ClickTrackerConfig } from './click-tracker/index.js';
5
5
  export { E as ElementInfo } from './element-resolver-BnZ_ItHT.js';
@@ -46,6 +46,10 @@ interface InteractionEvent {
46
46
  selector_path: string;
47
47
  /** Interaction type (click, scroll, etc.) */
48
48
  interaction_type: string;
49
+ /** Scroll-specific fields (only set when interaction_type = "scroll") */
50
+ scroll_depth_percent?: number;
51
+ scroll_direction?: string;
52
+ time_at_depth?: number;
49
53
  /** Unix timestamp in milliseconds */
50
54
  timestamp: number;
51
55
  }
@@ -212,6 +216,7 @@ declare class Li2Analytics {
212
216
  private cookieOptions;
213
217
  private autoEventTracker;
214
218
  private clickTracker;
219
+ private scrollTracker;
215
220
  pageview: PageviewTracker | null;
216
221
  constructor(config?: Li2Config);
217
222
  private log;
@@ -260,6 +265,23 @@ declare class Li2Analytics {
260
265
  cookieDomain?: string;
261
266
  cookiePath?: string;
262
267
  }): Promise<void>;
268
+ /**
269
+ * Initialize scroll tracking from data-attributes.
270
+ * @internal Called from auto-init block
271
+ */
272
+ initScrollTracking(scrollConfig: Record<string, string>): Promise<void>;
273
+ /**
274
+ * Enable scroll tracking programmatically (for users not using data-attributes)
275
+ */
276
+ enableScrollTracking(options?: {
277
+ milestones?: number[];
278
+ sessionTimeout?: number;
279
+ cookieLessMode?: boolean;
280
+ cookieDomain?: string;
281
+ cookiePath?: string;
282
+ }): Promise<void>;
283
+ /** Reset scroll tracker on SPA navigation (called by PageviewTracker) */
284
+ resetScrollTracker(): void;
263
285
  /**
264
286
  * Manually track a pageview (convenience method)
265
287
  */