UNPKG

@tinytapanalytics/sdk

Version:

Behavioral psychology platform that detects visitor frustration, predicts abandonment, and helps you save at-risk conversions in real-time

1 lines 5.26 kB
var e={d:function(t,n){for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{j:function(){return n}});class n{constructor(e,t){this.observers=new Set,this.listeners=new Set,this.isActive=!1,this.config=e,this.sdk=t}start(){this.isActive||(this.isActive=!0,this.setupClickTracking(),this.setupFormTracking(),this.setupScrollTracking(),this.setupElementVisibilityTracking(),this.setupPageEngagementTracking(),this.setupErrorTracking(),this.config.debug)}stop(){this.isActive&&(this.isActive=!1,this.observers.forEach(e=>e.disconnect()),this.observers.clear(),this.listeners.forEach(({element:e,event:t,handler:n})=>{e.removeEventListener(t,n)}),this.listeners.clear(),this.config.debug)}setupClickTracking(){const e=e=>{const t=e.target;this.shouldTrackClick(t)&&this.sdk.trackClick(t,{auto_tracked:!0,coordinates:{x:e.clientX,y:e.clientY},timestamp:Date.now()})};document.addEventListener("click",e,!0),this.listeners.add({element:document,event:"click",handler:e})}setupFormTracking(){const e=e=>{const t=e.target;this.sdk.track("form_submit",{form_id:t.id||null,form_action:t.action||null,form_method:t.method||"get",form_fields:this.getFormFields(t),auto_tracked:!0})},t=e=>{const t=e.target,n=t.closest("form");n&&this.shouldTrackFormField(t)&&this.sdk.track("form_field_interaction",{field_name:t.name||null,field_type:t.type||null,field_id:t.id||null,form_id:n.id||null,event_type:e.type,auto_tracked:!0})};document.addEventListener("submit",e,!0),document.addEventListener("focus",t,!0),document.addEventListener("blur",t,!0),this.listeners.add({element:document,event:"submit",handler:e}),this.listeners.add({element:document,event:"focus",handler:t}),this.listeners.add({element:document,event:"blur",handler:t})}setupScrollTracking(){let e,t=0;const n=()=>{clearTimeout(e),e=window.setTimeout(()=>{const e=this.getScrollDepth();if(e>t){const n=t;t=e;const r=[25,50,75,90].find(t=>n<t&&e>=t);r&&this.sdk.track("scroll_depth",{depth:r,auto_tracked:!0,page_height:document.documentElement.scrollHeight,viewport_height:window.innerHeight})}},250)};window.addEventListener("scroll",n,{passive:!0}),this.listeners.add({element:window,event:"scroll",handler:n})}setupElementVisibilityTracking(){if(!("IntersectionObserver"in window))return;const e=new IntersectionObserver(e=>{e.forEach(e=>{if(e.isIntersecting){const t=e.target,n=this.getElementSelector(t);this.sdk.track("element_view",{element:n,element_type:t.tagName.toLowerCase(),visibility_ratio:e.intersectionRatio,auto_tracked:!0})}})},{threshold:[.5]});document.querySelectorAll("[data-track-view]").forEach(t=>e.observe(t)),this.observers.add(e),this.setupDynamicElementTracking(e)}setupPageEngagementTracking(){let e=Date.now(),t=!document.hidden,n=0;const r=()=>{const r=Date.now();document.hidden?t&&(n+=r-e,t=!1):t||(e=r,t=!0)},i=()=>{const r=Date.now();t&&(n+=r-e),this.sdk.track("page_engagement",{total_time:n,page_url:window.location.href,auto_tracked:!0})};document.addEventListener("visibilitychange",r),window.addEventListener("beforeunload",i),this.listeners.add({element:document,event:"visibilitychange",handler:r}),this.listeners.add({element:window,event:"beforeunload",handler:i})}setupErrorTracking(){const e=e=>{const t=e;this.sdk.track("javascript_error",{message:t.message,filename:t.filename,lineno:t.lineno,colno:t.colno,stack:t.error?.stack,auto_tracked:!0})},t=e=>{const t=e;this.sdk.track("promise_rejection",{reason:t.reason?.toString()||"Unknown",auto_tracked:!0})};window.addEventListener("error",e),window.addEventListener("unhandledrejection",t),this.listeners.add({element:window,event:"error",handler:e}),this.listeners.add({element:window,event:"unhandledrejection",handler:t})}setupDynamicElementTracking(e){if(!("MutationObserver"in window))return;const t=new MutationObserver(t=>{t.forEach(t=>{t.addedNodes.forEach(t=>{if(t.nodeType===Node.ELEMENT_NODE){const n=t;n.hasAttribute("data-track-view")&&e.observe(n);n.querySelectorAll("[data-track-view]").forEach(t=>e.observe(t))}})})});t.observe(document.body,{childList:!0,subtree:!0}),this.observers.add(t)}shouldTrackClick(e){const t=e.tagName.toLowerCase();if("button"===t||"a"===t)return!0;if(e.hasAttribute("data-track")||e.hasAttribute("data-track-click"))return!0;const n=Array.from(e.classList);return["btn","button","cta","submit","checkout","buy","purchase","download"].some(e=>n.some(t=>t.toLowerCase().includes(e)))}shouldTrackFormField(e){return"password"!==e.type&&!e.hasAttribute("data-track-disable")}getFormFields(e){const t=[],n=new FormData(e);for(const[r]of n.entries())t.includes(r)||t.push(r);return t}getScrollDepth(){const e=window.innerHeight,t=document.documentElement.scrollHeight,n=window.pageYOffset||document.documentElement.scrollTop;return Math.round(n/(t-e)*100)}getElementSelector(e){if(e.id)return`#${e.id}`;if(e.className){return`.${Array.from(e.classList).join(".")}`}const t=e.parentElement;if(t){const n=Array.from(t.children).indexOf(e)+1;return`${e.tagName.toLowerCase()}:nth-child(${n})`}return e.tagName.toLowerCase()}getStats(){return{isActive:this.isActive,observers:this.observers.size,listeners:this.listeners.size}}}var r=t.j;export{r as AutoTracking};