@loamly/tracker 2.1.0 → 2.4.0

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.
@@ -1,4 +1,4 @@
1
- "use strict";var Loamly=(()=>{var ee=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var ke=Object.prototype.hasOwnProperty;var Se=(n,e)=>{for(var t in e)ee(n,t,{get:e[t],enumerable:!0})},Ie=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Ee(e))!ke.call(n,s)&&s!==t&&ee(n,s,{get:()=>e[s],enumerable:!(i=Te(e,s))||i.enumerable});return n};var Ce=n=>Ie(ee({},"__esModule",{value:!0}),n);var Ze={};Se(Ze,{default:()=>Je,loamly:()=>A});var T="2.1.0",l={apiHost:"https://app.loamly.ai",endpoints:{visit:"/api/ingest/visit",behavioral:"/api/ingest/behavioral",session:"/api/ingest/session",resolve:"/api/tracker/resolve",health:"/api/tracker/health",ping:"/api/tracker/ping"},pingInterval:3e4,batchSize:10,batchTimeout:5e3,sessionTimeout:18e5,maxTextLength:100,timeSpentThresholdMs:5e3},O={"chatgpt.com":"chatgpt","chat.openai.com":"chatgpt","claude.ai":"claude","perplexity.ai":"perplexity","bard.google.com":"bard","gemini.google.com":"gemini","copilot.microsoft.com":"copilot","github.com/copilot":"github-copilot","you.com":"you","phind.com":"phind","poe.com":"poe"};function le(){try{let n=performance.getEntriesByType("navigation");if(!n||n.length===0)return{nav_type:"unknown",confidence:0,signals:["no_timing_data"]};let e=n[0],t=[],i=0,s=e.fetchStart-e.startTime;s<5?(i+=.25,t.push("instant_fetch_start")):s<20&&(i+=.15,t.push("fast_fetch_start")),e.domainLookupEnd-e.domainLookupStart===0&&(i+=.15,t.push("no_dns_lookup")),e.connectEnd-e.connectStart===0&&(i+=.15,t.push("no_tcp_connect")),e.redirectCount===0&&(i+=.1,t.push("no_redirects")),Fe(e)<10&&(i+=.15,t.push("uniform_timing")),(!document.referrer||document.referrer==="")&&(i+=.1,t.push("no_referrer"));let m=Math.min(i,1);return{nav_type:i>=.5?"likely_paste":"likely_click",confidence:Math.round(m*1e3)/1e3,signals:t}}catch{return{nav_type:"unknown",confidence:0,signals:["detection_error"]}}}function Fe(n){let e=[n.fetchStart-n.startTime,n.domainLookupEnd-n.domainLookupStart,n.connectEnd-n.connectStart,n.responseStart-n.requestStart].filter(s=>s>=0);if(e.length===0)return 100;let t=e.reduce((s,r)=>s+r,0)/e.length,i=e.reduce((s,r)=>s+Math.pow(r-t,2),0)/e.length;return Math.sqrt(i)}function ce(n){if(!n)return null;try{let t=new URL(n).hostname.toLowerCase();for(let[i,s]of Object.entries(O))if(t.includes(i)||n.includes(i))return{isAI:!0,platform:s,confidence:.95,method:"referrer"};return null}catch{for(let[e,t]of Object.entries(O))if(n.toLowerCase().includes(e.toLowerCase()))return{isAI:!0,platform:t,confidence:.85,method:"referrer"};return null}}function ue(n){try{let t=new URL(n).searchParams.get("utm_source")?.toLowerCase();if(t){for(let[i,s]of Object.entries(O))if(t.includes(i.split(".")[0]))return{isAI:!0,platform:s,confidence:.99,method:"referrer"};if(t.includes("ai")||t.includes("llm")||t.includes("chatbot"))return{isAI:!0,platform:t,confidence:.9,method:"referrer"}}return null}catch{return null}}var de={human:{time_to_first_click_delayed:.85,time_to_first_click_normal:.75,time_to_first_click_fast:.5,time_to_first_click_immediate:.25,scroll_speed_variable:.8,scroll_speed_erratic:.7,scroll_speed_uniform:.35,scroll_speed_none:.45,nav_timing_click:.75,nav_timing_unknown:.55,nav_timing_paste:.35,has_referrer:.7,no_referrer:.45,homepage_landing:.65,deep_landing:.5,mouse_movement_curved:.9,mouse_movement_linear:.3,mouse_movement_none:.4,form_fill_normal:.85,form_fill_fast:.6,form_fill_instant:.2,focus_blur_normal:.75,focus_blur_rapid:.45},ai_influenced:{time_to_first_click_immediate:.75,time_to_first_click_fast:.55,time_to_first_click_normal:.4,time_to_first_click_delayed:.35,scroll_speed_none:.55,scroll_speed_uniform:.7,scroll_speed_variable:.35,scroll_speed_erratic:.4,nav_timing_paste:.75,nav_timing_unknown:.5,nav_timing_click:.35,no_referrer:.65,has_referrer:.4,deep_landing:.6,homepage_landing:.45,mouse_movement_none:.6,mouse_movement_linear:.75,mouse_movement_curved:.25,form_fill_instant:.8,form_fill_fast:.55,form_fill_normal:.3,focus_blur_rapid:.6,focus_blur_normal:.4}},me={human:.85,ai_influenced:.15},he=.5,q=class{constructor(e=1e4){this.classified=!1;this.result=null;this.onClassify=null;this.minSessionTime=e,this.data={firstClickTime:null,scrollEvents:[],mouseEvents:[],formEvents:[],focusBlurEvents:[],startTime:Date.now()}}setOnClassify(e){this.onClassify=e}recordClick(){this.data.firstClickTime===null&&(this.data.firstClickTime=Date.now()),this.checkAndClassify()}recordScroll(e){this.data.scrollEvents.push({time:Date.now(),position:e}),this.data.scrollEvents.length>50&&(this.data.scrollEvents=this.data.scrollEvents.slice(-50)),this.checkAndClassify()}recordMouse(e,t){this.data.mouseEvents.push({time:Date.now(),x:e,y:t}),this.data.mouseEvents.length>100&&(this.data.mouseEvents=this.data.mouseEvents.slice(-100)),this.checkAndClassify()}recordFormStart(e){this.data.formEvents.find(i=>i.fieldId===e&&i.endTime===0)||this.data.formEvents.push({fieldId:e,startTime:Date.now(),endTime:0})}recordFormEnd(e){let t=this.data.formEvents.find(i=>i.fieldId===e&&i.endTime===0);t&&(t.endTime=Date.now()),this.checkAndClassify()}recordFocusBlur(e){this.data.focusBlurEvents.push({type:e,time:Date.now()}),this.data.focusBlurEvents.length>20&&(this.data.focusBlurEvents=this.data.focusBlurEvents.slice(-20))}checkAndClassify(){this.classified||Date.now()-this.data.startTime<this.minSessionTime||!(this.data.scrollEvents.length>=2||this.data.mouseEvents.length>=5||this.data.firstClickTime!==null)||this.classify()}forceClassify(){return this.classified?this.result:this.classify()}classify(){let e=Date.now()-this.data.startTime,t=this.extractSignals(),i=Math.log(me.human),s=Math.log(me.ai_influenced);for(let F of t){let Z=de.human[F]??he,ae=de.ai_influenced[F]??he;i+=Math.log(Z),s+=Math.log(ae)}let r=Math.max(i,s),d=Math.exp(i-r),h=Math.exp(s-r),m=d+h,u=d/m,a=h/m,C,w;return u>.6?(C="human",w=u):a>.6?(C="ai_influenced",w=a):(C="uncertain",w=Math.max(u,a)),this.result={classification:C,humanProbability:u,aiProbability:a,confidence:w,signals:t,timestamp:Date.now(),sessionDurationMs:e},this.classified=!0,this.onClassify&&this.onClassify(this.result),this.result}extractSignals(){let e=[];if(this.data.firstClickTime!==null){let i=this.data.firstClickTime-this.data.startTime;i<500?e.push("time_to_first_click_immediate"):i<2e3?e.push("time_to_first_click_fast"):i<1e4?e.push("time_to_first_click_normal"):e.push("time_to_first_click_delayed")}if(this.data.scrollEvents.length===0)e.push("scroll_speed_none");else if(this.data.scrollEvents.length>=3){let i=[];for(let m=1;m<this.data.scrollEvents.length;m++){let u=this.data.scrollEvents[m].time-this.data.scrollEvents[m-1].time;i.push(u)}let s=i.reduce((m,u)=>m+u,0)/i.length,r=i.reduce((m,u)=>m+Math.pow(u-s,2),0)/i.length,d=Math.sqrt(r),h=s>0?d/s:0;h<.2?e.push("scroll_speed_uniform"):h<.6?e.push("scroll_speed_variable"):e.push("scroll_speed_erratic")}if(this.data.mouseEvents.length===0)e.push("mouse_movement_none");else if(this.data.mouseEvents.length>=10){let i=Math.min(this.data.mouseEvents.length,20),s=this.data.mouseEvents.slice(-i),r=0,d=0,h=0,m=0;for(let g of s)r+=g.x,d+=g.y,h+=g.x*g.y,m+=g.x*g.x;let u=i*m-r*r,a=u!==0?(i*h-r*d)/u:0,C=(d-a*r)/i,w=0,F=0,Z=d/i;for(let g of s){let we=a*g.x+C;w+=Math.pow(g.y-we,2),F+=Math.pow(g.y-Z,2)}(F!==0?1-w/F:0)>.95?e.push("mouse_movement_linear"):e.push("mouse_movement_curved")}let t=this.data.formEvents.filter(i=>i.endTime>0);if(t.length>0){let i=t.reduce((s,r)=>s+(r.endTime-r.startTime),0)/t.length;i<100?e.push("form_fill_instant"):i<500?e.push("form_fill_fast"):e.push("form_fill_normal")}if(this.data.focusBlurEvents.length>=4){let i=this.data.focusBlurEvents.slice(-10),s=[];for(let d=1;d<i.length;d++)s.push(i[d].time-i[d-1].time);s.reduce((d,h)=>d+h,0)/s.length<1e3?e.push("focus_blur_rapid"):e.push("focus_blur_normal")}return e}addContextSignal(e){}getResult(){return this.result}hasClassified(){return this.classified}};var U=class{constructor(){this.sequence=[];this.firstInteractionTime=null;this.analyzed=!1;this.result=null;this.pageLoadTime=performance.now()}initTracking(){document.addEventListener("focus",t=>{this.recordEvent("focus",t.target)},!0),document.addEventListener("blur",t=>{this.recordEvent("blur",t.target)},!0),window.addEventListener("focus",()=>{this.recordEvent("window_focus",null)}),window.addEventListener("blur",()=>{this.recordEvent("window_blur",null)});let e=()=>{this.firstInteractionTime===null&&(this.firstInteractionTime=performance.now())};document.addEventListener("click",e,{once:!0,passive:!0}),document.addEventListener("keydown",e,{once:!0,passive:!0})}recordEvent(e,t){let i={type:e,target:t?.tagName||"WINDOW",timestamp:performance.now()};this.sequence.push(i),this.sequence.length>20&&(this.sequence=this.sequence.slice(-20))}analyze(){if(this.analyzed&&this.result)return this.result;let e=[],t=0,i=this.sequence.filter(a=>a.timestamp<this.pageLoadTime+500);i.some(a=>a.type==="window_focus")&&(e.push("early_window_focus"),t+=.15),i.some(a=>a.type==="focus"&&a.target==="BODY")&&(e.push("early_body_focus"),t+=.15),this.sequence.some(a=>a.type==="focus"&&a.target==="A")||(e.push("no_link_focus"),t+=.1);let h=this.sequence.find(a=>a.type==="focus");h&&(h.target==="BODY"||h.target==="HTML")&&(e.push("first_focus_body"),t+=.1),this.sequence.filter(a=>a.type==="window_focus"||a.type==="window_blur").length<=2&&(e.push("minimal_window_switches"),t+=.05),this.firstInteractionTime!==null&&this.firstInteractionTime-this.pageLoadTime>3e3&&(e.push("delayed_first_interaction"),t+=.1),t=Math.min(t,.65);let u;return t>=.35?u="likely_paste":e.length===0?u="unknown":u="likely_click",this.result={nav_type:u,confidence:t,signals:e,sequence:this.sequence.slice(-10),time_to_first_interaction_ms:this.firstInteractionTime?Math.round(this.firstInteractionTime-this.pageLoadTime):null},this.analyzed=!0,this.result}getResult(){return this.analyze()}hasAnalyzed(){return this.analyzed}getSequence(){return[...this.sequence]}reset(){this.sequence=[],this.pageLoadTime=performance.now(),this.firstInteractionTime=null,this.analyzed=!1,this.result=null}};var te=class{constructor(){this.detected=!1;this.checkComplete=!1;this.observer=null}init(e=5e3){typeof document>"u"||(this.check(),!this.detected&&document.body&&(this.observer=new MutationObserver(()=>this.check()),this.observer.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>{this.observer&&!this.detected&&(this.observer.disconnect(),this.observer=null,this.checkComplete=!0)},e)))}check(){document.querySelector(".pplx-agent-overlay-stop-button")&&(this.detected=!0,this.checkComplete=!0,this.observer&&(this.observer.disconnect(),this.observer=null))}isDetected(){return this.detected}isCheckComplete(){return this.checkComplete}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null)}},ie=class{constructor(e=500){this.lastX=-1;this.lastY=-1;this.teleportingClicks=0;this.totalMovements=0;this.handleMove=e=>{this.totalMovements++,this.lastX=e.clientX,this.lastY=e.clientY};this.handleClick=e=>{if(this.lastX!==-1&&this.lastY!==-1){let t=Math.abs(e.clientX-this.lastX),i=Math.abs(e.clientY-this.lastY);(t>this.teleportThreshold||i>this.teleportThreshold)&&this.teleportingClicks++}this.lastX=e.clientX,this.lastY=e.clientY};this.teleportThreshold=e}init(){typeof document>"u"||(document.addEventListener("mousemove",this.handleMove,{passive:!0}),document.addEventListener("mousedown",this.handleClick,{passive:!0}))}getPatterns(){return{teleportingClicks:this.teleportingClicks,totalMovements:this.totalMovements}}destroy(){typeof document>"u"||(document.removeEventListener("mousemove",this.handleMove),document.removeEventListener("mousedown",this.handleClick))}},ne=class{constructor(){this.detected=!1}detect(){if(typeof navigator>"u")return!1;if(navigator.webdriver)return this.detected=!0,!0;if(typeof window<"u"){let e=window,t=["__webdriver_evaluate","__selenium_evaluate","__webdriver_script_function","__webdriver_script_func","__webdriver_script_fn","__fxdriver_evaluate","__driver_unwrapped","__webdriver_unwrapped","__driver_evaluate","__selenium_unwrapped","__fxdriver_unwrapped"];for(let i of t)if(i in e)return this.detected=!0,!0}return!1}isDetected(){return this.detected}},z=class{constructor(){this.initialized=!1;this.cometDetector=new te,this.mouseAnalyzer=new ie,this.cdpDetector=new ne}init(){this.initialized||(this.initialized=!0,this.cometDetector.init(),this.mouseAnalyzer.init(),this.cdpDetector.detect())}getResult(){let e=[],t=0;this.cometDetector.isDetected()&&(e.push("comet_dom_detected"),t=Math.max(t,.85)),this.cdpDetector.isDetected()&&(e.push("cdp_detected"),t=Math.max(t,.92));let i=this.mouseAnalyzer.getPatterns();return i.teleportingClicks>0&&(e.push(`teleporting_clicks:${i.teleportingClicks}`),t=Math.max(t,.78)),{cometDOMDetected:this.cometDetector.isDetected(),cdpDetected:this.cdpDetector.isDetected(),mousePatterns:i,agenticProbability:t,signals:e}}destroy(){this.cometDetector.destroy(),this.mouseAnalyzer.destroy()}};var De={batchSize:l.batchSize,batchTimeout:l.batchTimeout,maxRetries:3,retryDelayMs:1e3,storageKey:"_loamly_queue"},V=class{constructor(e,t={}){this.queue=[];this.batchTimer=null;this.isFlushing=!1;this.endpoint=e,this.config={...De,...t},this.loadFromStorage()}push(e,t){let i={id:this.generateId(),type:e,payload:t,timestamp:Date.now(),retries:0};this.queue.push(i),this.saveToStorage(),this.scheduleBatch()}async flush(){if(!(this.isFlushing||this.queue.length===0)){this.isFlushing=!0,this.clearBatchTimer();try{let e=[...this.queue];this.queue=[],await this.sendBatch(e)}finally{this.isFlushing=!1,this.saveToStorage()}}}flushBeacon(){if(this.queue.length===0)return!0;let e=this.queue.map(i=>({type:i.type,...i.payload,_queue_id:i.id,_queue_timestamp:i.timestamp})),t=navigator.sendBeacon?.(this.endpoint,JSON.stringify({events:e,beacon:!0}))??!1;return t&&(this.queue=[],this.clearStorage()),t}get length(){return this.queue.length}scheduleBatch(){if(!this.batchTimer){if(this.queue.length>=this.config.batchSize){this.flush();return}this.batchTimer=setTimeout(()=>{this.batchTimer=null,this.flush()},this.config.batchTimeout)}}clearBatchTimer(){this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null)}async sendBatch(e){if(e.length===0)return;let t={events:e.map(i=>({type:i.type,...i.payload,_queue_id:i.id,_queue_timestamp:i.timestamp})),batch:!0};try{let i=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!i.ok)throw new Error(`HTTP ${i.status}`)}catch{for(let s of e)s.retries<this.config.maxRetries&&(s.retries++,this.queue.push(s));if(this.queue.length>0){let s=this.config.retryDelayMs*Math.pow(2,e[0].retries-1);setTimeout(()=>this.flush(),s)}}}loadFromStorage(){try{let e=localStorage.getItem(this.config.storageKey);if(e){let t=JSON.parse(e);if(Array.isArray(t)){let i=Date.now()-864e5;this.queue=t.filter(s=>s.timestamp>i)}}}catch{}}saveToStorage(){try{this.queue.length>0?localStorage.setItem(this.config.storageKey,JSON.stringify(this.queue)):this.clearStorage()}catch{}}clearStorage(){try{localStorage.removeItem(this.config.storageKey)}catch{}}generateId(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}};var Y=class{constructor(e,t,i,s={}){this.intervalId=null;this.isVisible=!0;this.currentScrollDepth=0;this.ping=async()=>{let e=this.getData();if(this.config.onPing?.(e),this.config.endpoint)try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}catch{}};this.handleVisibilityChange=()=>{this.isVisible=document.visibilityState==="visible"};this.handleScroll=()=>{let e=Math.round((window.scrollY+window.innerHeight)/document.documentElement.scrollHeight*100);e>this.currentScrollDepth&&(this.currentScrollDepth=Math.min(e,100))};this.sessionId=e,this.visitorId=t,this.version=i,this.pageLoadTime=Date.now(),this.config={interval:l.pingInterval,endpoint:"",...s},document.addEventListener("visibilitychange",this.handleVisibilityChange),window.addEventListener("scroll",this.handleScroll,{passive:!0})}start(){this.intervalId||(this.intervalId=setInterval(()=>{this.isVisible&&this.ping()},this.config.interval),this.ping())}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),document.removeEventListener("visibilitychange",this.handleVisibilityChange),window.removeEventListener("scroll",this.handleScroll)}updateScrollDepth(e){e>this.currentScrollDepth&&(this.currentScrollDepth=e)}getData(){return{session_id:this.sessionId,visitor_id:this.visitorId,url:window.location.href,time_on_page_ms:Date.now()-this.pageLoadTime,scroll_depth:this.currentScrollDepth,is_active:this.isVisible,tracker_version:this.version}}};var Le=[30,60,90,100],B=class{constructor(e={}){this.maxDepth=0;this.reportedChunks=new Set;this.ticking=!1;this.isVisible=!0;this.handleScroll=()=>{!this.ticking&&this.isVisible&&(requestAnimationFrame(()=>{this.checkScrollDepth(),this.ticking=!1}),this.ticking=!0)};this.handleVisibility=()=>{this.isVisible=document.visibilityState==="visible"};this.config={chunks:Le,...e},this.startTime=Date.now()}start(){window.addEventListener("scroll",this.handleScroll,{passive:!0}),document.addEventListener("visibilitychange",this.handleVisibility),this.checkScrollDepth()}stop(){window.removeEventListener("scroll",this.handleScroll),document.removeEventListener("visibilitychange",this.handleVisibility)}getMaxDepth(){return this.maxDepth}getReportedChunks(){return Array.from(this.reportedChunks).sort((e,t)=>e-t)}getFinalEvent(){let e=document.documentElement.scrollHeight,t=window.innerHeight;return{depth:this.maxDepth,chunk:this.getChunkForDepth(this.maxDepth),time_to_reach_ms:Date.now()-this.startTime,total_height:e,viewport_height:t}}checkScrollDepth(){let e=window.scrollY,t=window.innerHeight,i=document.documentElement.scrollHeight;if(i<=t){this.updateDepth(100);return}let s=i-t,r=Math.min(100,Math.round(e/s*100));this.updateDepth(r)}updateDepth(e){if(!(e<=this.maxDepth)){this.maxDepth=e,this.config.onDepthChange?.(e);for(let t of this.config.chunks)e>=t&&!this.reportedChunks.has(t)&&(this.reportedChunks.add(t),this.reportChunk(t))}}reportChunk(e){let t=document.documentElement.scrollHeight,i=window.innerHeight,s={depth:this.maxDepth,chunk:e,time_to_reach_ms:Date.now()-this.startTime,total_height:t,viewport_height:i};this.config.onChunkReached?.(s)}getChunkForDepth(e){let t=this.config.chunks.sort((i,s)=>s-i);for(let i of t)if(e>=i)return i;return 0}};var xe={idleThresholdMs:3e4,updateIntervalMs:5e3},j=class{constructor(e={}){this.activeTime=0;this.idleTime=0;this.isVisible=!0;this.isIdle=!1;this.updateInterval=null;this.idleCheckInterval=null;this.handleVisibility=()=>{let e=this.isVisible;this.isVisible=document.visibilityState==="visible",e&&!this.isVisible?this.updateTimes():!e&&this.isVisible&&(this.lastUpdateTime=Date.now(),this.lastActivityTime=Date.now())};this.handleActivity=()=>{let e=Date.now();this.isIdle&&(this.isIdle=!1),this.lastActivityTime=e};this.config={...xe,...e},this.startTime=Date.now(),this.lastActivityTime=this.startTime,this.lastUpdateTime=this.startTime}start(){document.addEventListener("visibilitychange",this.handleVisibility),["mousemove","keydown","scroll","click","touchstart"].forEach(t=>{document.addEventListener(t,this.handleActivity,{passive:!0})}),this.updateInterval=setInterval(()=>{this.update()},this.config.updateIntervalMs),this.idleCheckInterval=setInterval(()=>{this.checkIdle()},1e3)}stop(){document.removeEventListener("visibilitychange",this.handleVisibility),["mousemove","keydown","scroll","click","touchstart"].forEach(t=>{document.removeEventListener(t,this.handleActivity)}),this.updateInterval&&(clearInterval(this.updateInterval),this.updateInterval=null),this.idleCheckInterval&&(clearInterval(this.idleCheckInterval),this.idleCheckInterval=null)}getMetrics(){return this.updateTimes(),{active_time_ms:this.activeTime,total_time_ms:Date.now()-this.startTime,idle_time_ms:this.idleTime,is_engaged:!this.isIdle&&this.isVisible}}getFinalMetrics(){return this.updateTimes(),this.getMetrics()}checkIdle(){let t=Date.now()-this.lastActivityTime;!this.isIdle&&t>=this.config.idleThresholdMs&&(this.isIdle=!0)}updateTimes(){let e=Date.now(),t=e-this.lastUpdateTime;this.isVisible&&(this.isIdle?this.idleTime+=t:this.activeTime+=t),this.lastUpdateTime=e}update(){this.isVisible&&(this.updateTimes(),this.config.onUpdate?.(this.getMetrics()))}};var fe={sensitiveFields:["password","pwd","pass","credit","card","cvv","cvc","ssn","social","secret","token","key"],trackableFields:["email","name","phone","company","first","last","city","country"],thankYouPatterns:[/thank[-_]?you/i,/success/i,/confirmation/i,/submitted/i,/complete/i]},G=class{constructor(e={}){this.formStartTimes=new Map;this.interactedForms=new Set;this.mutationObserver=null;this.handleFocusIn=e=>{let t=e.target;if(!this.isFormField(t))return;let i=t.closest("form"),s=this.getFormId(i||t);this.formStartTimes.has(s)||(this.formStartTimes.set(s,Date.now()),this.interactedForms.add(s),this.emitEvent({event_type:"form_start",form_id:s,form_type:this.detectFormType(i||t)}));let r=this.getFieldName(t);r&&!this.isSensitiveField(r)&&this.emitEvent({event_type:"form_field",form_id:s,form_type:this.detectFormType(i||t),field_name:this.sanitizeFieldName(r),field_type:t.type||t.tagName.toLowerCase()})};this.handleSubmit=e=>{let t=e.target;if(!t||t.tagName!=="FORM")return;let i=this.getFormId(t),s=this.formStartTimes.get(i);this.emitEvent({event_type:"form_submit",form_id:i,form_type:this.detectFormType(t),time_to_submit_ms:s?Date.now()-s:void 0,is_conversion:!0})};this.handleClick=e=>{let t=e.target;if(t.closest(".hs-button")||t.closest('[type="submit"]')){let i=t.closest("form");if(i&&i.classList.contains("hs-form")){let s=this.getFormId(i),r=this.formStartTimes.get(s);this.emitEvent({event_type:"form_submit",form_id:s,form_type:"hubspot",time_to_submit_ms:r?Date.now()-r:void 0,is_conversion:!0})}}t.closest('[data-qa="submit-button"]')&&this.emitEvent({event_type:"form_submit",form_id:"typeform_embed",form_type:"typeform",is_conversion:!0})};this.config={...fe,...e,sensitiveFields:[...fe.sensitiveFields,...e.sensitiveFields||[]]}}start(){document.addEventListener("focusin",this.handleFocusIn,{passive:!0}),document.addEventListener("submit",this.handleSubmit),document.addEventListener("click",this.handleClick,{passive:!0}),this.startMutationObserver(),this.checkThankYouPage(),this.scanForEmbeddedForms()}stop(){document.removeEventListener("focusin",this.handleFocusIn),document.removeEventListener("submit",this.handleSubmit),document.removeEventListener("click",this.handleClick),this.mutationObserver?.disconnect()}getInteractedForms(){return Array.from(this.interactedForms)}startMutationObserver(){this.mutationObserver=new MutationObserver(e=>{for(let t of e)for(let i of t.addedNodes)i instanceof HTMLElement&&((i.classList?.contains("hs-form")||i.querySelector?.(".hs-form"))&&this.trackEmbeddedForm(i,"hubspot"),(i.classList?.contains("typeform-widget")||i.querySelector?.("[data-tf-widget]"))&&this.trackEmbeddedForm(i,"typeform"),(i.classList?.contains("jotform-form")||i.querySelector?.(".jotform-form"))&&this.trackEmbeddedForm(i,"jotform"),(i.classList?.contains("gform_wrapper")||i.querySelector?.(".gform_wrapper"))&&this.trackEmbeddedForm(i,"gravity"))}),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0})}scanForEmbeddedForms(){document.querySelectorAll(".hs-form").forEach(e=>{this.trackEmbeddedForm(e,"hubspot")}),document.querySelectorAll("[data-tf-widget], .typeform-widget").forEach(e=>{this.trackEmbeddedForm(e,"typeform")}),document.querySelectorAll(".jotform-form").forEach(e=>{this.trackEmbeddedForm(e,"jotform")}),document.querySelectorAll(".gform_wrapper").forEach(e=>{this.trackEmbeddedForm(e,"gravity")})}trackEmbeddedForm(e,t){let i=`${t}_${this.getFormId(e)}`;e.addEventListener("focusin",()=>{this.formStartTimes.has(i)||(this.formStartTimes.set(i,Date.now()),this.interactedForms.add(i),this.emitEvent({event_type:"form_start",form_id:i,form_type:t}))},{passive:!0})}checkThankYouPage(){let e=window.location.href.toLowerCase(),t=document.title.toLowerCase();for(let i of this.config.thankYouPatterns)if(i.test(e)||i.test(t)){this.emitEvent({event_type:"form_success",form_id:"page_conversion",form_type:"unknown",is_conversion:!0});break}}isFormField(e){let t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}getFormId(e){return e?e.id||e.getAttribute("name")||e.getAttribute("data-form-id")||"form_"+Math.random().toString(36).substring(2,8):"unknown"}getFieldName(e){return e.name||e.id||e.getAttribute("data-name")||""}isSensitiveField(e){let t=e.toLowerCase();return this.config.sensitiveFields.some(i=>t.includes(i))}sanitizeFieldName(e){return e.replace(/[0-9]+/g,"*").substring(0,50)}detectFormType(e){return e.classList.contains("hs-form")||e.closest(".hs-form")?"hubspot":e.classList.contains("typeform-widget")||e.closest("[data-tf-widget]")?"typeform":e.classList.contains("jotform-form")||e.closest(".jotform-form")?"jotform":e.classList.contains("gform_wrapper")||e.closest(".gform_wrapper")?"gravity":e.tagName==="FORM"?"native":"unknown"}emitEvent(e){this.config.onFormEvent?.(e)}};var R=class{constructor(e={}){this.originalPushState=null;this.originalReplaceState=null;this.handleStateChange=e=>{let t=window.location.href;t!==this.currentUrl&&this.emitNavigation(t,e)};this.handlePopState=()=>{let e=window.location.href;e!==this.currentUrl&&this.emitNavigation(e,"pop")};this.handleHashChange=()=>{let e=window.location.href;e!==this.currentUrl&&this.emitNavigation(e,"hash")};this.config=e,this.currentUrl=window.location.href,this.pageEnterTime=Date.now()}start(){this.patchHistoryAPI(),window.addEventListener("popstate",this.handlePopState),this.config.ignoreHashChange||window.addEventListener("hashchange",this.handleHashChange)}stop(){this.originalPushState&&(history.pushState=this.originalPushState),this.originalReplaceState&&(history.replaceState=this.originalReplaceState),window.removeEventListener("popstate",this.handlePopState),window.removeEventListener("hashchange",this.handleHashChange)}navigate(e,t="push"){this.emitNavigation(e,t)}getCurrentUrl(){return this.currentUrl}getTimeOnPage(){return Date.now()-this.pageEnterTime}patchHistoryAPI(){this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...e)=>{let t=this.originalPushState(...e);return this.handleStateChange("push"),t},history.replaceState=(...e)=>{let t=this.originalReplaceState(...e);return this.handleStateChange("replace"),t}}emitNavigation(e,t){let i={from_url:this.currentUrl,to_url:e,navigation_type:t,time_on_previous_page_ms:Date.now()-this.pageEnterTime};this.currentUrl=e,this.pageEnterTime=Date.now(),this.config.onNavigate?.(i)}};function Q(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{let e=Math.random()*16|0;return(n==="x"?e:e&3|8).toString(16)})}function pe(){try{let n=localStorage.getItem("_loamly_vid");if(n)return n;let e=Q();return localStorage.setItem("_loamly_vid",e),e}catch{return Q()}}function ve(){try{let n=sessionStorage.getItem("loamly_session"),e=sessionStorage.getItem("loamly_start");if(n&&e)return{sessionId:n,isNew:!1};let t=Q(),i=Date.now().toString();return sessionStorage.setItem("loamly_session",t),sessionStorage.setItem("loamly_start",i),{sessionId:t,isNew:!0}}catch{return{sessionId:Q(),isNew:!0}}}function X(n){let e={};try{let t=new URL(n).searchParams,i=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"];for(let s of i){let r=t.get(s);r&&(e[s]=r)}}catch{}return e}function se(n,e){return n.length<=e?n:n.substring(0,e-3)+"..."}async function P(n,e,t=1e4){try{let i=new AbortController,s=setTimeout(()=>i.abort(),t),r=await fetch(n,{...e,signal:i.signal});return clearTimeout(s),r}catch{return null}}function K(n,e){return typeof navigator<"u"&&navigator.sendBeacon?navigator.sendBeacon(n,JSON.stringify(e)):!1}var N={apiHost:l.apiHost},E=!1,re=!1,p=null,v=null,L=null,f=null,c=null,oe=null,D=null,W=null,k=null,S=null,x=null,_=null,M=null,H=null,I=null;function o(...n){re&&console.log("[Loamly]",...n)}function y(n){return`${N.apiHost}${n}`}function Me(n={}){if(E){o("Already initialized");return}N={...N,...n,apiHost:n.apiHost||l.apiHost},re=n.debug??!1;let e={scroll:!0,time:!0,forms:!0,spa:!0,behavioralML:!0,focusBlur:!0,agentic:!0,eventQueue:!0,ping:!1,...n.features};o("Initializing Loamly Tracker v"+T),o("Features:",e),p=pe(),o("Visitor ID:",p);let t=ve();v=t.sessionId,o("Session ID:",v,t.isNew?"(new)":"(existing)"),e.eventQueue&&(S=new V(y(l.endpoints.behavioral),{batchSize:l.batchSize,batchTimeout:l.batchTimeout})),L=le(),o("Navigation timing:",L),f=ce(document.referrer)||ue(window.location.href),f&&o("AI detected:",f),E=!0,n.disableAutoPageview||$(),n.disableBehavioral||Ae(e),e.behavioralML&&(c=new q(1e4),c.setOnClassify(_e),He()),e.focusBlur&&(D=new U,D.initTracking(),setTimeout(()=>{D&&Oe(D.analyze())},5e3)),e.agentic&&(k=new z,k.init()),e.ping&&p&&v&&(x=new Y(v,p,T,{interval:l.pingInterval,endpoint:y(l.endpoints.ping)}),x.start()),I=new R({onNavigate:Be}),I.start(),Re(),ye("initialized"),o("Initialization complete")}function Ae(n){n.scroll&&(_=new B({chunks:[30,60,90,100],onChunkReached:e=>{o("Scroll chunk:",e.chunk),b("scroll_depth",{depth:e.depth,chunk:e.chunk,time_to_reach_ms:e.time_to_reach_ms})}}),_.start()),n.time&&(M=new j({updateIntervalMs:1e4,onUpdate:e=>{e.active_time_ms>=l.timeSpentThresholdMs&&b("time_spent",{active_time_ms:e.active_time_ms,total_time_ms:e.total_time_ms,idle_time_ms:e.idle_time_ms,is_engaged:e.is_engaged})}}),M.start()),n.forms&&(H=new G({onFormEvent:e=>{o("Form event:",e.event_type,e.form_id),b(e.event_type,{form_id:e.form_id,form_type:e.form_type,field_name:e.field_name,field_type:e.field_type,time_to_submit_ms:e.time_to_submit_ms,is_conversion:e.is_conversion})}}),H.start()),n.spa&&(I=new R({onNavigate:e=>{o("SPA navigation:",e.navigation_type),$(e.to_url)}}),I.start()),document.addEventListener("click",e=>{let i=e.target.closest("a");if(i&&i.href){let s=i.hostname!==window.location.hostname;b("click",{element:"link",href:se(i.href,200),text:se(i.textContent||"",100),is_external:s})}})}function b(n,e){S&&S.push(n,{visitor_id:p,session_id:v,event_type:n,...e,url:window.location.href,timestamp:new Date().toISOString(),tracker_version:T})}function Be(n){o("SPA navigation:",n.navigation_type,n.to_url),S?.flush(),x?.updateScrollDepth(0),_?.stop(),_=new B({chunks:[30,60,90,100],onChunkReached:e=>{b("scroll_depth",{depth:e.depth,chunk:e.chunk,time_to_reach_ms:e.time_to_reach_ms})}}),_.start(),$(n.to_url),b("spa_navigation",{from_url:n.from_url,to_url:n.to_url,navigation_type:n.navigation_type,time_on_previous_page_ms:n.time_on_previous_page_ms})}function Re(){let n=()=>{let e=_?.getFinalEvent();e&&K(y(l.endpoints.behavioral),{visitor_id:p,session_id:v,event_type:"scroll_depth_final",data:e,url:window.location.href});let t=M?.getFinalMetrics();t&&K(y(l.endpoints.behavioral),{visitor_id:p,session_id:v,event_type:"time_spent_final",data:t,url:window.location.href});let i=k?.getResult();if(i&&i.agenticProbability>0&&K(y(l.endpoints.behavioral),{visitor_id:p,session_id:v,event_type:"agentic_detection",data:i,url:window.location.href}),S?.flushBeacon(),c&&!c.hasClassified()){let s=c.forceClassify();s&&_e(s)}};window.addEventListener("beforeunload",n),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&n()})}function $(n){if(!E){o("Not initialized, call init() first");return}let e=n||window.location.href,t={visitor_id:p,session_id:v,url:e,referrer:document.referrer||null,title:document.title||null,utm_source:X(e).utm_source||null,utm_medium:X(e).utm_medium||null,utm_campaign:X(e).utm_campaign||null,user_agent:navigator.userAgent,screen_width:window.screen?.width,screen_height:window.screen?.height,language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,tracker_version:T,navigation_timing:L,ai_platform:f?.platform||null,is_ai_referrer:f?.isAI||!1};o("Pageview:",t),P(y(l.endpoints.visit),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function ge(n,e={}){if(!E){o("Not initialized, call init() first");return}let t={visitor_id:p,session_id:v,event_name:n,event_type:"custom",properties:e.properties||{},revenue:e.revenue,currency:e.currency||"USD",url:window.location.href,timestamp:new Date().toISOString(),tracker_version:T};o("Event:",n,t),P(y("/api/ingest/event"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function Pe(n,e,t="USD"){ge(n,{revenue:e,currency:t,properties:{type:"conversion"}})}function Ne(n,e={}){if(!E){o("Not initialized, call init() first");return}o("Identify:",n,e);let t={visitor_id:p,session_id:v,user_id:n,traits:e,timestamp:new Date().toISOString()};P(y("/api/ingest/identify"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}function He(){if(!c)return;let n=0;document.addEventListener("mousemove",t=>{n++,n%10===0&&c&&c.recordMouse(t.clientX,t.clientY)},{passive:!0}),document.addEventListener("click",()=>{c&&c.recordClick()},{passive:!0});let e=0;document.addEventListener("scroll",()=>{let t=window.scrollY;Math.abs(t-e)>50&&c&&(e=t,c.recordScroll(t))},{passive:!0}),document.addEventListener("focusin",t=>{if(c){c.recordFocusBlur("focus");let i=t.target;(i.tagName==="INPUT"||i.tagName==="TEXTAREA")&&c.recordFormStart(i.id||i.getAttribute("name")||"unknown")}},{passive:!0}),document.addEventListener("focusout",t=>{if(c){c.recordFocusBlur("blur");let i=t.target;(i.tagName==="INPUT"||i.tagName==="TEXTAREA")&&c.recordFormEnd(i.id||i.getAttribute("name")||"unknown")}},{passive:!0}),setTimeout(()=>{c&&!c.hasClassified()&&c.forceClassify()},3e4)}function _e(n){o("Behavioral ML classification:",n),oe={classification:n.classification,humanProbability:n.humanProbability,aiProbability:n.aiProbability,confidence:n.confidence,signals:n.signals,sessionDurationMs:n.sessionDurationMs},b("ml_classification",{classification:n.classification,human_probability:n.humanProbability,ai_probability:n.aiProbability,confidence:n.confidence,signals:n.signals,session_duration_ms:n.sessionDurationMs,navigation_timing:L,ai_detection:f,focus_blur:W}),n.classification==="ai_influenced"&&n.confidence>=.7&&(f={isAI:!0,confidence:n.confidence,method:"behavioral"},o("AI detection updated from behavioral ML:",f))}function Oe(n){o("Focus/blur analysis:",n),W={navType:n.nav_type,confidence:n.confidence,signals:n.signals,timeToFirstInteractionMs:n.time_to_first_interaction_ms},b("focus_blur_analysis",{nav_type:n.nav_type,confidence:n.confidence,signals:n.signals,time_to_first_interaction_ms:n.time_to_first_interaction_ms,sequence_length:n.sequence.length}),n.nav_type==="likely_paste"&&n.confidence>=.4&&(!f||f.confidence<n.confidence)&&(f={isAI:!0,confidence:n.confidence,method:"behavioral"},o("AI detection updated from focus/blur analysis:",f))}function qe(){return v}function Ue(){return p}function ze(){return f}function Ve(){return L}function Ye(){return oe}function je(){return W}function Ge(){return k?.getResult()||null}function Qe(){return E}function ye(n,e){if(N.apiKey)try{let t={workspace_id:N.apiKey,status:n,error_message:e||null,version:T,url:typeof window<"u"?window.location.href:null,user_agent:typeof navigator<"u"?navigator.userAgent:null,timestamp:new Date().toISOString(),features:{scroll_tracker:!!_,time_tracker:!!M,form_tracker:!!H,spa_router:!!I,behavioral_ml:!!c,focus_blur:!!D,agentic:!!k,ping_service:!!x,event_queue:!!S}};P(y(l.endpoints.health),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}).catch(()=>{}),o("Health reported:",n)}catch{}}function Xe(){o("Resetting tracker"),x?.stop(),_?.stop(),M?.stop(),H?.stop(),I?.stop(),k?.destroy(),E=!1,p=null,v=null,L=null,f=null,c=null,oe=null,D=null,W=null,k=null,S=null,x=null,_=null,M=null,H=null,I=null;try{sessionStorage.removeItem("loamly_session"),sessionStorage.removeItem("loamly_start")}catch{}}function Ke(n){re=n,o("Debug mode:",n?"enabled":"disabled")}var A={init:Me,pageview:$,track:ge,conversion:Pe,identify:Ne,getSessionId:qe,getVisitorId:Ue,getAIDetection:ze,getNavigationTiming:Ve,getBehavioralML:Ye,getFocusBlur:je,getAgentic:Ge,isInitialized:Qe,reset:Xe,debug:Ke,reportHealth:ye};function We(){let n=document.getElementsByTagName("script");for(let e of n){let t=e.src;if(t.includes("t.js")||t.includes("loamly"))try{let s=new URL(t).searchParams.get("d");if(s)return s}catch{}}return null}async function be(n){try{let e=await fetch(`${l.apiHost}${l.endpoints.resolve}?domain=${encodeURIComponent(n)}`);if(!e.ok)return console.warn("[Loamly] Failed to resolve workspace for domain:",n),null;let t=await e.json();return t.workspace_id?{apiKey:t.workspace_api_key,apiHost:l.apiHost}:null}catch(e){return console.warn("[Loamly] Error resolving workspace:",e),null}}function $e(){let n=document.getElementsByTagName("script");for(let e of n)if(e.src.includes("loamly")||e.dataset.loamly!==void 0){let t={};if(e.dataset.apiKey&&(t.apiKey=e.dataset.apiKey),e.dataset.apiHost&&(t.apiHost=e.dataset.apiHost),e.dataset.debug==="true"&&(t.debug=!0),e.dataset.disableAutoPageview==="true"&&(t.disableAutoPageview=!0),e.dataset.disableBehavioral==="true"&&(t.disableBehavioral=!0),t.apiKey)return t}return null}async function J(){let n=We();if(n){let i=await be(n);if(i){A.init(i);return}}let e=$e();if(e){A.init(e);return}let t=window.location.hostname;if(t&&t!=="localhost"){let i=await be(t);if(i){A.init(i);return}}}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{typeof requestIdleCallback<"u"?requestIdleCallback(()=>J()):setTimeout(J,0)}):typeof requestIdleCallback<"u"?requestIdleCallback(()=>J()):setTimeout(J,0));var Je=A;return Ce(Ze);})();
1
+ "use strict";var Loamly=(()=>{var te=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var De=Object.getOwnPropertyNames;var Le=Object.prototype.hasOwnProperty;var Ce=(n,e)=>{for(var t in e)te(n,t,{get:e[t],enumerable:!0})},Me=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of De(e))!Le.call(n,s)&&s!==t&&te(n,s,{get:()=>e[s],enumerable:!(i=Fe(e,s))||i.enumerable});return n};var xe=n=>Me(te({},"__esModule",{value:!0}),n);var lt={};Ce(lt,{default:()=>at,loamly:()=>L});var de={sensitiveFields:["password","pwd","pass","credit","card","cvv","cvc","ssn","social","secret","token","key","pin","security","answer"],trackableFields:["email","name","phone","company","first","last","city","country","domain","website","url","organization"],thankYouPatterns:[/thank[-_]?you/i,/success/i,/confirmation/i,/submitted/i,/complete/i],captureFieldValues:!0,maxFieldValueLength:200},z=class{constructor(e={}){this.formStartTimes=new Map;this.interactedForms=new Set;this.mutationObserver=null;this.handleFocusIn=e=>{let t=e.target;if(!this.isFormField(t))return;let i=t.closest("form"),s=this.getFormId(i||t);this.formStartTimes.has(s)||(this.formStartTimes.set(s,Date.now()),this.interactedForms.add(s),this.emitEvent({event_type:"form_start",form_id:s,form_type:this.detectFormType(i||t)}));let r=this.getFieldName(t);r&&!this.isSensitiveField(r)&&this.emitEvent({event_type:"form_field",form_id:s,form_type:this.detectFormType(i||t),field_name:this.sanitizeFieldName(r),field_type:t.type||t.tagName.toLowerCase()})};this.handleSubmit=e=>{let t=e.target;if(!t||t.tagName!=="FORM")return;let i=this.getFormId(t),s=this.formStartTimes.get(i),{fields:r,emailSubmitted:o}=this.captureFormFields(t);this.emitEvent({event_type:"form_submit",form_id:i,form_type:this.detectFormType(t),time_to_submit_ms:s?Date.now()-s:void 0,is_conversion:!0,submit_source:"submit",fields:r.length>0?r:void 0,email_submitted:o})};this.handleClick=e=>{let t=e.target;if(t.closest(".hs-button")||t.closest('[type="submit"]')){let i=t.closest("form");if(i&&i.classList.contains("hs-form")){let s=this.getFormId(i),r=this.formStartTimes.get(s),{fields:o,emailSubmitted:h}=this.captureFormFields(i);this.emitEvent({event_type:"form_submit",form_id:s,form_type:"hubspot",time_to_submit_ms:r?Date.now()-r:void 0,is_conversion:!0,submit_source:"click",fields:o.length>0?o:void 0,email_submitted:h})}}t.closest('[data-qa="submit-button"]')&&this.emitEvent({event_type:"form_submit",form_id:"typeform_embed",form_type:"typeform",is_conversion:!0,submit_source:"click"})};this.config={...de,...e,sensitiveFields:[...de.sensitiveFields,...e.sensitiveFields||[]]}}start(){document.addEventListener("focusin",this.handleFocusIn,{passive:!0}),document.addEventListener("submit",this.handleSubmit),document.addEventListener("click",this.handleClick,{passive:!0}),this.startMutationObserver(),this.checkThankYouPage(),this.scanForEmbeddedForms()}stop(){document.removeEventListener("focusin",this.handleFocusIn),document.removeEventListener("submit",this.handleSubmit),document.removeEventListener("click",this.handleClick),this.mutationObserver?.disconnect()}getInteractedForms(){return Array.from(this.interactedForms)}captureFormFields(e){let t=[],i;if(!this.config.captureFieldValues)return{fields:t,emailSubmitted:i};try{let s=new FormData(e);for(let[r,o]of s.entries()){if(this.isSensitiveField(r))continue;let f=e.elements.namedItem(r)?.type||"text";if(f==="file"||o instanceof File)continue;let l=String(o);this.isEmailField(r,l)&&(i=l.substring(0,254));let c=l.length>this.config.maxFieldValueLength?l.substring(0,this.config.maxFieldValueLength)+"...":l;t.push({name:this.sanitizeFieldName(r),type:f,value:c})}}catch(s){console.warn("[Loamly] Failed to capture form fields:",s)}return{fields:t,emailSubmitted:i}}isEmailField(e,t){let i=e.toLowerCase(),s=i.includes("email")||i==="e-mail",r=/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);return s&&r}startMutationObserver(){this.mutationObserver=new MutationObserver(e=>{for(let t of e)for(let i of t.addedNodes)i instanceof HTMLElement&&((i.classList?.contains("hs-form")||i.querySelector?.(".hs-form"))&&this.trackEmbeddedForm(i,"hubspot"),(i.classList?.contains("typeform-widget")||i.querySelector?.("[data-tf-widget]"))&&this.trackEmbeddedForm(i,"typeform"),(i.classList?.contains("jotform-form")||i.querySelector?.(".jotform-form"))&&this.trackEmbeddedForm(i,"jotform"),(i.classList?.contains("gform_wrapper")||i.querySelector?.(".gform_wrapper"))&&this.trackEmbeddedForm(i,"gravity"))}),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0})}scanForEmbeddedForms(){document.querySelectorAll(".hs-form").forEach(e=>{this.trackEmbeddedForm(e,"hubspot")}),document.querySelectorAll("[data-tf-widget], .typeform-widget").forEach(e=>{this.trackEmbeddedForm(e,"typeform")}),document.querySelectorAll(".jotform-form").forEach(e=>{this.trackEmbeddedForm(e,"jotform")}),document.querySelectorAll(".gform_wrapper").forEach(e=>{this.trackEmbeddedForm(e,"gravity")})}trackEmbeddedForm(e,t){let i=`${t}_${this.getFormId(e)}`;e.addEventListener("focusin",()=>{this.formStartTimes.has(i)||(this.formStartTimes.set(i,Date.now()),this.interactedForms.add(i),this.emitEvent({event_type:"form_start",form_id:i,form_type:t}))},{passive:!0})}checkThankYouPage(){let e=window.location.href.toLowerCase(),t=document.title.toLowerCase();for(let i of this.config.thankYouPatterns)if(i.test(e)||i.test(t)){this.emitEvent({event_type:"form_success",form_id:"page_conversion",form_type:"unknown",is_conversion:!0,submit_source:"thank_you"});break}}isFormField(e){let t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}getFormId(e){return e?e.id||e.getAttribute("name")||e.getAttribute("data-form-id")||"form_"+Math.random().toString(36).substring(2,8):"unknown"}getFieldName(e){return e.name||e.id||e.getAttribute("data-name")||""}isSensitiveField(e){let t=e.toLowerCase();return this.config.sensitiveFields.some(i=>t.includes(i))}sanitizeFieldName(e){return e.replace(/[0-9]+/g,"*").substring(0,50)}detectFormType(e){return e.classList.contains("hs-form")||e.closest(".hs-form")?"hubspot":e.classList.contains("typeform-widget")||e.closest("[data-tf-widget]")?"typeform":e.classList.contains("jotform-form")||e.closest(".jotform-form")?"jotform":e.classList.contains("gform_wrapper")||e.closest(".gform_wrapper")?"gravity":e.tagName==="FORM"?"native":"unknown"}emitEvent(e){this.config.onFormEvent?.(e)}};var Ae=[30,60,90,100],H=class{constructor(e={}){this.maxDepth=0;this.reportedChunks=new Set;this.ticking=!1;this.isVisible=!0;this.handleScroll=()=>{!this.ticking&&this.isVisible&&(requestAnimationFrame(()=>{this.checkScrollDepth(),this.ticking=!1}),this.ticking=!0)};this.handleVisibility=()=>{this.isVisible=document.visibilityState==="visible"};this.config={chunks:Ae,...e},this.startTime=Date.now()}start(){window.addEventListener("scroll",this.handleScroll,{passive:!0}),document.addEventListener("visibilitychange",this.handleVisibility),this.checkScrollDepth()}stop(){window.removeEventListener("scroll",this.handleScroll),document.removeEventListener("visibilitychange",this.handleVisibility)}getMaxDepth(){return this.maxDepth}getReportedChunks(){return Array.from(this.reportedChunks).sort((e,t)=>e-t)}getFinalEvent(){let e=document.documentElement.scrollHeight,t=window.innerHeight;return{depth:this.maxDepth,chunk:this.getChunkForDepth(this.maxDepth),time_to_reach_ms:Date.now()-this.startTime,total_height:e,viewport_height:t}}checkScrollDepth(){let e=window.scrollY,t=window.innerHeight,i=document.documentElement.scrollHeight;if(i<=t){this.updateDepth(100);return}let s=i-t,r=Math.min(100,Math.round(e/s*100));this.updateDepth(r)}updateDepth(e){if(!(e<=this.maxDepth)){this.maxDepth=e,this.config.onDepthChange?.(e);for(let t of this.config.chunks)e>=t&&!this.reportedChunks.has(t)&&(this.reportedChunks.add(t),this.reportChunk(t))}}reportChunk(e){let t=document.documentElement.scrollHeight,i=window.innerHeight,s={depth:this.maxDepth,chunk:e,time_to_reach_ms:Date.now()-this.startTime,total_height:t,viewport_height:i};this.config.onChunkReached?.(s)}getChunkForDepth(e){let t=this.config.chunks.sort((i,s)=>s-i);for(let i of t)if(e>=i)return i;return 0}};var Re={idleThresholdMs:3e4,updateIntervalMs:5e3},V=class{constructor(e={}){this.activeTime=0;this.idleTime=0;this.isVisible=!0;this.isIdle=!1;this.updateInterval=null;this.idleCheckInterval=null;this.handleVisibility=()=>{let e=this.isVisible;this.isVisible=document.visibilityState==="visible",e&&!this.isVisible?this.updateTimes():!e&&this.isVisible&&(this.lastUpdateTime=Date.now(),this.lastActivityTime=Date.now())};this.handleActivity=()=>{let e=Date.now();this.isIdle&&(this.isIdle=!1),this.lastActivityTime=e};this.config={...Re,...e},this.startTime=Date.now(),this.lastActivityTime=this.startTime,this.lastUpdateTime=this.startTime}start(){document.addEventListener("visibilitychange",this.handleVisibility),["mousemove","keydown","scroll","click","touchstart"].forEach(t=>{document.addEventListener(t,this.handleActivity,{passive:!0})}),this.updateInterval=setInterval(()=>{this.update()},this.config.updateIntervalMs),this.idleCheckInterval=setInterval(()=>{this.checkIdle()},1e3)}stop(){document.removeEventListener("visibilitychange",this.handleVisibility),["mousemove","keydown","scroll","click","touchstart"].forEach(t=>{document.removeEventListener(t,this.handleActivity)}),this.updateInterval&&(clearInterval(this.updateInterval),this.updateInterval=null),this.idleCheckInterval&&(clearInterval(this.idleCheckInterval),this.idleCheckInterval=null)}getMetrics(){return this.updateTimes(),{active_time_ms:this.activeTime,total_time_ms:Date.now()-this.startTime,idle_time_ms:this.idleTime,is_engaged:!this.isIdle&&this.isVisible}}getFinalMetrics(){return this.updateTimes(),this.getMetrics()}checkIdle(){let t=Date.now()-this.lastActivityTime;!this.isIdle&&t>=this.config.idleThresholdMs&&(this.isIdle=!0)}updateTimes(){let e=Date.now(),t=e-this.lastUpdateTime;this.isVisible&&(this.isIdle?this.idleTime+=t:this.activeTime+=t),this.lastUpdateTime=e}update(){this.isVisible&&(this.updateTimes(),this.config.onUpdate?.(this.getMetrics()))}};var b="2.4.0",u={apiHost:"https://app.loamly.ai",endpoints:{visit:"/api/ingest/visit",behavioral:"/api/ingest/behavioral",session:"/api/ingest/session",resolve:"/api/tracker/resolve",health:"/api/tracker/health",ping:"/api/tracker/ping"},pingInterval:3e4,batchSize:10,batchTimeout:5e3,sessionTimeout:18e5,maxTextLength:100,timeSpentThresholdMs:5e3},K={"chatgpt.com":"chatgpt","chat.openai.com":"chatgpt","claude.ai":"claude","perplexity.ai":"perplexity","bard.google.com":"bard","gemini.google.com":"gemini","copilot.microsoft.com":"copilot","github.com/copilot":"github-copilot","you.com":"you","phind.com":"phind","poe.com":"poe"};var ie=class{constructor(){this.detected=!1;this.checkComplete=!1;this.observer=null}init(e=5e3){typeof document>"u"||(this.check(),!this.detected&&document.body&&(this.observer=new MutationObserver(()=>this.check()),this.observer.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>{this.observer&&!this.detected&&(this.observer.disconnect(),this.observer=null,this.checkComplete=!0)},e)))}check(){document.querySelector(".pplx-agent-overlay-stop-button")&&(this.detected=!0,this.checkComplete=!0,this.observer&&(this.observer.disconnect(),this.observer=null))}isDetected(){return this.detected}isCheckComplete(){return this.checkComplete}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null)}},ne=class{constructor(e=500){this.lastX=-1;this.lastY=-1;this.teleportingClicks=0;this.totalMovements=0;this.handleMove=e=>{this.totalMovements++,this.lastX=e.clientX,this.lastY=e.clientY};this.handleClick=e=>{if(this.lastX!==-1&&this.lastY!==-1){let t=Math.abs(e.clientX-this.lastX),i=Math.abs(e.clientY-this.lastY);(t>this.teleportThreshold||i>this.teleportThreshold)&&this.teleportingClicks++}this.lastX=e.clientX,this.lastY=e.clientY};this.teleportThreshold=e}init(){typeof document>"u"||(document.addEventListener("mousemove",this.handleMove,{passive:!0}),document.addEventListener("mousedown",this.handleClick,{passive:!0}))}getPatterns(){return{teleportingClicks:this.teleportingClicks,totalMovements:this.totalMovements}}destroy(){typeof document>"u"||(document.removeEventListener("mousemove",this.handleMove),document.removeEventListener("mousedown",this.handleClick))}},se=class{constructor(){this.detected=!1}detect(){if(typeof navigator>"u")return!1;if(navigator.webdriver)return this.detected=!0,!0;if(typeof window<"u"){let e=window,t=["__webdriver_evaluate","__selenium_evaluate","__webdriver_script_function","__webdriver_script_func","__webdriver_script_fn","__fxdriver_evaluate","__driver_unwrapped","__webdriver_unwrapped","__driver_evaluate","__selenium_unwrapped","__fxdriver_unwrapped"];for(let i of t)if(i in e)return this.detected=!0,!0}return!1}isDetected(){return this.detected}},Y=class{constructor(){this.initialized=!1;this.cometDetector=new ie,this.mouseAnalyzer=new ne,this.cdpDetector=new se}init(){this.initialized||(this.initialized=!0,this.cometDetector.init(),this.mouseAnalyzer.init(),this.cdpDetector.detect())}getResult(){let e=[],t=0;this.cometDetector.isDetected()&&(e.push("comet_dom_detected"),t=Math.max(t,.85)),this.cdpDetector.isDetected()&&(e.push("cdp_detected"),t=Math.max(t,.92));let i=this.mouseAnalyzer.getPatterns();return i.teleportingClicks>0&&(e.push(`teleporting_clicks:${i.teleportingClicks}`),t=Math.max(t,.78)),{cometDOMDetected:this.cometDetector.isDetected(),cdpDetected:this.cdpDetector.isDetected(),mousePatterns:i,agenticProbability:t,signals:e}}destroy(){this.cometDetector.destroy(),this.mouseAnalyzer.destroy()}};var me={human:{time_to_first_click_delayed:.85,time_to_first_click_normal:.75,time_to_first_click_fast:.5,time_to_first_click_immediate:.25,scroll_speed_variable:.8,scroll_speed_erratic:.7,scroll_speed_uniform:.35,scroll_speed_none:.45,nav_timing_click:.75,nav_timing_unknown:.55,nav_timing_paste:.35,has_referrer:.7,no_referrer:.45,homepage_landing:.65,deep_landing:.5,mouse_movement_curved:.9,mouse_movement_linear:.3,mouse_movement_none:.4,form_fill_normal:.85,form_fill_fast:.6,form_fill_instant:.2,focus_blur_normal:.75,focus_blur_rapid:.45},ai_influenced:{time_to_first_click_immediate:.75,time_to_first_click_fast:.55,time_to_first_click_normal:.4,time_to_first_click_delayed:.35,scroll_speed_none:.55,scroll_speed_uniform:.7,scroll_speed_variable:.35,scroll_speed_erratic:.4,nav_timing_paste:.75,nav_timing_unknown:.5,nav_timing_click:.35,no_referrer:.65,has_referrer:.4,deep_landing:.6,homepage_landing:.45,mouse_movement_none:.6,mouse_movement_linear:.75,mouse_movement_curved:.25,form_fill_instant:.8,form_fill_fast:.55,form_fill_normal:.3,focus_blur_rapid:.6,focus_blur_normal:.4}},he={human:.85,ai_influenced:.15},fe=.5,j=class{constructor(e=1e4){this.classified=!1;this.result=null;this.onClassify=null;this.minSessionTime=e,this.data={firstClickTime:null,scrollEvents:[],mouseEvents:[],formEvents:[],focusBlurEvents:[],startTime:Date.now()}}setOnClassify(e){this.onClassify=e}recordClick(){this.data.firstClickTime===null&&(this.data.firstClickTime=Date.now()),this.checkAndClassify()}recordScroll(e){this.data.scrollEvents.push({time:Date.now(),position:e}),this.data.scrollEvents.length>50&&(this.data.scrollEvents=this.data.scrollEvents.slice(-50)),this.checkAndClassify()}recordMouse(e,t){this.data.mouseEvents.push({time:Date.now(),x:e,y:t}),this.data.mouseEvents.length>100&&(this.data.mouseEvents=this.data.mouseEvents.slice(-100)),this.checkAndClassify()}recordFormStart(e){this.data.formEvents.find(i=>i.fieldId===e&&i.endTime===0)||this.data.formEvents.push({fieldId:e,startTime:Date.now(),endTime:0})}recordFormEnd(e){let t=this.data.formEvents.find(i=>i.fieldId===e&&i.endTime===0);t&&(t.endTime=Date.now()),this.checkAndClassify()}recordFocusBlur(e){this.data.focusBlurEvents.push({type:e,time:Date.now()}),this.data.focusBlurEvents.length>20&&(this.data.focusBlurEvents=this.data.focusBlurEvents.slice(-20))}checkAndClassify(){this.classified||Date.now()-this.data.startTime<this.minSessionTime||!(this.data.scrollEvents.length>=2||this.data.mouseEvents.length>=5||this.data.firstClickTime!==null)||this.classify()}forceClassify(){return this.classified?this.result:this.classify()}classify(){let e=Date.now()-this.data.startTime,t=this.extractSignals(),i=Math.log(he.human),s=Math.log(he.ai_influenced);for(let M of t){let ee=me.human[M]??fe,ue=me.ai_influenced[M]??fe;i+=Math.log(ee),s+=Math.log(ue)}let r=Math.max(i,s),o=Math.exp(i-r),h=Math.exp(s-r),f=o+h,l=o/f,c=h/f,C,S;return l>.6?(C="human",S=l):c>.6?(C="ai_influenced",S=c):(C="uncertain",S=Math.max(l,c)),this.result={classification:C,humanProbability:l,aiProbability:c,confidence:S,signals:t,timestamp:Date.now(),sessionDurationMs:e},this.classified=!0,this.onClassify&&this.onClassify(this.result),this.result}extractSignals(){let e=[];if(this.data.firstClickTime!==null){let i=this.data.firstClickTime-this.data.startTime;i<500?e.push("time_to_first_click_immediate"):i<2e3?e.push("time_to_first_click_fast"):i<1e4?e.push("time_to_first_click_normal"):e.push("time_to_first_click_delayed")}if(this.data.scrollEvents.length===0)e.push("scroll_speed_none");else if(this.data.scrollEvents.length>=3){let i=[];for(let f=1;f<this.data.scrollEvents.length;f++){let l=this.data.scrollEvents[f].time-this.data.scrollEvents[f-1].time;i.push(l)}let s=i.reduce((f,l)=>f+l,0)/i.length,r=i.reduce((f,l)=>f+Math.pow(l-s,2),0)/i.length,o=Math.sqrt(r),h=s>0?o/s:0;h<.2?e.push("scroll_speed_uniform"):h<.6?e.push("scroll_speed_variable"):e.push("scroll_speed_erratic")}if(this.data.mouseEvents.length===0)e.push("mouse_movement_none");else if(this.data.mouseEvents.length>=10){let i=Math.min(this.data.mouseEvents.length,20),s=this.data.mouseEvents.slice(-i),r=0,o=0,h=0,f=0;for(let y of s)r+=y.x,o+=y.y,h+=y.x*y.y,f+=y.x*y.x;let l=i*f-r*r,c=l!==0?(i*h-r*o)/l:0,C=(o-c*r)/i,S=0,M=0,ee=o/i;for(let y of s){let Ie=c*y.x+C;S+=Math.pow(y.y-Ie,2),M+=Math.pow(y.y-ee,2)}(M!==0?1-S/M:0)>.95?e.push("mouse_movement_linear"):e.push("mouse_movement_curved")}let t=this.data.formEvents.filter(i=>i.endTime>0);if(t.length>0){let i=t.reduce((s,r)=>s+(r.endTime-r.startTime),0)/t.length;i<100?e.push("form_fill_instant"):i<500?e.push("form_fill_fast"):e.push("form_fill_normal")}if(this.data.focusBlurEvents.length>=4){let i=this.data.focusBlurEvents.slice(-10),s=[];for(let o=1;o<i.length;o++)s.push(i[o].time-i[o-1].time);s.reduce((o,h)=>o+h,0)/s.length<1e3?e.push("focus_blur_rapid"):e.push("focus_blur_normal")}return e}addContextSignal(e){}getResult(){return this.result}hasClassified(){return this.classified}};var W=class{constructor(){this.sequence=[];this.firstInteractionTime=null;this.analyzed=!1;this.result=null;this.pageLoadTime=performance.now()}initTracking(){document.addEventListener("focus",t=>{this.recordEvent("focus",t.target)},!0),document.addEventListener("blur",t=>{this.recordEvent("blur",t.target)},!0),window.addEventListener("focus",()=>{this.recordEvent("window_focus",null)}),window.addEventListener("blur",()=>{this.recordEvent("window_blur",null)});let e=()=>{this.firstInteractionTime===null&&(this.firstInteractionTime=performance.now())};document.addEventListener("click",e,{once:!0,passive:!0}),document.addEventListener("keydown",e,{once:!0,passive:!0})}recordEvent(e,t){let i={type:e,target:t?.tagName||"WINDOW",timestamp:performance.now()};this.sequence.push(i),this.sequence.length>20&&(this.sequence=this.sequence.slice(-20))}analyze(){if(this.analyzed&&this.result)return this.result;let e=[],t=0,i=this.sequence.filter(c=>c.timestamp<this.pageLoadTime+500);i.some(c=>c.type==="window_focus")&&(e.push("early_window_focus"),t+=.15),i.some(c=>c.type==="focus"&&c.target==="BODY")&&(e.push("early_body_focus"),t+=.15),this.sequence.some(c=>c.type==="focus"&&c.target==="A")||(e.push("no_link_focus"),t+=.1);let h=this.sequence.find(c=>c.type==="focus");h&&(h.target==="BODY"||h.target==="HTML")&&(e.push("first_focus_body"),t+=.1),this.sequence.filter(c=>c.type==="window_focus"||c.type==="window_blur").length<=2&&(e.push("minimal_window_switches"),t+=.05),this.firstInteractionTime!==null&&this.firstInteractionTime-this.pageLoadTime>3e3&&(e.push("delayed_first_interaction"),t+=.1),t=Math.min(t,.65);let l;return t>=.35?l="likely_paste":e.length===0?l="unknown":l="likely_click",this.result={nav_type:l,confidence:t,signals:e,sequence:this.sequence.slice(-10),time_to_first_interaction_ms:this.firstInteractionTime?Math.round(this.firstInteractionTime-this.pageLoadTime):null},this.analyzed=!0,this.result}getResult(){return this.analyze()}hasAnalyzed(){return this.analyzed}getSequence(){return[...this.sequence]}reset(){this.sequence=[],this.pageLoadTime=performance.now(),this.firstInteractionTime=null,this.analyzed=!1,this.result=null}};function pe(){try{let n=performance.getEntriesByType("navigation");if(!n||n.length===0)return{nav_type:"unknown",confidence:0,signals:["no_timing_data"]};let e=n[0],t=[],i=0,s=e.fetchStart-e.startTime;s<5?(i+=.25,t.push("instant_fetch_start")):s<20&&(i+=.15,t.push("fast_fetch_start")),e.domainLookupEnd-e.domainLookupStart===0&&(i+=.15,t.push("no_dns_lookup")),e.connectEnd-e.connectStart===0&&(i+=.15,t.push("no_tcp_connect")),e.redirectCount===0&&(i+=.1,t.push("no_redirects")),Be(e)<10&&(i+=.15,t.push("uniform_timing")),(!document.referrer||document.referrer==="")&&(i+=.1,t.push("no_referrer"));let f=Math.min(i,1);return{nav_type:i>=.5?"likely_paste":"likely_click",confidence:Math.round(f*1e3)/1e3,signals:t}}catch{return{nav_type:"unknown",confidence:0,signals:["detection_error"]}}}function Be(n){let e=[n.fetchStart-n.startTime,n.domainLookupEnd-n.domainLookupStart,n.connectEnd-n.connectStart,n.responseStart-n.requestStart].filter(s=>s>=0);if(e.length===0)return 100;let t=e.reduce((s,r)=>s+r,0)/e.length,i=e.reduce((s,r)=>s+Math.pow(r-t,2),0)/e.length;return Math.sqrt(i)}function ve(n){if(!n)return null;try{let t=new URL(n).hostname.toLowerCase();for(let[i,s]of Object.entries(K))if(t.includes(i)||n.includes(i))return{isAI:!0,platform:s,confidence:.95,method:"referrer"};return null}catch{for(let[e,t]of Object.entries(K))if(n.toLowerCase().includes(e.toLowerCase()))return{isAI:!0,platform:t,confidence:.85,method:"referrer"};return null}}function ge(n){try{let t=new URL(n).searchParams.get("utm_source")?.toLowerCase();if(t){for(let[i,s]of Object.entries(K))if(t.includes(i.split(".")[0]))return{isAI:!0,platform:s,confidence:.99,method:"referrer"};if(t.includes("ai")||t.includes("llm")||t.includes("chatbot"))return{isAI:!0,platform:t,confidence:.9,method:"referrer"}}return null}catch{return null}}var Pe={batchSize:u.batchSize,batchTimeout:u.batchTimeout,maxRetries:3,retryDelayMs:1e3,storageKey:"_loamly_queue"},$=class{constructor(e,t={}){this.queue=[];this.batchTimer=null;this.isFlushing=!1;this.endpoint=e,this.config={...Pe,...t},this.loadFromStorage()}push(e,t,i){let s={id:this.generateId(),type:e,payload:t,headers:i,timestamp:Date.now(),retries:0};this.queue.push(s),this.saveToStorage(),this.scheduleBatch()}async flush(){if(!(this.isFlushing||this.queue.length===0)){this.isFlushing=!0,this.clearBatchTimer();try{let e=[...this.queue];this.queue=[],await this.sendBatch(e)}finally{this.isFlushing=!1,this.saveToStorage()}}}flushBeacon(){if(this.queue.length===0)return!0;let e=this.config.apiKey?`${this.endpoint}?api_key=${encodeURIComponent(this.config.apiKey)}`:this.endpoint,t=!0;for(let i of this.queue){let s={...i.payload,_queue_id:i.id,_queue_timestamp:i.timestamp};if(!(navigator.sendBeacon?.(e,JSON.stringify(s))??!1)){t=!1;break}}return t&&(this.queue=[],this.clearStorage()),t}get length(){return this.queue.length}scheduleBatch(){if(!this.batchTimer){if(this.queue.length>=this.config.batchSize){this.flush();return}this.batchTimer=setTimeout(()=>{this.batchTimer=null,this.flush()},this.config.batchTimeout)}}clearBatchTimer(){this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null)}async sendBatch(e){if(e.length!==0)try{let t=await Promise.allSettled(e.map(async s=>{let r=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...s.headers||{}},body:JSON.stringify({...s.payload,_queue_id:s.id,_queue_timestamp:s.timestamp})});if(!r.ok)throw new Error(`HTTP ${r.status}`)})),i=e.filter((s,r)=>t[r]?.status==="rejected");if(i.length>0){for(let r of i)r.retries<this.config.maxRetries&&(r.retries++,this.queue.push(r));let s=this.config.retryDelayMs*Math.pow(2,i[0].retries-1);setTimeout(()=>this.flush(),s)}return}catch{for(let i of e)i.retries<this.config.maxRetries&&(i.retries++,this.queue.push(i));if(this.queue.length>0){let i=this.config.retryDelayMs*Math.pow(2,e[0].retries-1);setTimeout(()=>this.flush(),i)}}}loadFromStorage(){try{let e=localStorage.getItem(this.config.storageKey);if(e){let t=JSON.parse(e);if(Array.isArray(t)){let i=Date.now()-864e5;this.queue=t.filter(s=>s.timestamp>i)}}}catch{}}saveToStorage(){try{this.queue.length>0?localStorage.setItem(this.config.storageKey,JSON.stringify(this.queue)):this.clearStorage()}catch{}}clearStorage(){try{localStorage.removeItem(this.config.storageKey)}catch{}}generateId(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}};var X=class{constructor(e,t,i,s={}){this.intervalId=null;this.isVisible=!0;this.isFocused=!0;this.currentScrollDepth=0;this.ping=async()=>{let e=this.getData();if(this.config.onPing?.(e),this.config.endpoint)try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}catch{}};this.handleVisibilityChange=()=>{this.isVisible=document.visibilityState==="visible"};this.handleFocusChange=()=>{this.isFocused=typeof document.hasFocus=="function"?document.hasFocus():!0,this.intervalId&&this.isVisible&&this.isFocused&&this.ping()};this.handleScroll=()=>{let e=Math.round((window.scrollY+window.innerHeight)/document.documentElement.scrollHeight*100);e>this.currentScrollDepth&&(this.currentScrollDepth=Math.min(e,100))};this.sessionId=e,this.visitorId=t,this.version=i,this.pageLoadTime=Date.now(),this.isVisible=document.visibilityState==="visible",this.isFocused=typeof document.hasFocus=="function"?document.hasFocus():!0,this.config={interval:u.pingInterval,endpoint:"",...s},document.addEventListener("visibilitychange",this.handleVisibilityChange),window.addEventListener("focus",this.handleFocusChange),window.addEventListener("blur",this.handleFocusChange),window.addEventListener("scroll",this.handleScroll,{passive:!0})}start(){this.intervalId||(this.intervalId=setInterval(()=>{this.isVisible&&this.isFocused&&this.ping()},this.config.interval),this.isVisible&&this.isFocused&&this.ping())}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),document.removeEventListener("visibilitychange",this.handleVisibilityChange),window.removeEventListener("focus",this.handleFocusChange),window.removeEventListener("blur",this.handleFocusChange),window.removeEventListener("scroll",this.handleScroll)}updateScrollDepth(e){e>this.currentScrollDepth&&(this.currentScrollDepth=e)}getData(){return{session_id:this.sessionId,visitor_id:this.visitorId,url:window.location.href,time_on_page_ms:Date.now()-this.pageLoadTime,scroll_depth:this.currentScrollDepth,is_active:this.isVisible&&this.isFocused,tracker_version:this.version}}};var O=class{constructor(e={}){this.originalPushState=null;this.originalReplaceState=null;this.handleStateChange=e=>{let t=window.location.href;t!==this.currentUrl&&this.emitNavigation(t,e)};this.handlePopState=()=>{let e=window.location.href;e!==this.currentUrl&&this.emitNavigation(e,"pop")};this.handleHashChange=()=>{let e=window.location.href;e!==this.currentUrl&&this.emitNavigation(e,"hash")};this.config=e,this.currentUrl=window.location.href,this.pageEnterTime=Date.now()}start(){this.patchHistoryAPI(),window.addEventListener("popstate",this.handlePopState),this.config.ignoreHashChange||window.addEventListener("hashchange",this.handleHashChange)}stop(){this.originalPushState&&(history.pushState=this.originalPushState),this.originalReplaceState&&(history.replaceState=this.originalReplaceState),window.removeEventListener("popstate",this.handlePopState),window.removeEventListener("hashchange",this.handleHashChange)}navigate(e,t="push"){this.emitNavigation(e,t)}getCurrentUrl(){return this.currentUrl}getTimeOnPage(){return Date.now()-this.pageEnterTime}patchHistoryAPI(){this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...e)=>{let t=this.originalPushState(...e);return this.handleStateChange("push"),t},history.replaceState=(...e)=>{let t=this.originalReplaceState(...e);return this.handleStateChange("replace"),t}}emitNavigation(e,t){let i={from_url:this.currentUrl,to_url:e,navigation_type:t,time_on_previous_page_ms:Date.now()-this.pageEnterTime};this.currentUrl=e,this.pageEnterTime=Date.now(),this.config.onNavigate?.(i)}};function G(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{let e=Math.random()*16|0;return(n==="x"?e:e&3|8).toString(16)})}function _e(){try{let n=localStorage.getItem("_loamly_vid");if(n)return n;let e=G();return localStorage.setItem("_loamly_vid",e),e}catch{return G()}}function ye(){try{let n=sessionStorage.getItem("loamly_session"),e=sessionStorage.getItem("loamly_start");if(n&&e)return{sessionId:n,isNew:!1};let t=G(),i=Date.now().toString();return sessionStorage.setItem("loamly_session",t),sessionStorage.setItem("loamly_start",i),{sessionId:t,isNew:!0}}catch{return{sessionId:G(),isNew:!0}}}function be(n){let e={};try{let t=new URL(n).searchParams,i=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"];for(let s of i){let r=t.get(s);r&&(e[s]=r)}}catch{}return e}function re(n,e){return n.length<=e?n:n.substring(0,e-3)+"..."}async function x(n,e,t=1e4){try{let i=new AbortController,s=setTimeout(()=>i.abort(),t),r=await fetch(n,{...e,signal:i.signal});return clearTimeout(s),r}catch{return null}}function oe(n,e){return typeof navigator<"u"&&navigator.sendBeacon?navigator.sendBeacon(n,JSON.stringify(e)):!1}var p={apiHost:u.apiHost},E=!1,ae=!1,g=null,m=null,v=null,R=null,_=null,le=null,d=null,ce=null,A=null,Q=null,I=null,F=null,B=null,k=null,P=null,U=null,D=null;function a(...n){ae&&console.log("[Loamly]",...n)}function T(n){return`${p.apiHost}${n}`}function q(n){let e={"Content-Type":"application/json"};return p.apiKey&&(e["X-Loamly-Api-Key"]=p.apiKey),n&&(e["X-Idempotency-Key"]=n),e}function we(n){if(!p.apiKey)return n;let e=new URL(n,p.apiHost);return e.searchParams.set("api_key",p.apiKey),e.toString()}function N(n){return`${n}:${m||g||"unknown"}:${Date.now()}`}function Ne(n={}){if(E){a("Already initialized");return}p={...p,...n,apiHost:n.apiHost||u.apiHost},v=n.workspaceId??null,ae=n.debug??!1,p.apiKey&&!v&&a("Workspace ID missing. Behavioral events require workspaceId.");let e={scroll:!0,time:!0,forms:!0,spa:!0,behavioralML:!0,focusBlur:!0,agentic:!0,eventQueue:!0,ping:!1,...n.features};a("Initializing Loamly Tracker v"+b),a("Features:",e),g=_e(),a("Visitor ID:",g),e.eventQueue&&(F=new $(T(u.endpoints.behavioral),{batchSize:u.batchSize,batchTimeout:u.batchTimeout,apiKey:p.apiKey})),R=pe(),a("Navigation timing:",R),_=ve(document.referrer)||ge(window.location.href),_&&a("AI detected:",_),E=!0,e.agentic&&(I=new Y,I.init()),Oe().finally(()=>{He(),n.disableAutoPageview||J(),n.disableBehavioral||Ue(e),e.behavioralML&&(d=new j(1e4),d.setOnClassify(Te),Ye()),e.focusBlur&&(A=new W,A.initTracking(),setTimeout(()=>{A&&je(A.analyze())},5e3)),e.ping&&g&&m&&(B=new X(m,g,b,{interval:u.pingInterval,endpoint:T(u.endpoints.ping)}),B.start())}),D=new O({onNavigate:qe}),D.start(),ze(),Ee("initialized"),a("Initialization complete")}async function He(){if(!(typeof navigator>"u"||!("serviceWorker"in navigator))&&!(!p.apiKey||!v))try{let n=new URL("/tracker/loamly-sw.js",window.location.origin);n.searchParams.set("workspace_id",v),n.searchParams.set("api_key",p.apiKey);let e=await navigator.serviceWorker.register(n.toString(),{scope:"/"});e.addEventListener("updatefound",()=>{let t=e.installing;t?.addEventListener("statechange",()=>{t.state==="activated"&&t.postMessage({type:"SKIP_WAITING"})})}),setInterval(()=>{e.update().catch(()=>{})},1440*60*1e3)}catch{}}async function Oe(){let n=Date.now();le=n;try{let t=sessionStorage.getItem("loamly_session"),i=sessionStorage.getItem("loamly_start"),s=p.sessionTimeout??u.sessionTimeout;if(t&&i){let r=parseInt(i,10),o=n-r;if(o>0&&o<s){m=t,a("Session ID:",m,"(existing)");return}}}catch{}if(p.apiKey&&v&&g)try{let t=await x(T(u.endpoints.session),{method:"POST",headers:q(),body:JSON.stringify({workspace_id:v,visitor_id:g})});if(t?.ok){let i=await t.json();m=i.session_id||m;let s=i.start_time||n;if(m){try{sessionStorage.setItem("loamly_session",m),sessionStorage.setItem("loamly_start",String(s))}catch{}a("Session ID:",m,"(server)");return}}}catch{}let e=ye();m=e.sessionId,a("Session ID:",m,e.isNew?"(new)":"(existing)")}function Ue(n){n.scroll&&(k=new H({chunks:[30,60,90,100],onChunkReached:e=>{a("Scroll chunk:",e.chunk),w("scroll_depth",{scroll_depth:Math.round(e.depth/100*100)/100,milestone:Math.round(e.chunk/100*100)/100,time_to_reach_ms:e.time_to_reach_ms})}}),k.start()),n.time&&(P=new V({updateIntervalMs:1e4,onUpdate:e=>{e.active_time_ms>=u.timeSpentThresholdMs&&w("time_spent",{visible_time_ms:e.total_time_ms,page_start_time:le||Date.now()})}}),P.start()),n.forms&&(U=new z({onFormEvent:e=>{a("Form event:",e.event_type,e.form_id);let t=e.event_type==="form_submit",i=e.event_type==="form_success",s=t||i?"form_submit":"form_focus",r=e.submit_source||(i?"thank_you":t?"submit":null);w(s,{form_id:e.form_id,form_provider:e.form_type||"unknown",form_field_type:e.field_type||null,form_field_name:e.field_name||null,form_event_type:e.event_type,submit_source:r,is_inferred:i,time_to_submit_seconds:e.time_to_submit_ms?Math.round(e.time_to_submit_ms/1e3):null,fields:e.fields||null,email_submitted:e.email_submitted||null})}}),U.start()),n.spa&&(D=new O({onNavigate:e=>{a("SPA navigation:",e.navigation_type),J(e.to_url)}}),D.start()),document.addEventListener("click",e=>{let i=e.target.closest("a");if(i&&i.href){let s=i.hostname!==window.location.hostname;w("click",{element_type:"link",href:re(i.href,200),text:re(i.textContent||"",100),is_external:s})}})}function w(n,e){if(!F)return;if(!p.apiKey){a("Missing apiKey, behavioral event skipped:",n);return}if(!v){a("Missing workspaceId, behavioral event skipped:",n);return}if(!m){a("Missing sessionId, behavioral event skipped:",n);return}let t=N(n),i={visitor_id:g,session_id:m,event_type:n,event_data:e,page_url:window.location.href,page_path:window.location.pathname,timestamp:new Date().toISOString(),tracker_version:b,idempotency_key:t};i.workspace_id=v,F.push(n,i,q(t))}function qe(n){a("SPA navigation:",n.navigation_type,n.to_url),F?.flush(),B?.updateScrollDepth(0),k?.stop(),k=new H({chunks:[30,60,90,100],onChunkReached:e=>{w("scroll_depth",{depth:e.depth,chunk:e.chunk,time_to_reach_ms:e.time_to_reach_ms})}}),k.start(),J(n.to_url),w("spa_navigation",{from_url:n.from_url,to_url:n.to_url,navigation_type:n.navigation_type,time_on_previous_page_ms:n.time_on_previous_page_ms})}function ze(){let n=()=>{if(!v||!p.apiKey||!m)return;let e=k?.getFinalEvent();e&&oe(we(T(u.endpoints.behavioral)),{workspace_id:v,visitor_id:g,session_id:m,event_type:"scroll_depth_final",event_data:{scroll_depth:Math.round(e.depth/100*100)/100,milestone:Math.round(e.chunk/100*100)/100,time_to_reach_ms:e.time_to_reach_ms},page_url:window.location.href,page_path:window.location.pathname,timestamp:new Date().toISOString(),tracker_version:b,idempotency_key:N("scroll_depth_final")});let t=P?.getFinalMetrics();if(t&&oe(we(T(u.endpoints.behavioral)),{workspace_id:v,visitor_id:g,session_id:m,event_type:"time_spent",event_data:{visible_time_ms:t.total_time_ms,page_start_time:le||Date.now()},page_url:window.location.href,page_path:window.location.pathname,timestamp:new Date().toISOString(),tracker_version:b,idempotency_key:N("time_spent")}),F?.flushBeacon(),d&&!d.hasClassified()){let i=d.forceClassify();i&&Te(i)}};window.addEventListener("beforeunload",n),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&n()})}function J(n){if(!E){a("Not initialized, call init() first");return}if(!p.apiKey){a("Missing apiKey, pageview skipped");return}let e=n||window.location.href,t=be(e),i=new Date().toISOString(),s=N("visit"),r=I?.getResult(),o=(()=>{try{return new URL(e).pathname}catch{return window.location.pathname}})(),h={visitor_id:g,session_id:m,page_url:e,page_path:o,referrer:document.referrer||null,title:document.title||null,utm_source:t.utm_source||null,utm_medium:t.utm_medium||null,utm_campaign:t.utm_campaign||null,utm_term:t.utm_term||null,utm_content:t.utm_content||null,user_agent:navigator.userAgent,screen_width:window.screen?.width,screen_height:window.screen?.height,language:navigator.language,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,tracker_version:b,event_type:"pageview",event_data:null,timestamp:i,navigation_timing:R,ai_platform:_?.platform||null,is_ai_referrer:_?.isAI||!1,agentic_detection:r||null};v&&(h.workspace_id=v),a("Pageview:",h),x(T(u.endpoints.visit),{method:"POST",headers:q(s),body:JSON.stringify(h)})}function ke(n,e={}){if(!E){a("Not initialized, call init() first");return}if(!p.apiKey){a("Missing apiKey, event skipped:",n);return}let t=N(`event:${n}`),i={visitor_id:g,session_id:m,event_name:n,event_type:"custom",properties:e.properties||{},revenue:e.revenue,currency:e.currency||"USD",page_url:window.location.href,referrer:document.referrer||null,timestamp:new Date().toISOString(),tracker_version:b,idempotency_key:t};v&&(i.workspace_id=v),a("Event:",n,i),x(T("/api/ingest/event"),{method:"POST",headers:q(t),body:JSON.stringify(i)})}function Ve(n,e,t="USD"){ke(n,{revenue:e,currency:t,properties:{type:"conversion"}})}function Ke(n,e={}){if(!E){a("Not initialized, call init() first");return}if(!p.apiKey){a("Missing apiKey, identify skipped");return}a("Identify:",n,e);let t=N("identify"),i={visitor_id:g,session_id:m,user_id:n,traits:e,timestamp:new Date().toISOString(),idempotency_key:t};v&&(i.workspace_id=v),x(T("/api/ingest/identify"),{method:"POST",headers:q(t),body:JSON.stringify(i)})}function Ye(){if(!d)return;let n=0;document.addEventListener("mousemove",t=>{n++,n%10===0&&d&&d.recordMouse(t.clientX,t.clientY)},{passive:!0}),document.addEventListener("click",()=>{d&&d.recordClick()},{passive:!0});let e=0;document.addEventListener("scroll",()=>{let t=window.scrollY;Math.abs(t-e)>50&&d&&(e=t,d.recordScroll(t))},{passive:!0}),document.addEventListener("focusin",t=>{if(d){d.recordFocusBlur("focus");let i=t.target;(i.tagName==="INPUT"||i.tagName==="TEXTAREA")&&d.recordFormStart(i.id||i.getAttribute("name")||"unknown")}},{passive:!0}),document.addEventListener("focusout",t=>{if(d){d.recordFocusBlur("blur");let i=t.target;(i.tagName==="INPUT"||i.tagName==="TEXTAREA")&&d.recordFormEnd(i.id||i.getAttribute("name")||"unknown")}},{passive:!0}),setTimeout(()=>{d&&!d.hasClassified()&&d.forceClassify()},3e4)}function Te(n){a("Behavioral ML classification:",n),ce={classification:n.classification,humanProbability:n.humanProbability,aiProbability:n.aiProbability,confidence:n.confidence,signals:n.signals,sessionDurationMs:n.sessionDurationMs},w("ml_classification",{classification:n.classification,human_probability:n.humanProbability,ai_probability:n.aiProbability,confidence:n.confidence,signals:n.signals,session_duration_ms:n.sessionDurationMs,navigation_timing:R,ai_detection:_,focus_blur:Q}),n.classification==="ai_influenced"&&n.confidence>=.7&&(_={isAI:!0,confidence:n.confidence,method:"behavioral"},a("AI detection updated from behavioral ML:",_))}function je(n){a("Focus/blur analysis:",n),Q={navType:n.nav_type,confidence:n.confidence,signals:n.signals,timeToFirstInteractionMs:n.time_to_first_interaction_ms},w("focus_blur_analysis",{nav_type:n.nav_type,confidence:n.confidence,signals:n.signals,time_to_first_interaction_ms:n.time_to_first_interaction_ms,sequence_length:n.sequence.length}),n.nav_type==="likely_paste"&&n.confidence>=.4&&(!_||_.confidence<n.confidence)&&(_={isAI:!0,confidence:n.confidence,method:"behavioral"},a("AI detection updated from focus/blur analysis:",_))}function We(){return m}function $e(){return g}function Xe(){return _}function Ge(){return R}function Qe(){return ce}function Je(){return Q}function Ze(){return I?.getResult()||null}function et(){return E}function Ee(n,e){try{let t={workspace_id:v,visitor_id:g,session_id:m,status:n,error_message:e||null,tracker_version:b,page_url:typeof window<"u"?window.location.href:null,user_agent:typeof navigator<"u"?navigator.userAgent:null,timestamp:new Date().toISOString(),features:{scroll_tracker:!!k,time_tracker:!!P,form_tracker:!!U,spa_router:!!D,behavioral_ml:!!d,focus_blur:!!A,agentic:!!I,ping_service:!!B,event_queue:!!F}};x(T(u.endpoints.health),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}).catch(()=>{}),a("Health reported:",n)}catch{}}function tt(){a("Resetting tracker"),B?.stop(),k?.stop(),P?.stop(),U?.stop(),D?.stop(),I?.destroy(),E=!1,g=null,m=null,R=null,_=null,d=null,ce=null,A=null,Q=null,I=null,F=null,B=null,k=null,P=null,U=null,D=null;try{sessionStorage.removeItem("loamly_session"),sessionStorage.removeItem("loamly_start")}catch{}}function it(n){ae=n,a("Debug mode:",n?"enabled":"disabled")}function nt(n,e){if(!E){a("Not initialized, trackBehavioral skipped:",n);return}w(n,e)}function st(){return v}var L={init:Ne,pageview:J,track:ke,trackBehavioral:nt,conversion:Ve,identify:Ke,getSessionId:We,getVisitorId:$e,getWorkspaceId:st,getAIDetection:Xe,getNavigationTiming:Ge,getBehavioralML:Qe,getFocusBlur:Je,getAgentic:Ze,isInitialized:et,reset:tt,debug:it,reportHealth:Ee};function rt(){let n=document.getElementsByTagName("script");for(let e of n){let t=e.src;if(t.includes("t.js")||t.includes("loamly"))try{let s=new URL(t).searchParams.get("d");if(s)return s}catch{}}return null}async function Se(n){try{let e=await fetch(`${u.apiHost}${u.endpoints.resolve}?d=${encodeURIComponent(n)}`);if(!e.ok)return console.warn("[Loamly] Failed to resolve workspace for domain:",n),null;let t=await e.json();return t.workspace_id&&t.public_key?{apiKey:t.public_key,workspaceId:t.workspace_id,apiHost:u.apiHost}:null}catch(e){return console.warn("[Loamly] Error resolving workspace:",e),null}}function ot(){let n=document.getElementsByTagName("script");for(let e of n)if(e.src.includes("loamly")||e.dataset.loamly!==void 0){let t={};if(e.dataset.apiKey&&(t.apiKey=e.dataset.apiKey),e.dataset.workspaceId&&(t.workspaceId=e.dataset.workspaceId),e.dataset.apiHost&&(t.apiHost=e.dataset.apiHost),e.dataset.debug==="true"&&(t.debug=!0),e.dataset.disableAutoPageview==="true"&&(t.disableAutoPageview=!0),e.dataset.disableBehavioral==="true"&&(t.disableBehavioral=!0),t.apiKey||t.workspaceId)return t}return null}async function Z(){let n=rt();if(n){let o=await Se(n);if(o){L.init(o);return}}let e=ot();if(e){L.init(e);return}let t=new URLSearchParams(window.location.search),i=t.get("api_key"),s=t.get("workspace_id");if(i||s){L.init({apiKey:i||void 0,workspaceId:s||void 0});return}let r=window.location.hostname;if(r&&r!=="localhost"){let o=await Se(r);if(o){L.init(o);return}}}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{typeof requestIdleCallback<"u"?requestIdleCallback(()=>Z()):setTimeout(Z,0)}):typeof requestIdleCallback<"u"?requestIdleCallback(()=>Z()):setTimeout(Z,0));var at=L;return xe(lt);})();
2
2
  /**
3
3
  * Loamly Tracker Configuration
4
4
  *