@agenus-io/recovery 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* UpselyRecovery - Script global para uso via CDN */
|
|
2
|
-
"use strict";var S=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var G=(o,e)=>{for(var t in e)S(o,t,{get:e[t],enumerable:!0})},H=(o,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of O(e))!$.call(o,n)&&n!==t&&S(o,n,{get:()=>e[n],enumerable:!(i=N(e,n))||i.enumerable});return o};var K=o=>H(S({},"__esModule",{value:!0}),o);var B={};G(B,{autoInitFromScriptTag:()=>F,default:()=>V});module.exports=K(B);var v=class{constructor(e,t=!1){this.storageKey="upsely_session";this.cookieKey="upsely_session_id";this.sessionTimeout=1800*1e3;this.cookieExpirationDays=365;this.debug=!1;this.debug=t,this.sessionData=this.initializeSession(e),this.startActivityTracking()}initializeSession(e){let t=Date.now(),i=this.getStoredSession(),n=this.getCookie(this.cookieKey);if(i&&this.isSessionValid(i))return i.lastActivity=t,this.saveSession(i),n!==i.sessionId&&this.setCookie(this.cookieKey,i.sessionId),i;let s;e?s=e:n?s=n:s=this.generateSessionId();let r=!i&&!n,a={sessionId:s,lastActivity:t,createdAt:i?.createdAt||t,visitCount:i?i.visitCount+1:1,firstVisit:i?.firstVisit||t};return this.saveSession(a),this.setCookie(this.cookieKey,s),this.debug&&console.log("[GetSession] Nova sess\xE3o criada:",{sessionId:s,isFirstVisit:r,visitCount:a.visitCount}),a}generateSessionId(){let e=Date.now(),t=Math.random().toString(36).substring(2,15),i=Math.random().toString(36).substring(2,15);return`session_${e}_${t}${i}`}isSessionValid(e){return Date.now()-e.lastActivity<this.sessionTimeout}saveSession(e){try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(t){this.debug&&console.warn("[GetSession] Erro ao salvar sess\xE3o no localStorage:",t)}}getStoredSession(){try{if(typeof localStorage>"u")return null;let e=localStorage.getItem(this.storageKey);if(!e)return null;let t=JSON.parse(e);return!t.sessionId||!t.lastActivity?null:t}catch(e){return this.debug&&console.warn("[GetSession] Erro ao recuperar sess\xE3o do localStorage:",e),null}}setCookie(e,t){try{if(typeof document>"u")return;let i=new Date;i.setTime(i.getTime()+this.cookieExpirationDays*24*60*60*1e3);let n=`expires=${i.toUTCString()}`;document.cookie=`${e}=${t};${n};path=/;SameSite=Lax`}catch(i){this.debug&&console.warn("[GetSession] Erro ao definir cookie:",i)}}getCookie(e){try{if(typeof document>"u")return null;let t=`${e}=`,i=document.cookie.split(";");for(let n=0;n<i.length;n++){let s=i[n];for(;s.charAt(0)===" ";)s=s.substring(1,s.length);if(s.indexOf(t)===0)return s.substring(t.length,s.length)}return null}catch(t){return this.debug&&console.warn("[GetSession] Erro ao ler cookie:",t),null}}removeCookie(e){try{if(typeof document>"u")return;document.cookie=`${e}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`}catch(t){this.debug&&console.warn("[GetSession] Erro ao remover cookie:",t)}}startActivityTracking(){if(typeof window>"u")return;let e=["mousedown","mousemove","keypress","scroll","touchstart","click"],t=()=>{this.updateLastActivity()},i=0,n=()=>{let s=Date.now();s-i>6e4&&(i=s,t())};e.forEach(s=>{window.addEventListener(s,n,{passive:!0})}),window.addEventListener("focus",t,{passive:!0})}updateLastActivity(){let e=Date.now();this.sessionData.lastActivity=e,this.saveSession(this.sessionData)}renewSession(){if(this.isSessionValid(this.sessionData))this.updateLastActivity();else{let e=this.generateSessionId();this.sessionData=this.initializeSession(e)}}getSessionData(){return this.updateLastActivity(),{...this.sessionData}}getSessionId(){return this.sessionData.sessionId}isActive(){return this.isSessionValid(this.sessionData)}clearSession(){try{typeof localStorage<"u"&&localStorage.removeItem(this.storageKey),this.removeCookie(this.cookieKey),this.debug&&console.log("[GetSession] Sess\xE3o limpa")}catch(e){this.debug&&console.warn("[GetSession] Erro ao limpar sess\xE3o:",e)}}exportSessionData(){return JSON.stringify({session:this.sessionData,isActive:this.isActive(),timeUntilExpiration:this.sessionTimeout-(Date.now()-this.sessionData.lastActivity)},null,2)}};var w=()=>{if(typeof document>"u")return[];let o=document.querySelectorAll("form"),e=[];return o.forEach((t,i)=>{let n={},s=t.id||t.name||`form_${i}`;t.querySelectorAll("input, textarea, select").forEach(a=>{let l=a.name||a.id;if(!l)return;let d;if(a.type==="checkbox")d=a.checked;else if(a.type==="radio"){let c=t.querySelectorAll(`input[type="radio"][name="${l}"]`),m=Array.from(c).find(g=>g.checked);d=m?m.value:null}else if(a.tagName==="SELECT"){let c=a;c.multiple?d=Array.from(c.selectedOptions).map(m=>m.value):d=c.value}else d=a.value;d!=null&&d!==""&&(a.type==="checkbox"||a.type==="radio"||d!=="")&&(n[l]=d)}),Object.keys(n).length>0&&e.push({formId:s,formData:n,formIndex:i})}),e};var T=require("ua-parser-js");function D(){let e=new T.UAParser(navigator.userAgent).getResult();return{id:crypto.randomUUID(),type:e.device.type||"desktop",os:{name:e.os.name||"Unknown",version:e.os.version||""},browser:{name:e.browser.name||"Unknown",version:e.browser.version||""},engine:{name:e.engine.name||"",version:e.engine.version||""},language:navigator.language,screen:{width:window.screen.width,height:window.screen.height,pixel_ratio:window.devicePixelRatio}}}var A="UPSELY";var k=`${A}_FINGERPRINT_V1`;async function x(){if(typeof window>"u")return"";let o=localStorage.getItem(k);if(o)return o;let e=document.createElement("canvas");e.getContext("2d")?.fillText(A,10,50);let i=e.toDataURL(),n="";try{let u=e.getContext("webgl");if(u){let f=u.getExtension("WEBGL_debug_renderer_info");if(f){let M=u.getParameter(f.UNMASKED_VENDOR_WEBGL),P=u.getParameter(f.UNMASKED_RENDERER_WEBGL);n=`${M} ${P}`}}}catch{}let s="";try{s=Array.from(navigator.plugins||[]).map(u=>u.name).join(",")}catch{}let r=new Date().getTimezoneOffset().toString(),a=Intl.DateTimeFormat().resolvedOptions().locale,l=[navigator.userAgent,navigator.language,navigator.platform,navigator.hardwareConcurrency?.toString()||"",navigator.deviceMemory?.toString()||"",screen.width.toString(),screen.height.toString(),screen.colorDepth.toString(),Intl.DateTimeFormat().resolvedOptions().timeZone,r,a,i,window.devicePixelRatio?.toString()||"",navigator.connection?.effectiveType||"",s,n,typeof window.WebGL2RenderingContext<"u"?"webgl2":"no-webgl2"],c=new TextEncoder().encode(l.join("|")),m=await crypto.subtle.digest("SHA-256",c),p=Array.from(new Uint8Array(m)).map(u=>u.toString(16).padStart(2,"0")).join("");return localStorage.setItem(k,p),p}var z="cartData",U=()=>{let o=localStorage.getItem(z);return o?JSON.parse(o):null};var L=async({eventData:o,config:e,sessionId:t,version:i,scriptUrl:n})=>{let s=D(),r=await x(),a=U(),l={sessionId:t??"",timestamp:Date.now(),fingerprint:r,user_agent:navigator.userAgent,page:{url:window.location.href,title:document.title,referrer:document.referrer,path:window.location.pathname,hostname:window.location.hostname},data:{...o,cart_data:a},device:s,meta:{version:i,recovery_source:"upsely",environment:"production",script_url:n??""},query_params:(()=>{let c=window.location.search;return!c||c.length<=1?{}:c.substring(1).split("&").reduce((g,p)=>{if(!p)return g;let[u,f=""]=p.split("=");return u&&(g[decodeURIComponent(u)]=decodeURIComponent(f)),g},{})})()},d=`${e.apiEndpoint}/webhooks/abandoned-cart`;e.debug&&console.log("Sending event:",l);try{if(navigator.sendBeacon&&(console.log("Sending beacon:",JSON.stringify(l)),navigator.sendBeacon(d,JSON.stringify(l))))return{success:!0,event_id:`beacon_${Date.now()}`,timestamp:Date.now()};let c=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l),keepalive:!0});if(!c.ok)throw new Error(`HTTP ${c.status}: ${c.statusText}`);return{success:!0,event_id:(await c.json()).event_id||`fetch_${Date.now()}`,timestamp:Date.now()}}catch(c){return e.debug&&console.error("Error sending event:",c),{success:!1,event_id:`error_${Date.now()}`,timestamp:Date.now()}}};var E=30*1e3,C=120*1e3,R=120*1e3,y=class{constructor({config:e,sessionId:t,version:i,scriptUrl:n}){this.hasInteracted=!1;this.hasSent=!1;this.hasSubmitted=!1;this.pageStartTime=Date.now();this.inactivityTimer=null;this.visibilityTimer=null;this.formInteractionListeners=[];this.unloadListeners=[];this.activityListeners=[];this.config=e,this.sessionId=t,this.version=i,this.scriptUrl=n,this.initialize()}initialize(){typeof window>"u"||typeof document>"u"||(this.trackFormInteractions(),this.setupActivityTracking(),this.setupUnloadListeners(),this.config.debug&&console.log("[FormAbandonment] Sistema inicializado"))}canSendAbandonment(){if(this.hasSubmitted||this.hasSent)return!1;let t=Date.now()-this.pageStartTime;if(t<E)return this.config.debug&&console.log(`[FormAbandonment] Tempo na p\xE1gina insuficiente: ${Math.round(t/1e3)}s < ${E/1e3}s`),!1;if(!this.hasInteracted)return this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio n\xE3o interagiu com formul\xE1rio"),!1;let i=w();return i.length===0?(this.config.debug&&console.log("[FormAbandonment] Nenhum dado de formul\xE1rio encontrado"),!1):i.some(s=>Object.values(s.formData).some(r=>r==null?!1:typeof r=="string"?r.trim().length>0:typeof r=="boolean"?r===!0:Array.isArray(r)?r.length>0:!0))?!0:(this.config.debug&&console.log("[FormAbandonment] Dados m\xEDnimos n\xE3o preenchidos"),!1)}updateActivity(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),Date.now()-this.pageStartTime>=E&&(this.inactivityTimer=setTimeout(()=>{this.sendAbandonment()},C),this.config.debug&&console.log(`[FormAbandonment] Timer de inatividade iniciado (${C/1e3}s)`))}trackFormInteractions(){document.querySelectorAll("form").forEach(t=>{let i=()=>{this.hasInteracted=!0,this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio interagiu com formul\xE1rio")},n=()=>{this.hasInteracted=!0,this.updateActivity()},s=t.querySelectorAll("input, textarea, select");s.forEach(r=>{r.addEventListener("focus",i,{passive:!0}),r.addEventListener("change",n,{passive:!0}),r.addEventListener("input",n,{passive:!0})}),this.formInteractionListeners.push(()=>{s.forEach(r=>{r.removeEventListener("focus",i),r.removeEventListener("change",n),r.removeEventListener("input",n)})})})}setupActivityTracking(){let e=["mousedown","keydown","scroll","input","touchstart"],t=()=>{this.updateActivity()};e.forEach(i=>{document.addEventListener(i,t,{passive:!0})}),this.activityListeners.push(()=>{e.forEach(i=>{document.removeEventListener(i,t)})})}handleVisibilityChange(){document.visibilityState==="hidden"?(this.visibilityTimer&&clearTimeout(this.visibilityTimer),this.visibilityTimer=setTimeout(()=>{document.visibilityState==="hidden"&&this.sendAbandonment()},R),this.config.debug&&console.log(`[FormAbandonment] Aba oculta - timer iniciado (${R/1e3}s)`)):(this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Aba vis\xEDvel novamente - timer cancelado"))}handleBeforeUnload(){this.canSendAbandonment()&&this.sendAbandonment()}setupUnloadListeners(){let e=()=>{this.handleBeforeUnload()},t=()=>{this.handleVisibilityChange()},i=()=>{this.handleAbandonment()};window.addEventListener("beforeunload",e),document.addEventListener("visibilitychange",t),window.addEventListener("pagehide",i),this.unloadListeners.push(()=>{window.removeEventListener("beforeunload",e),document.removeEventListener("visibilitychange",t),window.removeEventListener("pagehide",i)})}sendAbandonment(){if(!this.canSendAbandonment())return;this.hasSent=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null);let e=w(),t={event_type:"form_abandonment",forms:e.map(i=>({form_id:i.formId,form_index:i.formIndex,fields:i.formData,field_count:Object.keys(i.formData).length})),total_forms:e.length,timestamp:Date.now()};this.config.debug&&console.log("[FormAbandonment] Enviando evento de abandono:",t),this.sendAbandonmentEvent(t)}handleAbandonment(){this.canSendAbandonment()&&this.sendAbandonment()}markAsSubmitted(){this.hasSubmitted=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.config.debug&&console.log("[FormAbandonment] Formul\xE1rio marcado como submetido")}sendAbandonmentEvent(e){L({eventData:e,config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:this.scriptUrl}).catch(t=>{this.config.debug&&console.error("[FormAbandonment] Erro ao enviar evento:",t)})}destroy(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.formInteractionListeners.forEach(e=>e()),this.unloadListeners.forEach(e=>e()),this.activityListeners.forEach(e=>e()),this.formInteractionListeners=[],this.unloadListeners=[],this.activityListeners=[],this.config.debug&&console.log("[FormAbandonment] Sistema destru\xEDdo")}};var I=class{constructor(e){this.version="1.0.0";if(!e.apiEndpoint)throw new Error("apiEndpoint \xE9 obrigat\xF3rio");this.config={debug:!1,version:this.version,...e},this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId(),this.initialize()}async initialize(){if(typeof window<"u"&&typeof document<"u")try{let e=this.getScriptUrl();this.formAbandonment=new y({config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:e}),this.config.debug&&console.log("[Initialization] Sistema de abandono de formul\xE1rio inicializado")}catch(e){this.config.debug&&console.error("[Initialization] Erro ao inicializar sistema de abandono:",e)}}getScriptUrl(){if(typeof document>"u")return;let e=document.getElementsByTagName("script");for(let i=0;i<e.length;i++){let n=e[i];if(n.src&&n.src.includes("upsely"))return n.src}let t=document.currentScript;if(t?.src)return t.src}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}getVersion(){return this.version}getSessionId(){return this.sessionId=this.sessionManager.getSessionId(),this.sessionId}getSessionData(){return this.sessionManager.getSessionData()}isSessionActive(){return this.sessionManager.isActive()}updateSessionActivity(){this.sessionManager.updateLastActivity()}renewSession(){this.sessionManager.renewSession(),this.sessionId=this.sessionManager.getSessionId()}clearSession(){this.sessionManager.clearSession(),this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId()}exportSessionData(){return this.sessionManager.exportSessionData()}destroyFormAbandonment(){this.formAbandonment&&(this.formAbandonment.destroy(),this.formAbandonment=void 0)}},b=I;var _=o=>({apiEndpoint:o.getAttribute("data-api-endpoint")||void 0,apiKey:o.getAttribute("data-api-key")||void 0,debug:o.getAttribute("data-debug")==="true",timeout:o.getAttribute("data-timeout")?Number(o.getAttribute("data-timeout")):5e3});var V=b,h={apiEndpoint:"https://api-upsely-webhook-dev.up.railway.app",debug:!0,timeout:5e3,version:"1.0.0"};async function F(){if(!(typeof window>"u"||typeof document>"u"))try{let o=document.currentScript;if(o){let e=_(o);return new b({apiEndpoint:e.apiEndpoint||h.apiEndpoint,debug:e.debug||h.debug,timeout:e.timeout||h.timeout,version:e.version||h.version,apiKey:e.apiKey||h.apiKey})}}catch(o){console.warn("[GomarkePixel] Erro no autoInitFromScriptTag:",o)}}typeof window<"u"&&(window.UpselyRecovery=b,(async()=>{let o=await F();o&&(window.upselyRecovery=o)})());0&&(module.exports={autoInitFromScriptTag});
|
|
2
|
+
"use strict";var S=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var G=(o,e)=>{for(var t in e)S(o,t,{get:e[t],enumerable:!0})},H=(o,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of O(e))!$.call(o,n)&&n!==t&&S(o,n,{get:()=>e[n],enumerable:!(i=N(e,n))||i.enumerable});return o};var K=o=>H(S({},"__esModule",{value:!0}),o);var B={};G(B,{autoInitFromScriptTag:()=>F,default:()=>V});module.exports=K(B);var v=class{constructor(e,t=!1){this.storageKey="upsely_session";this.cookieKey="upsely_session_id";this.sessionTimeout=1800*1e3;this.cookieExpirationDays=365;this.debug=!1;this.debug=t,this.sessionData=this.initializeSession(e),this.startActivityTracking()}initializeSession(e){let t=Date.now(),i=this.getStoredSession(),n=this.getCookie(this.cookieKey);if(i&&this.isSessionValid(i))return i.lastActivity=t,this.saveSession(i),n!==i.sessionId&&this.setCookie(this.cookieKey,i.sessionId),i;let s;e?s=e:n?s=n:s=this.generateSessionId();let r=!i&&!n,a={sessionId:s,lastActivity:t,createdAt:i?.createdAt||t,visitCount:i?i.visitCount+1:1,firstVisit:i?.firstVisit||t};return this.saveSession(a),this.setCookie(this.cookieKey,s),this.debug&&console.log("[GetSession] Nova sess\xE3o criada:",{sessionId:s,isFirstVisit:r,visitCount:a.visitCount}),a}generateSessionId(){let e=Date.now(),t=Math.random().toString(36).substring(2,15),i=Math.random().toString(36).substring(2,15);return`session_${e}_${t}${i}`}isSessionValid(e){return Date.now()-e.lastActivity<this.sessionTimeout}saveSession(e){try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(t){this.debug&&console.warn("[GetSession] Erro ao salvar sess\xE3o no localStorage:",t)}}getStoredSession(){try{if(typeof localStorage>"u")return null;let e=localStorage.getItem(this.storageKey);if(!e)return null;let t=JSON.parse(e);return!t.sessionId||!t.lastActivity?null:t}catch(e){return this.debug&&console.warn("[GetSession] Erro ao recuperar sess\xE3o do localStorage:",e),null}}setCookie(e,t){try{if(typeof document>"u")return;let i=new Date;i.setTime(i.getTime()+this.cookieExpirationDays*24*60*60*1e3);let n=`expires=${i.toUTCString()}`;document.cookie=`${e}=${t};${n};path=/;SameSite=Lax`}catch(i){this.debug&&console.warn("[GetSession] Erro ao definir cookie:",i)}}getCookie(e){try{if(typeof document>"u")return null;let t=`${e}=`,i=document.cookie.split(";");for(let n=0;n<i.length;n++){let s=i[n];for(;s.charAt(0)===" ";)s=s.substring(1,s.length);if(s.indexOf(t)===0)return s.substring(t.length,s.length)}return null}catch(t){return this.debug&&console.warn("[GetSession] Erro ao ler cookie:",t),null}}removeCookie(e){try{if(typeof document>"u")return;document.cookie=`${e}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`}catch(t){this.debug&&console.warn("[GetSession] Erro ao remover cookie:",t)}}startActivityTracking(){if(typeof window>"u")return;let e=["mousedown","mousemove","keypress","scroll","touchstart","click"],t=()=>{this.updateLastActivity()},i=0,n=()=>{let s=Date.now();s-i>6e4&&(i=s,t())};e.forEach(s=>{window.addEventListener(s,n,{passive:!0})}),window.addEventListener("focus",t,{passive:!0})}updateLastActivity(){let e=Date.now();this.sessionData.lastActivity=e,this.saveSession(this.sessionData)}renewSession(){if(this.isSessionValid(this.sessionData))this.updateLastActivity();else{let e=this.generateSessionId();this.sessionData=this.initializeSession(e)}}getSessionData(){return this.updateLastActivity(),{...this.sessionData}}getSessionId(){return this.sessionData.sessionId}isActive(){return this.isSessionValid(this.sessionData)}clearSession(){try{typeof localStorage<"u"&&localStorage.removeItem(this.storageKey),this.removeCookie(this.cookieKey),this.debug&&console.log("[GetSession] Sess\xE3o limpa")}catch(e){this.debug&&console.warn("[GetSession] Erro ao limpar sess\xE3o:",e)}}exportSessionData(){return JSON.stringify({session:this.sessionData,isActive:this.isActive(),timeUntilExpiration:this.sessionTimeout-(Date.now()-this.sessionData.lastActivity)},null,2)}};var w=()=>{if(typeof document>"u")return[];let o=document.querySelectorAll("form"),e=[];return o.forEach((t,i)=>{let n={},s=t.id||t.name||`form_${i}`;t.querySelectorAll("input, textarea, select").forEach(a=>{let l=a.name||a.id;if(!l)return;let d;if(a.type==="checkbox")d=a.checked;else if(a.type==="radio"){let c=t.querySelectorAll(`input[type="radio"][name="${l}"]`),m=Array.from(c).find(g=>g.checked);d=m?m.value:null}else if(a.tagName==="SELECT"){let c=a;c.multiple?d=Array.from(c.selectedOptions).map(m=>m.value):d=c.value}else d=a.value;d!=null&&d!==""&&(a.type==="checkbox"||a.type==="radio"||d!=="")&&(n[l]=d)}),Object.keys(n).length>0&&e.push({formId:s,formData:n,formIndex:i})}),e};var T=require("ua-parser-js");function D(){let e=new T.UAParser(navigator.userAgent).getResult();return{id:crypto.randomUUID(),type:e.device.type||"desktop",os:{name:e.os.name||"Unknown",version:e.os.version||""},browser:{name:e.browser.name||"Unknown",version:e.browser.version||""},engine:{name:e.engine.name||"",version:e.engine.version||""},language:navigator.language,screen:{width:window.screen.width,height:window.screen.height,pixel_ratio:window.devicePixelRatio}}}var A="UPSELY";var k=`${A}_FINGERPRINT_V1`;async function x(){if(typeof window>"u")return"";let o=localStorage.getItem(k);if(o)return o;let e=document.createElement("canvas");e.getContext("2d")?.fillText(A,10,50);let i=e.toDataURL(),n="";try{let u=e.getContext("webgl");if(u){let f=u.getExtension("WEBGL_debug_renderer_info");if(f){let M=u.getParameter(f.UNMASKED_VENDOR_WEBGL),P=u.getParameter(f.UNMASKED_RENDERER_WEBGL);n=`${M} ${P}`}}}catch{}let s="";try{s=Array.from(navigator.plugins||[]).map(u=>u.name).join(",")}catch{}let r=new Date().getTimezoneOffset().toString(),a=Intl.DateTimeFormat().resolvedOptions().locale,l=[navigator.userAgent,navigator.language,navigator.platform,navigator.hardwareConcurrency?.toString()||"",navigator.deviceMemory?.toString()||"",screen.width.toString(),screen.height.toString(),screen.colorDepth.toString(),Intl.DateTimeFormat().resolvedOptions().timeZone,r,a,i,window.devicePixelRatio?.toString()||"",navigator.connection?.effectiveType||"",s,n,typeof window.WebGL2RenderingContext<"u"?"webgl2":"no-webgl2"],c=new TextEncoder().encode(l.join("|")),m=await crypto.subtle.digest("SHA-256",c),p=Array.from(new Uint8Array(m)).map(u=>u.toString(16).padStart(2,"0")).join("");return localStorage.setItem(k,p),p}var z="cartData",U=()=>{let o=localStorage.getItem(z);return o?JSON.parse(o):null};var L=async({eventData:o,config:e,sessionId:t,version:i,scriptUrl:n})=>{let s=D(),r=await x(),a=U(),l={sessionId:t??"",timestamp:Date.now(),fingerprint:r,user_agent:navigator.userAgent,page:{url:window.location.href,title:document.title,referrer:document.referrer,path:window.location.pathname,hostname:window.location.hostname},data:{...o,cart_data:a},device:s,meta:{version:i,recovery_source:"upsely",environment:"production",script_url:n??""},query_params:(()=>{let c=window.location.search;return!c||c.length<=1?{}:c.substring(1).split("&").reduce((g,p)=>{if(!p)return g;let[u,f=""]=p.split("=");return u&&(g[decodeURIComponent(u)]=decodeURIComponent(f)),g},{})})()},d=`${e.apiEndpoint}/webhooks/abandoned-cart`;e.debug&&console.log("Sending event:",l);try{if(navigator.sendBeacon&&(console.log("Sending beacon:",JSON.stringify(l)),navigator.sendBeacon(d,JSON.stringify(l))))return{success:!0,event_id:`beacon_${Date.now()}`,timestamp:Date.now()};let c=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l),keepalive:!0});if(!c.ok)throw new Error(`HTTP ${c.status}: ${c.statusText}`);return{success:!0,event_id:(await c.json()).event_id||`fetch_${Date.now()}`,timestamp:Date.now()}}catch(c){return e.debug&&console.error("Error sending event:",c),{success:!1,event_id:`error_${Date.now()}`,timestamp:Date.now()}}};var E=5*1e3,C=120*1e3,R=120*1e3,y=class{constructor({config:e,sessionId:t,version:i,scriptUrl:n}){this.hasInteracted=!1;this.hasSent=!1;this.hasSubmitted=!1;this.pageStartTime=Date.now();this.inactivityTimer=null;this.visibilityTimer=null;this.formInteractionListeners=[];this.unloadListeners=[];this.activityListeners=[];this.config=e,this.sessionId=t,this.version=i,this.scriptUrl=n,this.initialize()}initialize(){typeof window>"u"||typeof document>"u"||(this.trackFormInteractions(),this.setupActivityTracking(),this.setupUnloadListeners(),this.config.debug&&console.log("[FormAbandonment] Sistema inicializado"))}canSendAbandonment(){if(this.hasSubmitted||this.hasSent)return!1;let t=Date.now()-this.pageStartTime;if(t<E)return this.config.debug&&console.log(`[FormAbandonment] Tempo na p\xE1gina insuficiente: ${Math.round(t/1e3)}s < ${E/1e3}s`),!1;if(!this.hasInteracted)return this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio n\xE3o interagiu com formul\xE1rio"),!1;let i=w();return i.length===0?(this.config.debug&&console.log("[FormAbandonment] Nenhum dado de formul\xE1rio encontrado"),!1):i.some(s=>Object.values(s.formData).some(r=>r==null?!1:typeof r=="string"?r.trim().length>0:typeof r=="boolean"?r===!0:Array.isArray(r)?r.length>0:!0))?!0:(this.config.debug&&console.log("[FormAbandonment] Dados m\xEDnimos n\xE3o preenchidos"),!1)}updateActivity(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),Date.now()-this.pageStartTime>=E&&(this.inactivityTimer=setTimeout(()=>{this.sendAbandonment()},C),this.config.debug&&console.log(`[FormAbandonment] Timer de inatividade iniciado (${C/1e3}s)`))}trackFormInteractions(){document.querySelectorAll("form").forEach(t=>{let i=()=>{this.hasInteracted=!0,this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio interagiu com formul\xE1rio")},n=()=>{this.hasInteracted=!0,this.updateActivity()},s=t.querySelectorAll("input, textarea, select");s.forEach(r=>{r.addEventListener("focus",i,{passive:!0}),r.addEventListener("change",n,{passive:!0}),r.addEventListener("input",n,{passive:!0})}),this.formInteractionListeners.push(()=>{s.forEach(r=>{r.removeEventListener("focus",i),r.removeEventListener("change",n),r.removeEventListener("input",n)})})})}setupActivityTracking(){let e=["mousedown","keydown","scroll","input","touchstart"],t=()=>{this.updateActivity()};e.forEach(i=>{document.addEventListener(i,t,{passive:!0})}),this.activityListeners.push(()=>{e.forEach(i=>{document.removeEventListener(i,t)})})}handleVisibilityChange(){document.visibilityState==="hidden"?(this.visibilityTimer&&clearTimeout(this.visibilityTimer),this.visibilityTimer=setTimeout(()=>{document.visibilityState==="hidden"&&this.sendAbandonment()},R),this.config.debug&&console.log(`[FormAbandonment] Aba oculta - timer iniciado (${R/1e3}s)`)):(this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Aba vis\xEDvel novamente - timer cancelado"))}handleBeforeUnload(){this.canSendAbandonment()&&this.sendAbandonment()}setupUnloadListeners(){let e=()=>{this.handleBeforeUnload()},t=()=>{this.handleVisibilityChange()},i=()=>{this.handleAbandonment()};window.addEventListener("beforeunload",e),document.addEventListener("visibilitychange",t),window.addEventListener("pagehide",i),this.unloadListeners.push(()=>{window.removeEventListener("beforeunload",e),document.removeEventListener("visibilitychange",t),window.removeEventListener("pagehide",i)})}sendAbandonment(){if(!this.canSendAbandonment())return;this.hasSent=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null);let e=w(),t={event_type:"form_abandonment",forms:e.map(i=>({form_id:i.formId,form_index:i.formIndex,fields:i.formData,field_count:Object.keys(i.formData).length})),total_forms:e.length,timestamp:Date.now()};this.config.debug&&console.log("[FormAbandonment] Enviando evento de abandono:",t),this.sendAbandonmentEvent(t)}handleAbandonment(){this.canSendAbandonment()&&this.sendAbandonment()}markAsSubmitted(){this.hasSubmitted=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.config.debug&&console.log("[FormAbandonment] Formul\xE1rio marcado como submetido")}sendAbandonmentEvent(e){L({eventData:e,config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:this.scriptUrl}).catch(t=>{this.config.debug&&console.error("[FormAbandonment] Erro ao enviar evento:",t)})}destroy(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.formInteractionListeners.forEach(e=>e()),this.unloadListeners.forEach(e=>e()),this.activityListeners.forEach(e=>e()),this.formInteractionListeners=[],this.unloadListeners=[],this.activityListeners=[],this.config.debug&&console.log("[FormAbandonment] Sistema destru\xEDdo")}};var I=class{constructor(e){this.version="1.0.0";if(!e.apiEndpoint)throw new Error("apiEndpoint \xE9 obrigat\xF3rio");this.config={debug:!1,version:this.version,...e},this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId(),this.initialize()}async initialize(){if(typeof window<"u"&&typeof document<"u")try{let e=this.getScriptUrl();this.formAbandonment=new y({config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:e}),this.config.debug&&console.log("[Initialization] Sistema de abandono de formul\xE1rio inicializado")}catch(e){this.config.debug&&console.error("[Initialization] Erro ao inicializar sistema de abandono:",e)}}getScriptUrl(){if(typeof document>"u")return;let e=document.getElementsByTagName("script");for(let i=0;i<e.length;i++){let n=e[i];if(n.src&&n.src.includes("upsely"))return n.src}let t=document.currentScript;if(t?.src)return t.src}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}getVersion(){return this.version}getSessionId(){return this.sessionId=this.sessionManager.getSessionId(),this.sessionId}getSessionData(){return this.sessionManager.getSessionData()}isSessionActive(){return this.sessionManager.isActive()}updateSessionActivity(){this.sessionManager.updateLastActivity()}renewSession(){this.sessionManager.renewSession(),this.sessionId=this.sessionManager.getSessionId()}clearSession(){this.sessionManager.clearSession(),this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId()}exportSessionData(){return this.sessionManager.exportSessionData()}destroyFormAbandonment(){this.formAbandonment&&(this.formAbandonment.destroy(),this.formAbandonment=void 0)}},b=I;var _=o=>({apiEndpoint:o.getAttribute("data-api-endpoint")||void 0,apiKey:o.getAttribute("data-api-key")||void 0,debug:o.getAttribute("data-debug")==="true",timeout:o.getAttribute("data-timeout")?Number(o.getAttribute("data-timeout")):5e3});var V=b,h={apiEndpoint:"https://api-upsely-webhook-dev.up.railway.app",debug:!0,timeout:5e3,version:"1.0.0"};async function F(){if(!(typeof window>"u"||typeof document>"u"))try{let o=document.currentScript;if(o){let e=_(o);return new b({apiEndpoint:e.apiEndpoint||h.apiEndpoint,debug:e.debug||h.debug,timeout:e.timeout||h.timeout,version:e.version||h.version,apiKey:e.apiKey||h.apiKey})}}catch(o){console.warn("[GomarkePixel] Erro no autoInitFromScriptTag:",o)}}typeof window<"u"&&(window.UpselyRecovery=b,(async()=>{let o=await F();o&&(window.upselyRecovery=o)})());0&&(module.exports={autoInitFromScriptTag});
|
|
3
3
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils/getSession.ts","../src/utils/getFormData.ts","../src/utils/getDeviceInfo.ts","../src/config.ts","../src/utils/getFingerprint.ts","../src/utils/getCartData.ts","../src/utils/sendEvent.tsx","../src/utils/formAbandonment.ts","../src/init.ts","../src/utils/parseConfigFromScriptTag.ts"],"sourcesContent":["// Exportação para uso em módulos\nimport UpselyRecovery from './init';\nimport { UpselyRecoveryConfig } from './types';\nimport { parseConfigFromScriptTag } from './utils/parseConfigFromScriptTag';\n\nexport default UpselyRecovery;\n\nconst defaultConfig: UpselyRecoveryConfig = {\n apiEndpoint: 'https://api-upsely-webhook-dev.up.railway.app',\n debug: true,\n timeout: 5000,\n version: '1.0.0',\n};\n\n// Função para auto-inicialização via script tag\nexport async function autoInitFromScriptTag(): Promise<\n UpselyRecovery | undefined\n> {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n try {\n const scriptTag = document.currentScript as HTMLScriptElement | null;\n if (scriptTag) {\n const config = parseConfigFromScriptTag(scriptTag);\n return new UpselyRecovery({\n apiEndpoint: config.apiEndpoint || defaultConfig.apiEndpoint,\n debug: config.debug || defaultConfig.debug,\n timeout: config.timeout || defaultConfig.timeout,\n version: config.version || defaultConfig.version,\n apiKey: config.apiKey || defaultConfig.apiKey,\n });\n }\n } catch (err) {\n console.warn('[GomarkePixel] Erro no autoInitFromScriptTag:', err);\n }\n}\n\n// Para uso global (IIFE) - versão corrigida\nif (typeof window !== 'undefined') {\n // Expor a classe GomarkePixel\n (\n window as unknown as { UpselyRecovery: typeof UpselyRecovery }\n ).UpselyRecovery = UpselyRecovery;\n\n // Auto-inicialização se configurado via script tag\n // Usando IIFE assíncrona para evitar top-level await\n (async () => {\n const autoPixel = await autoInitFromScriptTag();\n if (autoPixel) {\n (window as unknown as { upselyRecovery: UpselyRecovery }).upselyRecovery =\n autoPixel;\n }\n })();\n}\n","export interface ISessionData {\n sessionId: string;\n lastActivity: number;\n createdAt: number;\n visitCount: number;\n firstVisit: number;\n}\n\n/**\n * Gerenciador de sessão persistente com suporte a cookies e localStorage\n */\nexport class GetSession {\n private sessionData: ISessionData;\n private storageKey: string = 'upsely_session';\n private cookieKey: string = 'upsely_session_id';\n private sessionTimeout: number = 30 * 60 * 1000; // 30 minutos\n private cookieExpirationDays: number = 365; // 1 ano para cookies\n private debug: boolean = false;\n\n constructor(sessionId?: string, debug: boolean = false) {\n this.debug = debug;\n this.sessionData = this.initializeSession(sessionId);\n this.startActivityTracking();\n }\n\n /**\n * Inicializa ou recupera dados da sessão\n */\n private initializeSession(providedSessionId?: string): ISessionData {\n const now = Date.now();\n\n // Tenta recuperar sessão do localStorage\n const stored = this.getStoredSession();\n\n // Tenta recuperar sessionId do cookie\n const cookieSessionId = this.getCookie(this.cookieKey);\n\n if (stored && this.isSessionValid(stored)) {\n // Sessão existente válida - atualiza última atividade\n stored.lastActivity = now;\n this.saveSession(stored);\n\n // Garante que o cookie também está atualizado\n if (cookieSessionId !== stored.sessionId) {\n this.setCookie(this.cookieKey, stored.sessionId);\n }\n\n return stored;\n }\n\n // Determina o sessionId a usar\n let finalSessionId: string;\n\n if (providedSessionId) {\n finalSessionId = providedSessionId;\n } else if (cookieSessionId) {\n finalSessionId = cookieSessionId;\n } else {\n finalSessionId = this.generateSessionId();\n }\n\n // Nova sessão ou sessão expirada\n const isFirstVisit = !stored && !cookieSessionId;\n const newSession: ISessionData = {\n sessionId: finalSessionId,\n lastActivity: now,\n createdAt: stored?.createdAt || now,\n visitCount: stored ? stored.visitCount + 1 : 1,\n firstVisit: stored?.firstVisit || now,\n };\n\n this.saveSession(newSession);\n this.setCookie(this.cookieKey, finalSessionId);\n\n if (this.debug) {\n console.log('[GetSession] Nova sessão criada:', {\n sessionId: finalSessionId,\n isFirstVisit,\n visitCount: newSession.visitCount,\n });\n }\n\n return newSession;\n }\n\n /**\n * Gera um novo sessionId único\n */\n private generateSessionId(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 15);\n const random2 = Math.random().toString(36).substring(2, 15);\n return `session_${timestamp}_${random}${random2}`;\n }\n\n /**\n * Verifica se a sessão ainda é válida\n */\n private isSessionValid(session: ISessionData): boolean {\n const now = Date.now();\n return now - session.lastActivity < this.sessionTimeout;\n }\n\n /**\n * Salva dados da sessão no localStorage\n */\n private saveSession(session: ISessionData): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(this.storageKey, JSON.stringify(session));\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\n '[GetSession] Erro ao salvar sessão no localStorage:',\n error\n );\n }\n }\n }\n\n /**\n * Recupera dados da sessão do localStorage\n */\n private getStoredSession(): ISessionData | null {\n try {\n if (typeof localStorage === 'undefined') {\n return null;\n }\n const stored = localStorage.getItem(this.storageKey);\n if (!stored) return null;\n\n const parsed = JSON.parse(stored) as ISessionData;\n\n // Valida estrutura básica\n if (!parsed.sessionId || !parsed.lastActivity) {\n return null;\n }\n\n return parsed;\n } catch (error) {\n if (this.debug) {\n console.warn(\n '[GetSession] Erro ao recuperar sessão do localStorage:',\n error\n );\n }\n return null;\n }\n }\n\n /**\n * Define um cookie\n */\n private setCookie(name: string, value: string): void {\n try {\n if (typeof document === 'undefined') return;\n\n const expirationDate = new Date();\n expirationDate.setTime(\n expirationDate.getTime() +\n this.cookieExpirationDays * 24 * 60 * 60 * 1000\n );\n\n const expires = `expires=${expirationDate.toUTCString()}`;\n document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao definir cookie:', error);\n }\n }\n }\n\n /**\n * Obtém um cookie\n */\n private getCookie(name: string): string | null {\n try {\n if (typeof document === 'undefined') return null;\n\n const nameEQ = `${name}=`;\n const ca = document.cookie.split(';');\n\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n return null;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao ler cookie:', error);\n }\n return null;\n }\n }\n\n /**\n * Remove um cookie\n */\n private removeCookie(name: string): void {\n try {\n if (typeof document === 'undefined') return;\n document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao remover cookie:', error);\n }\n }\n }\n\n /**\n * Inicia o rastreamento de atividade para renovar sessão automaticamente\n */\n private startActivityTracking(): void {\n if (typeof window === 'undefined') return;\n\n // Atualiza atividade em eventos do usuário\n const events = [\n 'mousedown',\n 'mousemove',\n 'keypress',\n 'scroll',\n 'touchstart',\n 'click',\n ];\n const updateActivity = () => {\n this.updateLastActivity();\n };\n\n // Throttle para não atualizar muito frequentemente\n let lastUpdate = 0;\n const throttledUpdate = () => {\n const now = Date.now();\n if (now - lastUpdate > 60000) {\n // Atualiza no máximo a cada 1 minuto\n lastUpdate = now;\n updateActivity();\n }\n };\n\n events.forEach(event => {\n window.addEventListener(event, throttledUpdate, { passive: true });\n });\n\n // Atualiza ao focar na janela\n window.addEventListener('focus', updateActivity, { passive: true });\n }\n\n /**\n * Atualiza a última atividade da sessão\n */\n public updateLastActivity(): void {\n const now = Date.now();\n this.sessionData.lastActivity = now;\n this.saveSession(this.sessionData);\n }\n\n /**\n * Renova a sessão (cria nova se expirada)\n */\n public renewSession(): void {\n if (!this.isSessionValid(this.sessionData)) {\n const newSessionId = this.generateSessionId();\n this.sessionData = this.initializeSession(newSessionId);\n } else {\n this.updateLastActivity();\n }\n }\n\n /**\n * Obtém dados da sessão\n */\n public getSessionData(): ISessionData {\n // Atualiza última atividade antes de retornar\n this.updateLastActivity();\n return { ...this.sessionData };\n }\n\n /**\n * Obtém apenas o sessionId\n */\n public getSessionId(): string {\n return this.sessionData.sessionId;\n }\n\n /**\n * Verifica se a sessão está ativa\n */\n public isActive(): boolean {\n return this.isSessionValid(this.sessionData);\n }\n\n /**\n * Limpa dados da sessão\n */\n public clearSession(): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(this.storageKey);\n }\n this.removeCookie(this.cookieKey);\n\n if (this.debug) {\n console.log('[GetSession] Sessão limpa');\n }\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao limpar sessão:', error);\n }\n }\n }\n\n /**\n * Exporta dados da sessão\n */\n public exportSessionData(): string {\n return JSON.stringify(\n {\n session: this.sessionData,\n isActive: this.isActive(),\n timeUntilExpiration:\n this.sessionTimeout - (Date.now() - this.sessionData.lastActivity),\n },\n null,\n 2\n );\n }\n}\n","/**\n * Utilitário para capturar dados de todos os formulários na página\n */\n\nexport interface FormDataResult {\n formId: string;\n formData: Record<string, unknown>;\n formIndex: number;\n}\n\n/**\n * Captura dados de todos os formulários na página\n * @returns Array com dados de cada formulário encontrado\n */\nexport const getFormData = (): FormDataResult[] => {\n if (typeof document === 'undefined') {\n return [];\n }\n\n const forms = document.querySelectorAll('form');\n const results: FormDataResult[] = [];\n\n forms.forEach((form, index) => {\n const formData: Record<string, unknown> = {};\n const formId = form.id || form.name || `form_${index}`;\n\n // Captura todos os campos do formulário\n const inputs = form.querySelectorAll<HTMLInputElement>(\n 'input, textarea, select'\n );\n\n inputs.forEach(field => {\n const name = field.name || field.id;\n if (!name) return;\n\n let value: unknown;\n\n // Trata diferentes tipos de campos\n if (field.type === 'checkbox') {\n value = (field as HTMLInputElement).checked;\n } else if (field.type === 'radio') {\n // Para radio, pega o valor do radio selecionado no grupo\n const radioGroup = form.querySelectorAll<HTMLInputElement>(\n `input[type=\"radio\"][name=\"${name}\"]`\n );\n const checked = Array.from(radioGroup).find(r => r.checked);\n value = checked ? checked.value : null;\n } else if (field.tagName === 'SELECT') {\n const select = field as unknown as HTMLSelectElement;\n if (select.multiple) {\n // Para select múltiplo, retorna array de valores\n value = Array.from(select.selectedOptions).map(\n option => option.value\n );\n } else {\n value = select.value;\n }\n } else {\n value = (field as HTMLInputElement | HTMLTextAreaElement).value;\n }\n\n // Só adiciona se o campo tiver valor ou for checkbox/radio\n if (\n value !== null &&\n value !== undefined &&\n value !== '' &&\n (field.type === 'checkbox' || field.type === 'radio' || value !== '')\n ) {\n formData[name] = value;\n }\n });\n\n // Só adiciona o formulário se tiver dados\n if (Object.keys(formData).length > 0) {\n results.push({\n formId,\n formData,\n formIndex: index,\n });\n }\n });\n\n return results;\n};\n","import { Event } from '@/types';\nimport { UAParser } from 'ua-parser-js';\n\nexport function getDeviceInfo(): Event['device'] {\n const parser = new UAParser(navigator.userAgent);\n const result = parser.getResult();\n\n return {\n id: crypto.randomUUID(),\n type: (result.device.type || 'desktop') as Event['device']['type'], // 'mobile' | 'tablet' | 'desktop' | 'smarttv' | 'wearable' | 'embedded'\n os: {\n name: (result.os.name || 'Unknown') as Event['device']['os']['name'],\n version: result.os.version || '',\n },\n browser: {\n name: (result.browser.name || 'Unknown') as\n | Event['device']['browser']['name']\n | 'Other',\n version: (result.browser.version ||\n '') as Event['device']['browser']['version'],\n },\n engine: {\n name: result.engine.name || '',\n version: result.engine.version || '',\n },\n language: navigator.language,\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n pixel_ratio: window.devicePixelRatio,\n },\n };\n}\n","export const APP_NAME = 'UPSELY';\nexport const VERSION = '0.0.1';\nexport const API_ENDPOINT = 'https://api.upsely.com';\n","import { APP_NAME } from '@/config';\n\nconst FINGERPRINT_KEY = `${APP_NAME}_FINGERPRINT_V1`;\n// const FINGERPRINT_TTL_DAYS = 365;\n\nexport type DeviceInfo = {\n userAgent: string;\n language: {\n primary: string;\n all: string[];\n };\n addBlock: boolean;\n incognito: boolean;\n platform: string;\n hardwareConcurrency: number | null;\n deviceMemory: number | null;\n screen: {\n width: number;\n height: number;\n pixelRatio: number;\n colorDepth: number;\n };\n timezone: string;\n timezoneOffset: number;\n locale: string;\n connection: {\n type: string;\n effectiveType: string;\n downlink: number;\n rtt: number;\n };\n plugins: string[];\n gpu: string;\n webgl2Support: boolean;\n fingerprint: string;\n};\n\n/**\n * Gera ou recupera o Fingerprint do device\n */\nexport async function getFingerprint(): Promise<string> {\n if (typeof window === 'undefined') return '';\n\n const cached = localStorage.getItem(FINGERPRINT_KEY);\n if (cached) return cached as string;\n\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n ctx?.fillText(APP_NAME, 10, 50);\n const canvasData = canvas.toDataURL();\n\n let gpuInfo = '';\n try {\n const gl = canvas.getContext('webgl') as WebGLRenderingContext | null;\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);\n const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\n gpuInfo = `${vendor} ${renderer}`;\n }\n }\n } catch {\n // eslint-disable-next-line no-empty\n }\n\n let pluginNames = '';\n try {\n pluginNames = Array.from(navigator.plugins || [])\n .map(p => p.name)\n .join(',');\n } catch {\n // eslint-disable-next-line no-empty\n }\n\n const timezoneOffset = new Date().getTimezoneOffset().toString();\n const locale = Intl.DateTimeFormat().resolvedOptions().locale;\n\n const components = [\n navigator.userAgent,\n navigator.language,\n navigator.platform,\n navigator.hardwareConcurrency?.toString() || '',\n (\n navigator as unknown as { deviceMemory?: number }\n ).deviceMemory?.toString() || '',\n screen.width.toString(),\n screen.height.toString(),\n screen.colorDepth.toString(),\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n timezoneOffset,\n locale,\n canvasData,\n window.devicePixelRatio?.toString() || '',\n (navigator as unknown as { connection?: { effectiveType: string } })\n .connection?.effectiveType || '',\n pluginNames,\n gpuInfo,\n typeof (window as unknown as { WebGL2RenderingContext?: unknown })\n .WebGL2RenderingContext !== 'undefined'\n ? 'webgl2'\n : 'no-webgl2',\n ];\n\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(components.join('|'));\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const fingerprint = hashArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n localStorage.setItem(FINGERPRINT_KEY, fingerprint);\n return fingerprint;\n}\n","const STORAGE_KEY = 'cartData';\n\nexport const getCartData = () => {\n const cartData = localStorage.getItem(STORAGE_KEY);\n if (!cartData) return null;\n return JSON.parse(cartData);\n};\n","import { Event, UpselyRecoveryConfig } from '@/types';\nimport { getDeviceInfo } from './getDeviceInfo';\nimport { getFingerprint } from './getFingerprint';\nimport { getCartData } from './getCartData';\n\nexport interface SendEventParams {\n eventData: Event['data'];\n config: UpselyRecoveryConfig;\n sessionId: string;\n version: string;\n scriptUrl?: string;\n}\n\nexport const sendEvent = async ({\n eventData,\n config,\n sessionId,\n version,\n scriptUrl,\n}: SendEventParams): Promise<{\n success: boolean;\n timestamp: number;\n event_id: string;\n}> => {\n const deviceInfo = getDeviceInfo();\n const fingerprint = await getFingerprint();\n const cartData = getCartData();\n const payload: Event = {\n sessionId: sessionId ?? '',\n timestamp: Date.now(),\n fingerprint: fingerprint,\n user_agent: navigator.userAgent,\n page: {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n path: window.location.pathname,\n hostname: window.location.hostname,\n },\n data: {\n ...eventData,\n cart_data: cartData,\n },\n device: deviceInfo,\n meta: {\n version,\n recovery_source: 'upsely',\n environment: 'production',\n script_url: scriptUrl ?? '',\n },\n query_params: (() => {\n const search = window.location.search;\n if (!search || search.length <= 1) {\n return {};\n }\n\n const queryString = search.substring(1); // Remove o '?'\n return queryString.split('&').reduce(\n (acc, curr) => {\n if (!curr) return acc;\n const [key, value = ''] = curr.split('=');\n if (key) {\n (acc as Record<string, string>)[decodeURIComponent(key)] =\n decodeURIComponent(value);\n }\n return acc;\n },\n {} as Record<string, string>\n );\n })(),\n };\n\n const endPointUrl = `${config.apiEndpoint}/webhooks/abandoned-cart`;\n\n if (config.debug) {\n console.log('Sending event:', payload);\n }\n\n try {\n // Tentar sendBeacon primeiro (melhor para tracking)\n if (navigator.sendBeacon) {\n // const blob = new Blob([JSON.stringify(payload)]);\n\n console.log('Sending beacon:', JSON.stringify(payload));\n\n const success = navigator.sendBeacon(\n endPointUrl,\n JSON.stringify(payload)\n );\n\n if (success) {\n return {\n success: true,\n event_id: `beacon_${Date.now()}`,\n timestamp: Date.now(),\n };\n }\n }\n\n // Fallback para fetch\n const response = await fetch(endPointUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n keepalive: true,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n return {\n success: true,\n event_id: result.event_id || `fetch_${Date.now()}`,\n timestamp: Date.now(),\n };\n } catch (error) {\n if (config.debug) {\n console.error('Error sending event:', error);\n }\n\n return {\n success: false,\n event_id: `error_${Date.now()}`,\n timestamp: Date.now(),\n };\n }\n};\n","import { UpselyRecoveryConfig } from '@/types';\nimport { getFormData } from './getFormData';\nimport { sendEvent } from './sendEvent';\n\nexport interface FormAbandonmentConfig {\n config: UpselyRecoveryConfig;\n sessionId: string;\n version: string;\n scriptUrl?: string;\n}\n\n// Constantes de tempo (em milissegundos)\nconst MIN_TIME_ON_PAGE = 30 * 1000; // 30 segundos\nconst INACTIVITY_TIMEOUT = 2 * 60 * 1000; // 2 minutos\nconst VISIBILITY_TIMEOUT = 2 * 60 * 1000; // 2 minutos\n\n/**\n * Sistema de detecção e envio de dados de abandono de formulário\n */\nexport class FormAbandonment {\n private config: UpselyRecoveryConfig;\n private sessionId: string;\n private version: string;\n private scriptUrl?: string;\n private hasInteracted: boolean = false;\n private hasSent: boolean = false;\n private hasSubmitted: boolean = false;\n private pageStartTime: number = Date.now();\n private inactivityTimer: ReturnType<typeof setTimeout> | null = null;\n private visibilityTimer: ReturnType<typeof setTimeout> | null = null;\n private formInteractionListeners: (() => void)[] = [];\n private unloadListeners: (() => void)[] = [];\n private activityListeners: (() => void)[] = [];\n\n constructor({\n config,\n sessionId,\n version,\n scriptUrl,\n }: FormAbandonmentConfig) {\n this.config = config;\n this.sessionId = sessionId;\n this.version = version;\n this.scriptUrl = scriptUrl;\n\n this.initialize();\n }\n\n /**\n * Inicializa o sistema de abandono\n */\n private initialize(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n // Rastreia interações com formulários\n this.trackFormInteractions();\n\n // Rastreia atividades gerais do usuário\n this.setupActivityTracking();\n\n // Configura listeners para eventos de saída\n this.setupUnloadListeners();\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Sistema inicializado');\n }\n }\n\n /**\n * Verifica se pode enviar abandono (todas as condições devem ser atendidas)\n */\n private canSendAbandonment(): boolean {\n // Não envia se já submeteu ou já enviou\n if (this.hasSubmitted || this.hasSent) {\n return false;\n }\n\n const now = Date.now();\n const timeOnPage = now - this.pageStartTime;\n\n // Verifica tempo mínimo na página (30 segundos)\n if (timeOnPage < MIN_TIME_ON_PAGE) {\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Tempo na página insuficiente: ${Math.round(\n timeOnPage / 1000\n )}s < ${MIN_TIME_ON_PAGE / 1000}s`\n );\n }\n return false;\n }\n\n // Só envia se o usuário interagiu com algum formulário\n if (!this.hasInteracted) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Usuário não interagiu com formulário');\n }\n return false;\n }\n\n // Verifica se há dados mínimos preenchidos\n const formsData = getFormData();\n if (formsData.length === 0) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Nenhum dado de formulário encontrado');\n }\n return false;\n }\n\n // Verifica se há pelo menos um campo com valor significativo\n const hasMinimalData = formsData.some(form => {\n return Object.values(form.formData).some(value => {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') {\n return value.trim().length > 0;\n }\n if (typeof value === 'boolean') {\n return value === true;\n }\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n return true;\n });\n });\n\n if (!hasMinimalData) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Dados mínimos não preenchidos');\n }\n return false;\n }\n\n return true;\n }\n\n /**\n * Atualiza o timestamp da última atividade e reseta o timer de inatividade\n */\n private updateActivity(): void {\n // Limpa o timer anterior\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n // Só inicia o timer se já passou o tempo mínimo na página\n const timeOnPage = Date.now() - this.pageStartTime;\n if (timeOnPage >= MIN_TIME_ON_PAGE) {\n this.inactivityTimer = setTimeout(() => {\n this.sendAbandonment();\n }, INACTIVITY_TIMEOUT);\n\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Timer de inatividade iniciado (${INACTIVITY_TIMEOUT / 1000}s)`\n );\n }\n }\n }\n\n /**\n * Rastreia interações do usuário com formulários\n */\n private trackFormInteractions(): void {\n const forms = document.querySelectorAll('form');\n\n forms.forEach(form => {\n // Listener para quando o usuário foca em qualquer campo\n const focusHandler = () => {\n this.hasInteracted = true;\n this.updateActivity();\n if (this.config.debug) {\n console.log('[FormAbandonment] Usuário interagiu com formulário');\n }\n };\n\n // Listener para mudanças nos campos\n const changeHandler = () => {\n this.hasInteracted = true;\n this.updateActivity();\n };\n\n // Adiciona listeners em todos os campos do formulário\n const fields = form.querySelectorAll('input, textarea, select');\n fields.forEach(field => {\n field.addEventListener('focus', focusHandler, { passive: true });\n field.addEventListener('change', changeHandler, { passive: true });\n field.addEventListener('input', changeHandler, { passive: true });\n });\n\n // Armazena handlers para limpeza posterior\n this.formInteractionListeners.push(() => {\n fields.forEach(field => {\n field.removeEventListener('focus', focusHandler);\n field.removeEventListener('change', changeHandler);\n field.removeEventListener('input', changeHandler);\n });\n });\n });\n }\n\n /**\n * Configura rastreamento de atividades gerais do usuário\n */\n private setupActivityTracking(): void {\n const events = ['mousedown', 'keydown', 'scroll', 'input', 'touchstart'];\n\n const handleInteraction = () => {\n this.updateActivity();\n };\n\n events.forEach(event => {\n document.addEventListener(event, handleInteraction, { passive: true });\n });\n\n // Armazena handlers para limpeza posterior\n this.activityListeners.push(() => {\n events.forEach(event => {\n document.removeEventListener(event, handleInteraction);\n });\n });\n }\n\n /**\n * Rastreia mudanças de visibilidade da página\n */\n private handleVisibilityChange(): void {\n if (document.visibilityState === 'hidden') {\n // Limpa o timer anterior se existir\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n }\n\n // Inicia timer de 2 minutos - se não voltar, considera abandono\n this.visibilityTimer = setTimeout(() => {\n if (document.visibilityState === 'hidden') {\n this.sendAbandonment();\n }\n }, VISIBILITY_TIMEOUT);\n\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Aba oculta - timer iniciado (${VISIBILITY_TIMEOUT / 1000}s)`\n );\n }\n } else {\n // Aba voltou a ficar visível - cancela o timer\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Atualiza atividade quando volta\n this.updateActivity();\n\n if (this.config.debug) {\n console.log(\n '[FormAbandonment] Aba visível novamente - timer cancelado'\n );\n }\n }\n }\n\n /**\n * Handler para quando o usuário tenta sair da página\n */\n private handleBeforeUnload(): void {\n if (this.canSendAbandonment()) {\n this.sendAbandonment();\n }\n }\n\n /**\n * Configura listeners para eventos de saída da página\n */\n private setupUnloadListeners(): void {\n // beforeunload - dispara quando o usuário tenta fechar a página\n const beforeUnloadHandler = () => {\n this.handleBeforeUnload();\n };\n\n // visibilitychange - dispara quando a aba fica oculta\n const visibilityChangeHandler = () => {\n this.handleVisibilityChange();\n };\n\n // pagehide - dispara quando a página está sendo descarregada\n const pageHideHandler = () => {\n this.handleAbandonment();\n };\n\n window.addEventListener('beforeunload', beforeUnloadHandler);\n document.addEventListener('visibilitychange', visibilityChangeHandler);\n window.addEventListener('pagehide', pageHideHandler);\n\n // Armazena handlers para limpeza posterior\n this.unloadListeners.push(() => {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n document.removeEventListener('visibilitychange', visibilityChangeHandler);\n window.removeEventListener('pagehide', pageHideHandler);\n });\n }\n\n /**\n * Função para enviar dados de abandono\n */\n private sendAbandonment(): void {\n if (!this.canSendAbandonment()) {\n return;\n }\n\n this.hasSent = true;\n\n // Limpa todos os timers\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Captura dados dos formulários\n const formsData = getFormData();\n\n // Prepara dados do evento\n const eventData: Record<string, unknown> = {\n event_type: 'form_abandonment',\n forms: formsData.map(form => ({\n form_id: form.formId,\n form_index: form.formIndex,\n fields: form.formData,\n field_count: Object.keys(form.formData).length,\n })),\n total_forms: formsData.length,\n timestamp: Date.now(),\n };\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Enviando evento de abandono:', eventData);\n }\n\n // Envia evento usando sendBeacon (síncrono, mais confiável para unload)\n this.sendAbandonmentEvent(eventData);\n }\n\n /**\n * Processa o abandono e envia dados se necessário (usado pelos handlers de unload)\n */\n private handleAbandonment(): void {\n if (this.canSendAbandonment()) {\n this.sendAbandonment();\n }\n }\n\n /**\n * Marca que o formulário foi submetido com sucesso\n */\n public markAsSubmitted(): void {\n this.hasSubmitted = true;\n\n // Limpa todos os timers quando submetido\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Formulário marcado como submetido');\n }\n }\n\n /**\n * Envia evento de abandono\n */\n private sendAbandonmentEvent(eventData: Record<string, unknown>): void {\n // Usa sendEvent que já tem suporte para sendBeacon\n sendEvent({\n eventData,\n config: this.config,\n sessionId: this.sessionId,\n version: this.version,\n scriptUrl: this.scriptUrl,\n }).catch(error => {\n if (this.config.debug) {\n console.error('[FormAbandonment] Erro ao enviar evento:', error);\n }\n });\n }\n\n /**\n * Limpa todos os listeners e timers\n */\n public destroy(): void {\n // Limpa todos os timers\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Limpa todos os listeners\n this.formInteractionListeners.forEach(cleanup => cleanup());\n this.unloadListeners.forEach(cleanup => cleanup());\n this.activityListeners.forEach(cleanup => cleanup());\n\n this.formInteractionListeners = [];\n this.unloadListeners = [];\n this.activityListeners = [];\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Sistema destruído');\n }\n }\n}\n\n/**\n * Função helper para inicializar o sistema de abandono\n */\nexport const initializeFormAbandonment = (\n config: FormAbandonmentConfig\n): FormAbandonment => {\n return new FormAbandonment(config);\n};\n","/**\n * GomarkePixel - Pixel Tracker para Facebook e Google Analytics\n * Versão: 1.0.0\n */\n\nimport { UpselyRecoveryConfig } from './types';\nimport { GetSession } from './utils/getSession';\nimport { FormAbandonment } from './utils/formAbandonment';\n\nclass Initialization {\n private config: UpselyRecoveryConfig;\n private version: string = '1.0.0';\n private sessionId: string;\n private sessionManager: GetSession;\n private formAbandonment?: FormAbandonment;\n\n constructor(config: UpselyRecoveryConfig) {\n if (!config.apiEndpoint) {\n throw new Error('apiEndpoint é obrigatório');\n }\n\n this.config = {\n debug: false,\n version: this.version,\n ...config,\n };\n\n // Inicializa sessão persistente\n this.sessionManager = new GetSession(undefined, this.config.debug);\n this.sessionId = this.sessionManager.getSessionId();\n\n // Inicializa o pixel\n this.initialize();\n }\n\n private async initialize(): Promise<void> {\n // Inicializa sistema de abandono de formulário apenas no browser\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n try {\n // Obtém URL do script se disponível\n const scriptUrl = this.getScriptUrl();\n\n this.formAbandonment = new FormAbandonment({\n config: this.config,\n sessionId: this.sessionId,\n version: this.version,\n scriptUrl,\n });\n\n if (this.config.debug) {\n console.log(\n '[Initialization] Sistema de abandono de formulário inicializado'\n );\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\n '[Initialization] Erro ao inicializar sistema de abandono:',\n error\n );\n }\n }\n }\n }\n\n /**\n * Obtém a URL do script atual se disponível\n */\n private getScriptUrl(): string | undefined {\n if (typeof document === 'undefined') {\n return undefined;\n }\n\n // Tenta encontrar o script atual\n const scripts = document.getElementsByTagName('script');\n for (let i = 0; i < scripts.length; i++) {\n const script = scripts[i];\n if (script.src && script.src.includes('upsely')) {\n return script.src;\n }\n }\n\n // Tenta usar currentScript se disponível\n const currentScript = document.currentScript as HTMLScriptElement | null;\n if (currentScript?.src) {\n return currentScript.src;\n }\n\n return undefined;\n }\n\n /**\n * Atualiza a configuração\n */\n public updateConfig(newConfig: Partial<UpselyRecoveryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n /**\n * Obtém a configuração atual\n */\n public getConfig(): UpselyRecoveryConfig {\n return { ...this.config };\n }\n\n /**\n * Obtém a versão\n */\n public getVersion(): string {\n return this.version;\n }\n\n /**\n * Obtém o session ID\n */\n public getSessionId(): string {\n // Atualiza o sessionId caso tenha mudado\n this.sessionId = this.sessionManager.getSessionId();\n return this.sessionId;\n }\n\n /**\n * Obtém dados da sessão\n */\n public getSessionData() {\n return this.sessionManager.getSessionData();\n }\n\n /**\n * Verifica se a sessão está ativa\n */\n public isSessionActive(): boolean {\n return this.sessionManager.isActive();\n }\n\n /**\n * Atualiza a última atividade da sessão\n */\n public updateSessionActivity(): void {\n this.sessionManager.updateLastActivity();\n }\n\n /**\n * Renova a sessão\n */\n public renewSession(): void {\n this.sessionManager.renewSession();\n this.sessionId = this.sessionManager.getSessionId();\n }\n\n /**\n * Limpa a sessão\n */\n public clearSession(): void {\n this.sessionManager.clearSession();\n // Cria nova sessão após limpar\n this.sessionManager = new GetSession(undefined, this.config.debug);\n this.sessionId = this.sessionManager.getSessionId();\n }\n\n /**\n * Exporta dados da sessão\n */\n public exportSessionData(): string {\n return this.sessionManager.exportSessionData();\n }\n\n /**\n * Destrói o sistema de abandono de formulário\n */\n public destroyFormAbandonment(): void {\n if (this.formAbandonment) {\n this.formAbandonment.destroy();\n this.formAbandonment = undefined;\n }\n }\n}\n\n// Exportação para uso em módulos\nexport default Initialization;\n","import { UpselyRecoveryConfig } from '../types';\n\nexport const parseConfigFromScriptTag = (\n scriptTag: HTMLScriptElement\n): UpselyRecoveryConfig => {\n const config: UpselyRecoveryConfig = {\n apiEndpoint: scriptTag.getAttribute('data-api-endpoint') || undefined,\n apiKey: scriptTag.getAttribute('data-api-key') || undefined,\n debug: scriptTag.getAttribute('data-debug') === 'true',\n timeout: scriptTag.getAttribute('data-timeout')\n ? Number(scriptTag.getAttribute('data-timeout'))\n : 5000,\n };\n\n return config;\n};\n"],"mappings":";yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,EAAA,YAAAC,IAAA,eAAAC,EAAAJ,GCWO,IAAMK,EAAN,KAAiB,CAQtB,YAAYC,EAAoBC,EAAiB,GAAO,CANxD,KAAQ,WAAqB,iBAC7B,KAAQ,UAAoB,oBAC5B,KAAQ,eAAyB,KAAU,IAC3C,KAAQ,qBAA+B,IACvC,KAAQ,MAAiB,GAGvB,KAAK,MAAQA,EACb,KAAK,YAAc,KAAK,kBAAkBD,CAAS,EACnD,KAAK,sBAAsB,CAC7B,CAKQ,kBAAkBE,EAA0C,CAClE,IAAMC,EAAM,KAAK,IAAI,EAGfC,EAAS,KAAK,iBAAiB,EAG/BC,EAAkB,KAAK,UAAU,KAAK,SAAS,EAErD,GAAID,GAAU,KAAK,eAAeA,CAAM,EAEtC,OAAAA,EAAO,aAAeD,EACtB,KAAK,YAAYC,CAAM,EAGnBC,IAAoBD,EAAO,WAC7B,KAAK,UAAU,KAAK,UAAWA,EAAO,SAAS,EAG1CA,EAIT,IAAIE,EAEAJ,EACFI,EAAiBJ,EACRG,EACTC,EAAiBD,EAEjBC,EAAiB,KAAK,kBAAkB,EAI1C,IAAMC,EAAe,CAACH,GAAU,CAACC,EAC3BG,EAA2B,CAC/B,UAAWF,EACX,aAAcH,EACd,UAAWC,GAAQ,WAAaD,EAChC,WAAYC,EAASA,EAAO,WAAa,EAAI,EAC7C,WAAYA,GAAQ,YAAcD,CACpC,EAEA,YAAK,YAAYK,CAAU,EAC3B,KAAK,UAAU,KAAK,UAAWF,CAAc,EAEzC,KAAK,OACP,QAAQ,IAAI,sCAAoC,CAC9C,UAAWA,EACX,aAAAC,EACA,WAAYC,EAAW,UACzB,CAAC,EAGIA,CACT,CAKQ,mBAA4B,CAClC,IAAMC,EAAY,KAAK,IAAI,EACrBC,EAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EACnDC,EAAU,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,EAAG,EAAE,EAC1D,MAAO,WAAWF,CAAS,IAAIC,CAAM,GAAGC,CAAO,EACjD,CAKQ,eAAeC,EAAgC,CAErD,OADY,KAAK,IAAI,EACRA,EAAQ,aAAe,KAAK,cAC3C,CAKQ,YAAYA,EAA6B,CAC/C,GAAI,CACE,OAAO,aAAiB,KAC1B,aAAa,QAAQ,KAAK,WAAY,KAAK,UAAUA,CAAO,CAAC,CAEjE,OAASC,EAAO,CACV,KAAK,OACP,QAAQ,KACN,yDACAA,CACF,CAEJ,CACF,CAKQ,kBAAwC,CAC9C,GAAI,CACF,GAAI,OAAO,aAAiB,IAC1B,OAAO,KAET,IAAMT,EAAS,aAAa,QAAQ,KAAK,UAAU,EACnD,GAAI,CAACA,EAAQ,OAAO,KAEpB,IAAMU,EAAS,KAAK,MAAMV,CAAM,EAGhC,MAAI,CAACU,EAAO,WAAa,CAACA,EAAO,aACxB,KAGFA,CACT,OAASD,EAAO,CACd,OAAI,KAAK,OACP,QAAQ,KACN,4DACAA,CACF,EAEK,IACT,CACF,CAKQ,UAAUE,EAAcC,EAAqB,CACnD,GAAI,CACF,GAAI,OAAO,SAAa,IAAa,OAErC,IAAMC,EAAiB,IAAI,KAC3BA,EAAe,QACbA,EAAe,QAAQ,EACrB,KAAK,qBAAuB,GAAK,GAAK,GAAK,GAC/C,EAEA,IAAMC,EAAU,WAAWD,EAAe,YAAY,CAAC,GACvD,SAAS,OAAS,GAAGF,CAAI,IAAIC,CAAK,IAAIE,CAAO,sBAC/C,OAASL,EAAO,CACV,KAAK,OACP,QAAQ,KAAK,uCAAwCA,CAAK,CAE9D,CACF,CAKQ,UAAUE,EAA6B,CAC7C,GAAI,CACF,GAAI,OAAO,SAAa,IAAa,OAAO,KAE5C,IAAMI,EAAS,GAAGJ,CAAI,IAChBK,EAAK,SAAS,OAAO,MAAM,GAAG,EAEpC,QAASC,EAAI,EAAGA,EAAID,EAAG,OAAQC,IAAK,CAClC,IAAIC,EAAIF,EAAGC,CAAC,EACZ,KAAOC,EAAE,OAAO,CAAC,IAAM,KAAKA,EAAIA,EAAE,UAAU,EAAGA,EAAE,MAAM,EACvD,GAAIA,EAAE,QAAQH,CAAM,IAAM,EACxB,OAAOG,EAAE,UAAUH,EAAO,OAAQG,EAAE,MAAM,CAE9C,CACA,OAAO,IACT,OAAST,EAAO,CACd,OAAI,KAAK,OACP,QAAQ,KAAK,mCAAoCA,CAAK,EAEjD,IACT,CACF,CAKQ,aAAaE,EAAoB,CACvC,GAAI,CACF,GAAI,OAAO,SAAa,IAAa,OACrC,SAAS,OAAS,GAAGA,CAAI,iDAC3B,OAASF,EAAO,CACV,KAAK,OACP,QAAQ,KAAK,uCAAwCA,CAAK,CAE9D,CACF,CAKQ,uBAA8B,CACpC,GAAI,OAAO,OAAW,IAAa,OAGnC,IAAMU,EAAS,CACb,YACA,YACA,WACA,SACA,aACA,OACF,EACMC,EAAiB,IAAM,CAC3B,KAAK,mBAAmB,CAC1B,EAGIC,EAAa,EACXC,EAAkB,IAAM,CAC5B,IAAMvB,EAAM,KAAK,IAAI,EACjBA,EAAMsB,EAAa,MAErBA,EAAatB,EACbqB,EAAe,EAEnB,EAEAD,EAAO,QAAQI,GAAS,CACtB,OAAO,iBAAiBA,EAAOD,EAAiB,CAAE,QAAS,EAAK,CAAC,CACnE,CAAC,EAGD,OAAO,iBAAiB,QAASF,EAAgB,CAAE,QAAS,EAAK,CAAC,CACpE,CAKO,oBAA2B,CAChC,IAAMrB,EAAM,KAAK,IAAI,EACrB,KAAK,YAAY,aAAeA,EAChC,KAAK,YAAY,KAAK,WAAW,CACnC,CAKO,cAAqB,CAC1B,GAAK,KAAK,eAAe,KAAK,WAAW,EAIvC,KAAK,mBAAmB,MAJkB,CAC1C,IAAMyB,EAAe,KAAK,kBAAkB,EAC5C,KAAK,YAAc,KAAK,kBAAkBA,CAAY,CACxD,CAGF,CAKO,gBAA+B,CAEpC,YAAK,mBAAmB,EACjB,CAAE,GAAG,KAAK,WAAY,CAC/B,CAKO,cAAuB,CAC5B,OAAO,KAAK,YAAY,SAC1B,CAKO,UAAoB,CACzB,OAAO,KAAK,eAAe,KAAK,WAAW,CAC7C,CAKO,cAAqB,CAC1B,GAAI,CACE,OAAO,aAAiB,KAC1B,aAAa,WAAW,KAAK,UAAU,EAEzC,KAAK,aAAa,KAAK,SAAS,EAE5B,KAAK,OACP,QAAQ,IAAI,8BAA2B,CAE3C,OAASf,EAAO,CACV,KAAK,OACP,QAAQ,KAAK,yCAAuCA,CAAK,CAE7D,CACF,CAKO,mBAA4B,CACjC,OAAO,KAAK,UACV,CACE,QAAS,KAAK,YACd,SAAU,KAAK,SAAS,EACxB,oBACE,KAAK,gBAAkB,KAAK,IAAI,EAAI,KAAK,YAAY,aACzD,EACA,KACA,CACF,CACF,CACF,EC5TO,IAAMgB,EAAc,IAAwB,CACjD,GAAI,OAAO,SAAa,IACtB,MAAO,CAAC,EAGV,IAAMC,EAAQ,SAAS,iBAAiB,MAAM,EACxCC,EAA4B,CAAC,EAEnC,OAAAD,EAAM,QAAQ,CAACE,EAAMC,IAAU,CAC7B,IAAMC,EAAoC,CAAC,EACrCC,EAASH,EAAK,IAAMA,EAAK,MAAQ,QAAQC,CAAK,GAGrCD,EAAK,iBAClB,yBACF,EAEO,QAAQI,GAAS,CACtB,IAAMC,EAAOD,EAAM,MAAQA,EAAM,GACjC,GAAI,CAACC,EAAM,OAEX,IAAIC,EAGJ,GAAIF,EAAM,OAAS,WACjBE,EAASF,EAA2B,gBAC3BA,EAAM,OAAS,QAAS,CAEjC,IAAMG,EAAaP,EAAK,iBACtB,6BAA6BK,CAAI,IACnC,EACMG,EAAU,MAAM,KAAKD,CAAU,EAAE,KAAKE,GAAKA,EAAE,OAAO,EAC1DH,EAAQE,EAAUA,EAAQ,MAAQ,IACpC,SAAWJ,EAAM,UAAY,SAAU,CACrC,IAAMM,EAASN,EACXM,EAAO,SAETJ,EAAQ,MAAM,KAAKI,EAAO,eAAe,EAAE,IACzCC,GAAUA,EAAO,KACnB,EAEAL,EAAQI,EAAO,KAEnB,MACEJ,EAASF,EAAiD,MAK1DE,GAAU,MAEVA,IAAU,KACTF,EAAM,OAAS,YAAcA,EAAM,OAAS,SAAWE,IAAU,MAElEJ,EAASG,CAAI,EAAIC,EAErB,CAAC,EAGG,OAAO,KAAKJ,CAAQ,EAAE,OAAS,GACjCH,EAAQ,KAAK,CACX,OAAAI,EACA,SAAAD,EACA,UAAWD,CACb,CAAC,CAEL,CAAC,EAEMF,CACT,EClFA,IAAAa,EAAyB,wBAElB,SAASC,GAAiC,CAE/C,IAAMC,EADS,IAAI,WAAS,UAAU,SAAS,EACzB,UAAU,EAEhC,MAAO,CACL,GAAI,OAAO,WAAW,EACtB,KAAOA,EAAO,OAAO,MAAQ,UAC7B,GAAI,CACF,KAAOA,EAAO,GAAG,MAAQ,UACzB,QAASA,EAAO,GAAG,SAAW,EAChC,EACA,QAAS,CACP,KAAOA,EAAO,QAAQ,MAAQ,UAG9B,QAAUA,EAAO,QAAQ,SACvB,EACJ,EACA,OAAQ,CACN,KAAMA,EAAO,OAAO,MAAQ,GAC5B,QAASA,EAAO,OAAO,SAAW,EACpC,EACA,SAAU,UAAU,SACpB,OAAQ,CACN,MAAO,OAAO,OAAO,MACrB,OAAQ,OAAO,OAAO,OACtB,YAAa,OAAO,gBACtB,CACF,CACF,CChCO,IAAMC,EAAW,SCExB,IAAMC,EAAkB,GAAGC,CAAQ,kBAsCnC,eAAsBC,GAAkC,CACtD,GAAI,OAAO,OAAW,IAAa,MAAO,GAE1C,IAAMC,EAAS,aAAa,QAAQH,CAAe,EACnD,GAAIG,EAAQ,OAAOA,EAEnB,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAClCA,EAAO,WAAW,IAAI,GAC7B,SAASH,EAAU,GAAI,EAAE,EAC9B,IAAMI,EAAaD,EAAO,UAAU,EAEhCE,EAAU,GACd,GAAI,CACF,IAAMC,EAAKH,EAAO,WAAW,OAAO,EACpC,GAAIG,EAAI,CACN,IAAMC,EAAYD,EAAG,aAAa,2BAA2B,EAC7D,GAAIC,EAAW,CACb,IAAMC,EAASF,EAAG,aAAaC,EAAU,qBAAqB,EACxDE,EAAWH,EAAG,aAAaC,EAAU,uBAAuB,EAClEF,EAAU,GAAGG,CAAM,IAAIC,CAAQ,EACjC,CACF,CACF,MAAQ,CAER,CAEA,IAAIC,EAAc,GAClB,GAAI,CACFA,EAAc,MAAM,KAAK,UAAU,SAAW,CAAC,CAAC,EAC7C,IAAIC,GAAKA,EAAE,IAAI,EACf,KAAK,GAAG,CACb,MAAQ,CAER,CAEA,IAAMC,EAAiB,IAAI,KAAK,EAAE,kBAAkB,EAAE,SAAS,EACzDC,EAAS,KAAK,eAAe,EAAE,gBAAgB,EAAE,OAEjDC,EAAa,CACjB,UAAU,UACV,UAAU,SACV,UAAU,SACV,UAAU,qBAAqB,SAAS,GAAK,GAE3C,UACA,cAAc,SAAS,GAAK,GAC9B,OAAO,MAAM,SAAS,EACtB,OAAO,OAAO,SAAS,EACvB,OAAO,WAAW,SAAS,EAC3B,KAAK,eAAe,EAAE,gBAAgB,EAAE,SACxCF,EACAC,EACAT,EACA,OAAO,kBAAkB,SAAS,GAAK,GACtC,UACE,YAAY,eAAiB,GAChCM,EACAL,EACA,OAAQ,OACL,uBAA2B,IAC1B,SACA,WACN,EAGMU,EADU,IAAI,YAAY,EACL,OAAOD,EAAW,KAAK,GAAG,CAAC,EAChDE,EAAa,MAAM,OAAO,OAAO,OAAO,UAAWD,CAAU,EAE7DE,EADY,MAAM,KAAK,IAAI,WAAWD,CAAU,CAAC,EAEpD,IAAIE,GAAKA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACxC,KAAK,EAAE,EAEV,oBAAa,QAAQnB,EAAiBkB,CAAW,EAC1CA,CACT,CClHA,IAAME,EAAc,WAEPC,EAAc,IAAM,CAC/B,IAAMC,EAAW,aAAa,QAAQF,CAAW,EACjD,OAAKE,EACE,KAAK,MAAMA,CAAQ,EADJ,IAExB,ECOO,IAAMC,EAAY,MAAO,CAC9B,UAAAC,EACA,OAAAC,EACA,UAAAC,EACA,QAAAC,EACA,UAAAC,CACF,IAIM,CACJ,IAAMC,EAAaC,EAAc,EAC3BC,EAAc,MAAMC,EAAe,EACnCC,EAAWC,EAAY,EACvBC,EAAiB,CACrB,UAAWT,GAAa,GACxB,UAAW,KAAK,IAAI,EACpB,YAAaK,EACb,WAAY,UAAU,UACtB,KAAM,CACJ,IAAK,OAAO,SAAS,KACrB,MAAO,SAAS,MAChB,SAAU,SAAS,SACnB,KAAM,OAAO,SAAS,SACtB,SAAU,OAAO,SAAS,QAC5B,EACA,KAAM,CACJ,GAAGP,EACH,UAAWS,CACb,EACA,OAAQJ,EACR,KAAM,CACJ,QAAAF,EACA,gBAAiB,SACjB,YAAa,aACb,WAAYC,GAAa,EAC3B,EACA,cAAe,IAAM,CACnB,IAAMQ,EAAS,OAAO,SAAS,OAC/B,MAAI,CAACA,GAAUA,EAAO,QAAU,EACvB,CAAC,EAGUA,EAAO,UAAU,CAAC,EACnB,MAAM,GAAG,EAAE,OAC5B,CAACC,EAAKC,IAAS,CACb,GAAI,CAACA,EAAM,OAAOD,EAClB,GAAM,CAACE,EAAKC,EAAQ,EAAE,EAAIF,EAAK,MAAM,GAAG,EACxC,OAAIC,IACDF,EAA+B,mBAAmBE,CAAG,CAAC,EACrD,mBAAmBC,CAAK,GAErBH,CACT,EACA,CAAC,CACH,CACF,GAAG,CACL,EAEMI,EAAc,GAAGhB,EAAO,WAAW,2BAErCA,EAAO,OACT,QAAQ,IAAI,iBAAkBU,CAAO,EAGvC,GAAI,CAEF,GAAI,UAAU,aAGZ,QAAQ,IAAI,kBAAmB,KAAK,UAAUA,CAAO,CAAC,EAEtC,UAAU,WACxBM,EACA,KAAK,UAAUN,CAAO,CACxB,GAGE,MAAO,CACL,QAAS,GACT,SAAU,UAAU,KAAK,IAAI,CAAC,GAC9B,UAAW,KAAK,IAAI,CACtB,EAKJ,IAAMO,EAAW,MAAM,MAAMD,EAAa,CACxC,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAUN,CAAO,EAC5B,UAAW,EACb,CAAC,EAED,GAAI,CAACO,EAAS,GACZ,MAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,KAAKA,EAAS,UAAU,EAAE,EAInE,MAAO,CACL,QAAS,GACT,UAHa,MAAMA,EAAS,KAAK,GAGhB,UAAY,SAAS,KAAK,IAAI,CAAC,GAChD,UAAW,KAAK,IAAI,CACtB,CACF,OAASC,EAAO,CACd,OAAIlB,EAAO,OACT,QAAQ,MAAM,uBAAwBkB,CAAK,EAGtC,CACL,QAAS,GACT,SAAU,SAAS,KAAK,IAAI,CAAC,GAC7B,UAAW,KAAK,IAAI,CACtB,CACF,CACF,ECtHA,IAAMC,EAAmB,GAAK,IACxBC,EAAqB,IAAS,IAC9BC,EAAqB,IAAS,IAKvBC,EAAN,KAAsB,CAe3B,YAAY,CACV,OAAAC,EACA,UAAAC,EACA,QAAAC,EACA,UAAAC,CACF,EAA0B,CAf1B,KAAQ,cAAyB,GACjC,KAAQ,QAAmB,GAC3B,KAAQ,aAAwB,GAChC,KAAQ,cAAwB,KAAK,IAAI,EACzC,KAAQ,gBAAwD,KAChE,KAAQ,gBAAwD,KAChE,KAAQ,yBAA2C,CAAC,EACpD,KAAQ,gBAAkC,CAAC,EAC3C,KAAQ,kBAAoC,CAAC,EAQ3C,KAAK,OAASH,EACd,KAAK,UAAYC,EACjB,KAAK,QAAUC,EACf,KAAK,UAAYC,EAEjB,KAAK,WAAW,CAClB,CAKQ,YAAmB,CACrB,OAAO,OAAW,KAAe,OAAO,SAAa,MAKzD,KAAK,sBAAsB,EAG3B,KAAK,sBAAsB,EAG3B,KAAK,qBAAqB,EAEtB,KAAK,OAAO,OACd,QAAQ,IAAI,wCAAwC,EAExD,CAKQ,oBAA8B,CAEpC,GAAI,KAAK,cAAgB,KAAK,QAC5B,MAAO,GAIT,IAAMC,EADM,KAAK,IAAI,EACI,KAAK,cAG9B,GAAIA,EAAaR,EACf,OAAI,KAAK,OAAO,OACd,QAAQ,IACN,sDAAmD,KAAK,MACtDQ,EAAa,GACf,CAAC,OAAOR,EAAmB,GAAI,GACjC,EAEK,GAIT,GAAI,CAAC,KAAK,cACR,OAAI,KAAK,OAAO,OACd,QAAQ,IAAI,iEAAwD,EAE/D,GAIT,IAAMS,EAAYC,EAAY,EAC9B,OAAID,EAAU,SAAW,GACnB,KAAK,OAAO,OACd,QAAQ,IAAI,2DAAwD,EAE/D,IAIcA,EAAU,KAAKE,GAC7B,OAAO,OAAOA,EAAK,QAAQ,EAAE,KAAKC,GACnCA,GAAU,KAAoC,GAC9C,OAAOA,GAAU,SACZA,EAAM,KAAK,EAAE,OAAS,EAE3B,OAAOA,GAAU,UACZA,IAAU,GAEf,MAAM,QAAQA,CAAK,EACdA,EAAM,OAAS,EAEjB,EACR,CACF,EASM,IAND,KAAK,OAAO,OACd,QAAQ,IAAI,uDAAiD,EAExD,GAIX,CAKQ,gBAAuB,CAEzB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAIN,KAAK,IAAI,EAAI,KAAK,eACnBZ,IAChB,KAAK,gBAAkB,WAAW,IAAM,CACtC,KAAK,gBAAgB,CACvB,EAAGC,CAAkB,EAEjB,KAAK,OAAO,OACd,QAAQ,IACN,oDAAoDA,EAAqB,GAAI,IAC/E,EAGN,CAKQ,uBAA8B,CACtB,SAAS,iBAAiB,MAAM,EAExC,QAAQU,GAAQ,CAEpB,IAAME,EAAe,IAAM,CACzB,KAAK,cAAgB,GACrB,KAAK,eAAe,EAChB,KAAK,OAAO,OACd,QAAQ,IAAI,0DAAoD,CAEpE,EAGMC,EAAgB,IAAM,CAC1B,KAAK,cAAgB,GACrB,KAAK,eAAe,CACtB,EAGMC,EAASJ,EAAK,iBAAiB,yBAAyB,EAC9DI,EAAO,QAAQC,GAAS,CACtBA,EAAM,iBAAiB,QAASH,EAAc,CAAE,QAAS,EAAK,CAAC,EAC/DG,EAAM,iBAAiB,SAAUF,EAAe,CAAE,QAAS,EAAK,CAAC,EACjEE,EAAM,iBAAiB,QAASF,EAAe,CAAE,QAAS,EAAK,CAAC,CAClE,CAAC,EAGD,KAAK,yBAAyB,KAAK,IAAM,CACvCC,EAAO,QAAQC,GAAS,CACtBA,EAAM,oBAAoB,QAASH,CAAY,EAC/CG,EAAM,oBAAoB,SAAUF,CAAa,EACjDE,EAAM,oBAAoB,QAASF,CAAa,CAClD,CAAC,CACH,CAAC,CACH,CAAC,CACH,CAKQ,uBAA8B,CACpC,IAAMG,EAAS,CAAC,YAAa,UAAW,SAAU,QAAS,YAAY,EAEjEC,EAAoB,IAAM,CAC9B,KAAK,eAAe,CACtB,EAEAD,EAAO,QAAQE,GAAS,CACtB,SAAS,iBAAiBA,EAAOD,EAAmB,CAAE,QAAS,EAAK,CAAC,CACvE,CAAC,EAGD,KAAK,kBAAkB,KAAK,IAAM,CAChCD,EAAO,QAAQE,GAAS,CACtB,SAAS,oBAAoBA,EAAOD,CAAiB,CACvD,CAAC,CACH,CAAC,CACH,CAKQ,wBAA+B,CACjC,SAAS,kBAAoB,UAE3B,KAAK,iBACP,aAAa,KAAK,eAAe,EAInC,KAAK,gBAAkB,WAAW,IAAM,CAClC,SAAS,kBAAoB,UAC/B,KAAK,gBAAgB,CAEzB,EAAGhB,CAAkB,EAEjB,KAAK,OAAO,OACd,QAAQ,IACN,kDAAkDA,EAAqB,GAAI,IAC7E,IAIE,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAIzB,KAAK,eAAe,EAEhB,KAAK,OAAO,OACd,QAAQ,IACN,8DACF,EAGN,CAKQ,oBAA2B,CAC7B,KAAK,mBAAmB,GAC1B,KAAK,gBAAgB,CAEzB,CAKQ,sBAA6B,CAEnC,IAAMkB,EAAsB,IAAM,CAChC,KAAK,mBAAmB,CAC1B,EAGMC,EAA0B,IAAM,CACpC,KAAK,uBAAuB,CAC9B,EAGMC,EAAkB,IAAM,CAC5B,KAAK,kBAAkB,CACzB,EAEA,OAAO,iBAAiB,eAAgBF,CAAmB,EAC3D,SAAS,iBAAiB,mBAAoBC,CAAuB,EACrE,OAAO,iBAAiB,WAAYC,CAAe,EAGnD,KAAK,gBAAgB,KAAK,IAAM,CAC9B,OAAO,oBAAoB,eAAgBF,CAAmB,EAC9D,SAAS,oBAAoB,mBAAoBC,CAAuB,EACxE,OAAO,oBAAoB,WAAYC,CAAe,CACxD,CAAC,CACH,CAKQ,iBAAwB,CAC9B,GAAI,CAAC,KAAK,mBAAmB,EAC3B,OAGF,KAAK,QAAU,GAGX,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAGrB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAIzB,IAAMb,EAAYC,EAAY,EAGxBa,EAAqC,CACzC,WAAY,mBACZ,MAAOd,EAAU,IAAIE,IAAS,CAC5B,QAASA,EAAK,OACd,WAAYA,EAAK,UACjB,OAAQA,EAAK,SACb,YAAa,OAAO,KAAKA,EAAK,QAAQ,EAAE,MAC1C,EAAE,EACF,YAAaF,EAAU,OACvB,UAAW,KAAK,IAAI,CACtB,EAEI,KAAK,OAAO,OACd,QAAQ,IAAI,iDAAkDc,CAAS,EAIzE,KAAK,qBAAqBA,CAAS,CACrC,CAKQ,mBAA0B,CAC5B,KAAK,mBAAmB,GAC1B,KAAK,gBAAgB,CAEzB,CAKO,iBAAwB,CAC7B,KAAK,aAAe,GAGhB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAGrB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAGrB,KAAK,OAAO,OACd,QAAQ,IAAI,wDAAqD,CAErE,CAKQ,qBAAqBA,EAA0C,CAErEC,EAAU,CACR,UAAAD,EACA,OAAQ,KAAK,OACb,UAAW,KAAK,UAChB,QAAS,KAAK,QACd,UAAW,KAAK,SAClB,CAAC,EAAE,MAAME,GAAS,CACZ,KAAK,OAAO,OACd,QAAQ,MAAM,2CAA4CA,CAAK,CAEnE,CAAC,CACH,CAKO,SAAgB,CAEjB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAGrB,KAAK,kBACP,aAAa,KAAK,eAAe,EACjC,KAAK,gBAAkB,MAIzB,KAAK,yBAAyB,QAAQC,GAAWA,EAAQ,CAAC,EAC1D,KAAK,gBAAgB,QAAQA,GAAWA,EAAQ,CAAC,EACjD,KAAK,kBAAkB,QAAQA,GAAWA,EAAQ,CAAC,EAEnD,KAAK,yBAA2B,CAAC,EACjC,KAAK,gBAAkB,CAAC,EACxB,KAAK,kBAAoB,CAAC,EAEtB,KAAK,OAAO,OACd,QAAQ,IAAI,wCAAqC,CAErD,CACF,ECnaA,IAAMC,EAAN,KAAqB,CAOnB,YAAYC,EAA8B,CAL1C,KAAQ,QAAkB,QAMxB,GAAI,CAACA,EAAO,YACV,MAAM,IAAI,MAAM,iCAA2B,EAG7C,KAAK,OAAS,CACZ,MAAO,GACP,QAAS,KAAK,QACd,GAAGA,CACL,EAGA,KAAK,eAAiB,IAAIC,EAAW,OAAW,KAAK,OAAO,KAAK,EACjE,KAAK,UAAY,KAAK,eAAe,aAAa,EAGlD,KAAK,WAAW,CAClB,CAEA,MAAc,YAA4B,CAExC,GAAI,OAAO,OAAW,KAAe,OAAO,SAAa,IACvD,GAAI,CAEF,IAAMC,EAAY,KAAK,aAAa,EAEpC,KAAK,gBAAkB,IAAIC,EAAgB,CACzC,OAAQ,KAAK,OACb,UAAW,KAAK,UAChB,QAAS,KAAK,QACd,UAAAD,CACF,CAAC,EAEG,KAAK,OAAO,OACd,QAAQ,IACN,oEACF,CAEJ,OAASE,EAAO,CACV,KAAK,OAAO,OACd,QAAQ,MACN,4DACAA,CACF,CAEJ,CAEJ,CAKQ,cAAmC,CACzC,GAAI,OAAO,SAAa,IACtB,OAIF,IAAMC,EAAU,SAAS,qBAAqB,QAAQ,EACtD,QAAS,EAAI,EAAG,EAAIA,EAAQ,OAAQ,IAAK,CACvC,IAAMC,EAASD,EAAQ,CAAC,EACxB,GAAIC,EAAO,KAAOA,EAAO,IAAI,SAAS,QAAQ,EAC5C,OAAOA,EAAO,GAElB,CAGA,IAAMC,EAAgB,SAAS,cAC/B,GAAIA,GAAe,IACjB,OAAOA,EAAc,GAIzB,CAKO,aAAaC,EAAgD,CAClE,KAAK,OAAS,CAAE,GAAG,KAAK,OAAQ,GAAGA,CAAU,CAC/C,CAKO,WAAkC,CACvC,MAAO,CAAE,GAAG,KAAK,MAAO,CAC1B,CAKO,YAAqB,CAC1B,OAAO,KAAK,OACd,CAKO,cAAuB,CAE5B,YAAK,UAAY,KAAK,eAAe,aAAa,EAC3C,KAAK,SACd,CAKO,gBAAiB,CACtB,OAAO,KAAK,eAAe,eAAe,CAC5C,CAKO,iBAA2B,CAChC,OAAO,KAAK,eAAe,SAAS,CACtC,CAKO,uBAA8B,CACnC,KAAK,eAAe,mBAAmB,CACzC,CAKO,cAAqB,CAC1B,KAAK,eAAe,aAAa,EACjC,KAAK,UAAY,KAAK,eAAe,aAAa,CACpD,CAKO,cAAqB,CAC1B,KAAK,eAAe,aAAa,EAEjC,KAAK,eAAiB,IAAIP,EAAW,OAAW,KAAK,OAAO,KAAK,EACjE,KAAK,UAAY,KAAK,eAAe,aAAa,CACpD,CAKO,mBAA4B,CACjC,OAAO,KAAK,eAAe,kBAAkB,CAC/C,CAKO,wBAA+B,CAChC,KAAK,kBACP,KAAK,gBAAgB,QAAQ,EAC7B,KAAK,gBAAkB,OAE3B,CACF,EAGOQ,EAAQV,ECjLR,IAAMW,EACXC,IAEqC,CACnC,YAAaA,EAAU,aAAa,mBAAmB,GAAK,OAC5D,OAAQA,EAAU,aAAa,cAAc,GAAK,OAClD,MAAOA,EAAU,aAAa,YAAY,IAAM,OAChD,QAASA,EAAU,aAAa,cAAc,EAC1C,OAAOA,EAAU,aAAa,cAAc,CAAC,EAC7C,GACN,GVPF,IAAOC,EAAQC,EAETC,EAAsC,CAC1C,YAAa,gDACb,MAAO,GACP,QAAS,IACT,QAAS,OACX,EAGA,eAAsBC,GAEpB,CACA,GAAI,SAAO,OAAW,KAAe,OAAO,SAAa,KAEzD,GAAI,CACF,IAAMC,EAAY,SAAS,cAC3B,GAAIA,EAAW,CACb,IAAMC,EAASC,EAAyBF,CAAS,EACjD,OAAO,IAAIH,EAAe,CACxB,YAAaI,EAAO,aAAeH,EAAc,YACjD,MAAOG,EAAO,OAASH,EAAc,MACrC,QAASG,EAAO,SAAWH,EAAc,QACzC,QAASG,EAAO,SAAWH,EAAc,QACzC,OAAQG,EAAO,QAAUH,EAAc,MACzC,CAAC,CACH,CACF,OAASK,EAAK,CACZ,QAAQ,KAAK,gDAAiDA,CAAG,CACnE,CACF,CAGI,OAAO,OAAW,MAGlB,OACA,eAAiBN,GAIlB,SAAY,CACX,IAAMO,EAAY,MAAML,EAAsB,EAC1CK,IACD,OAAyD,eACxDA,EAEN,GAAG","names":["index_exports","__export","autoInitFromScriptTag","index_default","__toCommonJS","GetSession","sessionId","debug","providedSessionId","now","stored","cookieSessionId","finalSessionId","isFirstVisit","newSession","timestamp","random","random2","session","error","parsed","name","value","expirationDate","expires","nameEQ","ca","i","c","events","updateActivity","lastUpdate","throttledUpdate","event","newSessionId","getFormData","forms","results","form","index","formData","formId","field","name","value","radioGroup","checked","r","select","option","import_ua_parser_js","getDeviceInfo","result","APP_NAME","FINGERPRINT_KEY","APP_NAME","getFingerprint","cached","canvas","canvasData","gpuInfo","gl","debugInfo","vendor","renderer","pluginNames","p","timezoneOffset","locale","components","dataBuffer","hashBuffer","fingerprint","b","STORAGE_KEY","getCartData","cartData","sendEvent","eventData","config","sessionId","version","scriptUrl","deviceInfo","getDeviceInfo","fingerprint","getFingerprint","cartData","getCartData","payload","search","acc","curr","key","value","endPointUrl","response","error","MIN_TIME_ON_PAGE","INACTIVITY_TIMEOUT","VISIBILITY_TIMEOUT","FormAbandonment","config","sessionId","version","scriptUrl","timeOnPage","formsData","getFormData","form","value","focusHandler","changeHandler","fields","field","events","handleInteraction","event","beforeUnloadHandler","visibilityChangeHandler","pageHideHandler","eventData","sendEvent","error","cleanup","Initialization","config","GetSession","scriptUrl","FormAbandonment","error","scripts","script","currentScript","newConfig","init_default","parseConfigFromScriptTag","scriptTag","index_default","init_default","defaultConfig","autoInitFromScriptTag","scriptTag","config","parseConfigFromScriptTag","err","autoPixel"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils/getSession.ts","../src/utils/getFormData.ts","../src/utils/getDeviceInfo.ts","../src/config.ts","../src/utils/getFingerprint.ts","../src/utils/getCartData.ts","../src/utils/sendEvent.tsx","../src/utils/formAbandonment.ts","../src/init.ts","../src/utils/parseConfigFromScriptTag.ts"],"sourcesContent":["// Exportação para uso em módulos\nimport UpselyRecovery from './init';\nimport { UpselyRecoveryConfig } from './types';\nimport { parseConfigFromScriptTag } from './utils/parseConfigFromScriptTag';\n\nexport default UpselyRecovery;\n\nconst defaultConfig: UpselyRecoveryConfig = {\n apiEndpoint: 'https://api-upsely-webhook-dev.up.railway.app',\n debug: true,\n timeout: 5000,\n version: '1.0.0',\n};\n\n// Função para auto-inicialização via script tag\nexport async function autoInitFromScriptTag(): Promise<\n UpselyRecovery | undefined\n> {\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n try {\n const scriptTag = document.currentScript as HTMLScriptElement | null;\n if (scriptTag) {\n const config = parseConfigFromScriptTag(scriptTag);\n return new UpselyRecovery({\n apiEndpoint: config.apiEndpoint || defaultConfig.apiEndpoint,\n debug: config.debug || defaultConfig.debug,\n timeout: config.timeout || defaultConfig.timeout,\n version: config.version || defaultConfig.version,\n apiKey: config.apiKey || defaultConfig.apiKey,\n });\n }\n } catch (err) {\n console.warn('[GomarkePixel] Erro no autoInitFromScriptTag:', err);\n }\n}\n\n// Para uso global (IIFE) - versão corrigida\nif (typeof window !== 'undefined') {\n // Expor a classe GomarkePixel\n (\n window as unknown as { UpselyRecovery: typeof UpselyRecovery }\n ).UpselyRecovery = UpselyRecovery;\n\n // Auto-inicialização se configurado via script tag\n // Usando IIFE assíncrona para evitar top-level await\n (async () => {\n const autoPixel = await autoInitFromScriptTag();\n if (autoPixel) {\n (window as unknown as { upselyRecovery: UpselyRecovery }).upselyRecovery =\n autoPixel;\n }\n })();\n}\n","export interface ISessionData {\n sessionId: string;\n lastActivity: number;\n createdAt: number;\n visitCount: number;\n firstVisit: number;\n}\n\n/**\n * Gerenciador de sessão persistente com suporte a cookies e localStorage\n */\nexport class GetSession {\n private sessionData: ISessionData;\n private storageKey: string = 'upsely_session';\n private cookieKey: string = 'upsely_session_id';\n private sessionTimeout: number = 30 * 60 * 1000; // 30 minutos\n private cookieExpirationDays: number = 365; // 1 ano para cookies\n private debug: boolean = false;\n\n constructor(sessionId?: string, debug: boolean = false) {\n this.debug = debug;\n this.sessionData = this.initializeSession(sessionId);\n this.startActivityTracking();\n }\n\n /**\n * Inicializa ou recupera dados da sessão\n */\n private initializeSession(providedSessionId?: string): ISessionData {\n const now = Date.now();\n\n // Tenta recuperar sessão do localStorage\n const stored = this.getStoredSession();\n\n // Tenta recuperar sessionId do cookie\n const cookieSessionId = this.getCookie(this.cookieKey);\n\n if (stored && this.isSessionValid(stored)) {\n // Sessão existente válida - atualiza última atividade\n stored.lastActivity = now;\n this.saveSession(stored);\n\n // Garante que o cookie também está atualizado\n if (cookieSessionId !== stored.sessionId) {\n this.setCookie(this.cookieKey, stored.sessionId);\n }\n\n return stored;\n }\n\n // Determina o sessionId a usar\n let finalSessionId: string;\n\n if (providedSessionId) {\n finalSessionId = providedSessionId;\n } else if (cookieSessionId) {\n finalSessionId = cookieSessionId;\n } else {\n finalSessionId = this.generateSessionId();\n }\n\n // Nova sessão ou sessão expirada\n const isFirstVisit = !stored && !cookieSessionId;\n const newSession: ISessionData = {\n sessionId: finalSessionId,\n lastActivity: now,\n createdAt: stored?.createdAt || now,\n visitCount: stored ? stored.visitCount + 1 : 1,\n firstVisit: stored?.firstVisit || now,\n };\n\n this.saveSession(newSession);\n this.setCookie(this.cookieKey, finalSessionId);\n\n if (this.debug) {\n console.log('[GetSession] Nova sessão criada:', {\n sessionId: finalSessionId,\n isFirstVisit,\n visitCount: newSession.visitCount,\n });\n }\n\n return newSession;\n }\n\n /**\n * Gera um novo sessionId único\n */\n private generateSessionId(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 15);\n const random2 = Math.random().toString(36).substring(2, 15);\n return `session_${timestamp}_${random}${random2}`;\n }\n\n /**\n * Verifica se a sessão ainda é válida\n */\n private isSessionValid(session: ISessionData): boolean {\n const now = Date.now();\n return now - session.lastActivity < this.sessionTimeout;\n }\n\n /**\n * Salva dados da sessão no localStorage\n */\n private saveSession(session: ISessionData): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(this.storageKey, JSON.stringify(session));\n }\n } catch (error) {\n if (this.debug) {\n console.warn(\n '[GetSession] Erro ao salvar sessão no localStorage:',\n error\n );\n }\n }\n }\n\n /**\n * Recupera dados da sessão do localStorage\n */\n private getStoredSession(): ISessionData | null {\n try {\n if (typeof localStorage === 'undefined') {\n return null;\n }\n const stored = localStorage.getItem(this.storageKey);\n if (!stored) return null;\n\n const parsed = JSON.parse(stored) as ISessionData;\n\n // Valida estrutura básica\n if (!parsed.sessionId || !parsed.lastActivity) {\n return null;\n }\n\n return parsed;\n } catch (error) {\n if (this.debug) {\n console.warn(\n '[GetSession] Erro ao recuperar sessão do localStorage:',\n error\n );\n }\n return null;\n }\n }\n\n /**\n * Define um cookie\n */\n private setCookie(name: string, value: string): void {\n try {\n if (typeof document === 'undefined') return;\n\n const expirationDate = new Date();\n expirationDate.setTime(\n expirationDate.getTime() +\n this.cookieExpirationDays * 24 * 60 * 60 * 1000\n );\n\n const expires = `expires=${expirationDate.toUTCString()}`;\n document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao definir cookie:', error);\n }\n }\n }\n\n /**\n * Obtém um cookie\n */\n private getCookie(name: string): string | null {\n try {\n if (typeof document === 'undefined') return null;\n\n const nameEQ = `${name}=`;\n const ca = document.cookie.split(';');\n\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n return null;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao ler cookie:', error);\n }\n return null;\n }\n }\n\n /**\n * Remove um cookie\n */\n private removeCookie(name: string): void {\n try {\n if (typeof document === 'undefined') return;\n document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao remover cookie:', error);\n }\n }\n }\n\n /**\n * Inicia o rastreamento de atividade para renovar sessão automaticamente\n */\n private startActivityTracking(): void {\n if (typeof window === 'undefined') return;\n\n // Atualiza atividade em eventos do usuário\n const events = [\n 'mousedown',\n 'mousemove',\n 'keypress',\n 'scroll',\n 'touchstart',\n 'click',\n ];\n const updateActivity = () => {\n this.updateLastActivity();\n };\n\n // Throttle para não atualizar muito frequentemente\n let lastUpdate = 0;\n const throttledUpdate = () => {\n const now = Date.now();\n if (now - lastUpdate > 60000) {\n // Atualiza no máximo a cada 1 minuto\n lastUpdate = now;\n updateActivity();\n }\n };\n\n events.forEach(event => {\n window.addEventListener(event, throttledUpdate, { passive: true });\n });\n\n // Atualiza ao focar na janela\n window.addEventListener('focus', updateActivity, { passive: true });\n }\n\n /**\n * Atualiza a última atividade da sessão\n */\n public updateLastActivity(): void {\n const now = Date.now();\n this.sessionData.lastActivity = now;\n this.saveSession(this.sessionData);\n }\n\n /**\n * Renova a sessão (cria nova se expirada)\n */\n public renewSession(): void {\n if (!this.isSessionValid(this.sessionData)) {\n const newSessionId = this.generateSessionId();\n this.sessionData = this.initializeSession(newSessionId);\n } else {\n this.updateLastActivity();\n }\n }\n\n /**\n * Obtém dados da sessão\n */\n public getSessionData(): ISessionData {\n // Atualiza última atividade antes de retornar\n this.updateLastActivity();\n return { ...this.sessionData };\n }\n\n /**\n * Obtém apenas o sessionId\n */\n public getSessionId(): string {\n return this.sessionData.sessionId;\n }\n\n /**\n * Verifica se a sessão está ativa\n */\n public isActive(): boolean {\n return this.isSessionValid(this.sessionData);\n }\n\n /**\n * Limpa dados da sessão\n */\n public clearSession(): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(this.storageKey);\n }\n this.removeCookie(this.cookieKey);\n\n if (this.debug) {\n console.log('[GetSession] Sessão limpa');\n }\n } catch (error) {\n if (this.debug) {\n console.warn('[GetSession] Erro ao limpar sessão:', error);\n }\n }\n }\n\n /**\n * Exporta dados da sessão\n */\n public exportSessionData(): string {\n return JSON.stringify(\n {\n session: this.sessionData,\n isActive: this.isActive(),\n timeUntilExpiration:\n this.sessionTimeout - (Date.now() - this.sessionData.lastActivity),\n },\n null,\n 2\n );\n }\n}\n","/**\n * Utilitário para capturar dados de todos os formulários na página\n */\n\nexport interface FormDataResult {\n formId: string;\n formData: Record<string, unknown>;\n formIndex: number;\n}\n\n/**\n * Captura dados de todos os formulários na página\n * @returns Array com dados de cada formulário encontrado\n */\nexport const getFormData = (): FormDataResult[] => {\n if (typeof document === 'undefined') {\n return [];\n }\n\n const forms = document.querySelectorAll('form');\n const results: FormDataResult[] = [];\n\n forms.forEach((form, index) => {\n const formData: Record<string, unknown> = {};\n const formId = form.id || form.name || `form_${index}`;\n\n // Captura todos os campos do formulário\n const inputs = form.querySelectorAll<HTMLInputElement>(\n 'input, textarea, select'\n );\n\n inputs.forEach(field => {\n const name = field.name || field.id;\n if (!name) return;\n\n let value: unknown;\n\n // Trata diferentes tipos de campos\n if (field.type === 'checkbox') {\n value = (field as HTMLInputElement).checked;\n } else if (field.type === 'radio') {\n // Para radio, pega o valor do radio selecionado no grupo\n const radioGroup = form.querySelectorAll<HTMLInputElement>(\n `input[type=\"radio\"][name=\"${name}\"]`\n );\n const checked = Array.from(radioGroup).find(r => r.checked);\n value = checked ? checked.value : null;\n } else if (field.tagName === 'SELECT') {\n const select = field as unknown as HTMLSelectElement;\n if (select.multiple) {\n // Para select múltiplo, retorna array de valores\n value = Array.from(select.selectedOptions).map(\n option => option.value\n );\n } else {\n value = select.value;\n }\n } else {\n value = (field as HTMLInputElement | HTMLTextAreaElement).value;\n }\n\n // Só adiciona se o campo tiver valor ou for checkbox/radio\n if (\n value !== null &&\n value !== undefined &&\n value !== '' &&\n (field.type === 'checkbox' || field.type === 'radio' || value !== '')\n ) {\n formData[name] = value;\n }\n });\n\n // Só adiciona o formulário se tiver dados\n if (Object.keys(formData).length > 0) {\n results.push({\n formId,\n formData,\n formIndex: index,\n });\n }\n });\n\n return results;\n};\n","import { Event } from '@/types';\nimport { UAParser } from 'ua-parser-js';\n\nexport function getDeviceInfo(): Event['device'] {\n const parser = new UAParser(navigator.userAgent);\n const result = parser.getResult();\n\n return {\n id: crypto.randomUUID(),\n type: (result.device.type || 'desktop') as Event['device']['type'], // 'mobile' | 'tablet' | 'desktop' | 'smarttv' | 'wearable' | 'embedded'\n os: {\n name: (result.os.name || 'Unknown') as Event['device']['os']['name'],\n version: result.os.version || '',\n },\n browser: {\n name: (result.browser.name || 'Unknown') as\n | Event['device']['browser']['name']\n | 'Other',\n version: (result.browser.version ||\n '') as Event['device']['browser']['version'],\n },\n engine: {\n name: result.engine.name || '',\n version: result.engine.version || '',\n },\n language: navigator.language,\n screen: {\n width: window.screen.width,\n height: window.screen.height,\n pixel_ratio: window.devicePixelRatio,\n },\n };\n}\n","export const APP_NAME = 'UPSELY';\nexport const VERSION = '0.0.1';\nexport const API_ENDPOINT = 'https://api.upsely.com';\n","import { APP_NAME } from '@/config';\n\nconst FINGERPRINT_KEY = `${APP_NAME}_FINGERPRINT_V1`;\n// const FINGERPRINT_TTL_DAYS = 365;\n\nexport type DeviceInfo = {\n userAgent: string;\n language: {\n primary: string;\n all: string[];\n };\n addBlock: boolean;\n incognito: boolean;\n platform: string;\n hardwareConcurrency: number | null;\n deviceMemory: number | null;\n screen: {\n width: number;\n height: number;\n pixelRatio: number;\n colorDepth: number;\n };\n timezone: string;\n timezoneOffset: number;\n locale: string;\n connection: {\n type: string;\n effectiveType: string;\n downlink: number;\n rtt: number;\n };\n plugins: string[];\n gpu: string;\n webgl2Support: boolean;\n fingerprint: string;\n};\n\n/**\n * Gera ou recupera o Fingerprint do device\n */\nexport async function getFingerprint(): Promise<string> {\n if (typeof window === 'undefined') return '';\n\n const cached = localStorage.getItem(FINGERPRINT_KEY);\n if (cached) return cached as string;\n\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n ctx?.fillText(APP_NAME, 10, 50);\n const canvasData = canvas.toDataURL();\n\n let gpuInfo = '';\n try {\n const gl = canvas.getContext('webgl') as WebGLRenderingContext | null;\n if (gl) {\n const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');\n if (debugInfo) {\n const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);\n const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\n gpuInfo = `${vendor} ${renderer}`;\n }\n }\n } catch {\n // eslint-disable-next-line no-empty\n }\n\n let pluginNames = '';\n try {\n pluginNames = Array.from(navigator.plugins || [])\n .map(p => p.name)\n .join(',');\n } catch {\n // eslint-disable-next-line no-empty\n }\n\n const timezoneOffset = new Date().getTimezoneOffset().toString();\n const locale = Intl.DateTimeFormat().resolvedOptions().locale;\n\n const components = [\n navigator.userAgent,\n navigator.language,\n navigator.platform,\n navigator.hardwareConcurrency?.toString() || '',\n (\n navigator as unknown as { deviceMemory?: number }\n ).deviceMemory?.toString() || '',\n screen.width.toString(),\n screen.height.toString(),\n screen.colorDepth.toString(),\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n timezoneOffset,\n locale,\n canvasData,\n window.devicePixelRatio?.toString() || '',\n (navigator as unknown as { connection?: { effectiveType: string } })\n .connection?.effectiveType || '',\n pluginNames,\n gpuInfo,\n typeof (window as unknown as { WebGL2RenderingContext?: unknown })\n .WebGL2RenderingContext !== 'undefined'\n ? 'webgl2'\n : 'no-webgl2',\n ];\n\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(components.join('|'));\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const fingerprint = hashArray\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n localStorage.setItem(FINGERPRINT_KEY, fingerprint);\n return fingerprint;\n}\n","const STORAGE_KEY = 'cartData';\n\nexport const getCartData = () => {\n const cartData = localStorage.getItem(STORAGE_KEY);\n if (!cartData) return null;\n return JSON.parse(cartData);\n};\n","import { Event, UpselyRecoveryConfig } from '@/types';\nimport { getDeviceInfo } from './getDeviceInfo';\nimport { getFingerprint } from './getFingerprint';\nimport { getCartData } from './getCartData';\n\nexport interface SendEventParams {\n eventData: Event['data'];\n config: UpselyRecoveryConfig;\n sessionId: string;\n version: string;\n scriptUrl?: string;\n}\n\nexport const sendEvent = async ({\n eventData,\n config,\n sessionId,\n version,\n scriptUrl,\n}: SendEventParams): Promise<{\n success: boolean;\n timestamp: number;\n event_id: string;\n}> => {\n const deviceInfo = getDeviceInfo();\n const fingerprint = await getFingerprint();\n const cartData = getCartData();\n const payload: Event = {\n sessionId: sessionId ?? '',\n timestamp: Date.now(),\n fingerprint: fingerprint,\n user_agent: navigator.userAgent,\n page: {\n url: window.location.href,\n title: document.title,\n referrer: document.referrer,\n path: window.location.pathname,\n hostname: window.location.hostname,\n },\n data: {\n ...eventData,\n cart_data: cartData,\n },\n device: deviceInfo,\n meta: {\n version,\n recovery_source: 'upsely',\n environment: 'production',\n script_url: scriptUrl ?? '',\n },\n query_params: (() => {\n const search = window.location.search;\n if (!search || search.length <= 1) {\n return {};\n }\n\n const queryString = search.substring(1); // Remove o '?'\n return queryString.split('&').reduce(\n (acc, curr) => {\n if (!curr) return acc;\n const [key, value = ''] = curr.split('=');\n if (key) {\n (acc as Record<string, string>)[decodeURIComponent(key)] =\n decodeURIComponent(value);\n }\n return acc;\n },\n {} as Record<string, string>\n );\n })(),\n };\n\n const endPointUrl = `${config.apiEndpoint}/webhooks/abandoned-cart`;\n\n if (config.debug) {\n console.log('Sending event:', payload);\n }\n\n try {\n // Tentar sendBeacon primeiro (melhor para tracking)\n if (navigator.sendBeacon) {\n // const blob = new Blob([JSON.stringify(payload)]);\n\n console.log('Sending beacon:', JSON.stringify(payload));\n\n const success = navigator.sendBeacon(\n endPointUrl,\n JSON.stringify(payload)\n );\n\n if (success) {\n return {\n success: true,\n event_id: `beacon_${Date.now()}`,\n timestamp: Date.now(),\n };\n }\n }\n\n // Fallback para fetch\n const response = await fetch(endPointUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n keepalive: true,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n return {\n success: true,\n event_id: result.event_id || `fetch_${Date.now()}`,\n timestamp: Date.now(),\n };\n } catch (error) {\n if (config.debug) {\n console.error('Error sending event:', error);\n }\n\n return {\n success: false,\n event_id: `error_${Date.now()}`,\n timestamp: Date.now(),\n };\n }\n};\n","import { UpselyRecoveryConfig } from '@/types';\nimport { getFormData } from './getFormData';\nimport { sendEvent } from './sendEvent';\n\nexport interface FormAbandonmentConfig {\n config: UpselyRecoveryConfig;\n sessionId: string;\n version: string;\n scriptUrl?: string;\n}\n\n// Constantes de tempo (em milissegundos)\nconst MIN_TIME_ON_PAGE = 5 * 1000; // 30 segundos\nconst INACTIVITY_TIMEOUT = 2 * 60 * 1000; // 2 minutos\nconst VISIBILITY_TIMEOUT = 2 * 60 * 1000; // 2 minutos\n\n/**\n * Sistema de detecção e envio de dados de abandono de formulário\n */\nexport class FormAbandonment {\n private config: UpselyRecoveryConfig;\n private sessionId: string;\n private version: string;\n private scriptUrl?: string;\n private hasInteracted: boolean = false;\n private hasSent: boolean = false;\n private hasSubmitted: boolean = false;\n private pageStartTime: number = Date.now();\n private inactivityTimer: ReturnType<typeof setTimeout> | null = null;\n private visibilityTimer: ReturnType<typeof setTimeout> | null = null;\n private formInteractionListeners: (() => void)[] = [];\n private unloadListeners: (() => void)[] = [];\n private activityListeners: (() => void)[] = [];\n\n constructor({\n config,\n sessionId,\n version,\n scriptUrl,\n }: FormAbandonmentConfig) {\n this.config = config;\n this.sessionId = sessionId;\n this.version = version;\n this.scriptUrl = scriptUrl;\n\n this.initialize();\n }\n\n /**\n * Inicializa o sistema de abandono\n */\n private initialize(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n // Rastreia interações com formulários\n this.trackFormInteractions();\n\n // Rastreia atividades gerais do usuário\n this.setupActivityTracking();\n\n // Configura listeners para eventos de saída\n this.setupUnloadListeners();\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Sistema inicializado');\n }\n }\n\n /**\n * Verifica se pode enviar abandono (todas as condições devem ser atendidas)\n */\n private canSendAbandonment(): boolean {\n // Não envia se já submeteu ou já enviou\n if (this.hasSubmitted || this.hasSent) {\n return false;\n }\n\n const now = Date.now();\n const timeOnPage = now - this.pageStartTime;\n\n // Verifica tempo mínimo na página (30 segundos)\n if (timeOnPage < MIN_TIME_ON_PAGE) {\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Tempo na página insuficiente: ${Math.round(\n timeOnPage / 1000\n )}s < ${MIN_TIME_ON_PAGE / 1000}s`\n );\n }\n return false;\n }\n\n // Só envia se o usuário interagiu com algum formulário\n if (!this.hasInteracted) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Usuário não interagiu com formulário');\n }\n return false;\n }\n\n // Verifica se há dados mínimos preenchidos\n const formsData = getFormData();\n if (formsData.length === 0) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Nenhum dado de formulário encontrado');\n }\n return false;\n }\n\n // Verifica se há pelo menos um campo com valor significativo\n const hasMinimalData = formsData.some(form => {\n return Object.values(form.formData).some(value => {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') {\n return value.trim().length > 0;\n }\n if (typeof value === 'boolean') {\n return value === true;\n }\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n return true;\n });\n });\n\n if (!hasMinimalData) {\n if (this.config.debug) {\n console.log('[FormAbandonment] Dados mínimos não preenchidos');\n }\n return false;\n }\n\n return true;\n }\n\n /**\n * Atualiza o timestamp da última atividade e reseta o timer de inatividade\n */\n private updateActivity(): void {\n // Limpa o timer anterior\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n // Só inicia o timer se já passou o tempo mínimo na página\n const timeOnPage = Date.now() - this.pageStartTime;\n if (timeOnPage >= MIN_TIME_ON_PAGE) {\n this.inactivityTimer = setTimeout(() => {\n this.sendAbandonment();\n }, INACTIVITY_TIMEOUT);\n\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Timer de inatividade iniciado (${INACTIVITY_TIMEOUT / 1000}s)`\n );\n }\n }\n }\n\n /**\n * Rastreia interações do usuário com formulários\n */\n private trackFormInteractions(): void {\n const forms = document.querySelectorAll('form');\n\n forms.forEach(form => {\n // Listener para quando o usuário foca em qualquer campo\n const focusHandler = () => {\n this.hasInteracted = true;\n this.updateActivity();\n if (this.config.debug) {\n console.log('[FormAbandonment] Usuário interagiu com formulário');\n }\n };\n\n // Listener para mudanças nos campos\n const changeHandler = () => {\n this.hasInteracted = true;\n this.updateActivity();\n };\n\n // Adiciona listeners em todos os campos do formulário\n const fields = form.querySelectorAll('input, textarea, select');\n fields.forEach(field => {\n field.addEventListener('focus', focusHandler, { passive: true });\n field.addEventListener('change', changeHandler, { passive: true });\n field.addEventListener('input', changeHandler, { passive: true });\n });\n\n // Armazena handlers para limpeza posterior\n this.formInteractionListeners.push(() => {\n fields.forEach(field => {\n field.removeEventListener('focus', focusHandler);\n field.removeEventListener('change', changeHandler);\n field.removeEventListener('input', changeHandler);\n });\n });\n });\n }\n\n /**\n * Configura rastreamento de atividades gerais do usuário\n */\n private setupActivityTracking(): void {\n const events = ['mousedown', 'keydown', 'scroll', 'input', 'touchstart'];\n\n const handleInteraction = () => {\n this.updateActivity();\n };\n\n events.forEach(event => {\n document.addEventListener(event, handleInteraction, { passive: true });\n });\n\n // Armazena handlers para limpeza posterior\n this.activityListeners.push(() => {\n events.forEach(event => {\n document.removeEventListener(event, handleInteraction);\n });\n });\n }\n\n /**\n * Rastreia mudanças de visibilidade da página\n */\n private handleVisibilityChange(): void {\n if (document.visibilityState === 'hidden') {\n // Limpa o timer anterior se existir\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n }\n\n // Inicia timer de 2 minutos - se não voltar, considera abandono\n this.visibilityTimer = setTimeout(() => {\n if (document.visibilityState === 'hidden') {\n this.sendAbandonment();\n }\n }, VISIBILITY_TIMEOUT);\n\n if (this.config.debug) {\n console.log(\n `[FormAbandonment] Aba oculta - timer iniciado (${VISIBILITY_TIMEOUT / 1000}s)`\n );\n }\n } else {\n // Aba voltou a ficar visível - cancela o timer\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Atualiza atividade quando volta\n this.updateActivity();\n\n if (this.config.debug) {\n console.log(\n '[FormAbandonment] Aba visível novamente - timer cancelado'\n );\n }\n }\n }\n\n /**\n * Handler para quando o usuário tenta sair da página\n */\n private handleBeforeUnload(): void {\n if (this.canSendAbandonment()) {\n this.sendAbandonment();\n }\n }\n\n /**\n * Configura listeners para eventos de saída da página\n */\n private setupUnloadListeners(): void {\n // beforeunload - dispara quando o usuário tenta fechar a página\n const beforeUnloadHandler = () => {\n this.handleBeforeUnload();\n };\n\n // visibilitychange - dispara quando a aba fica oculta\n const visibilityChangeHandler = () => {\n this.handleVisibilityChange();\n };\n\n // pagehide - dispara quando a página está sendo descarregada\n const pageHideHandler = () => {\n this.handleAbandonment();\n };\n\n window.addEventListener('beforeunload', beforeUnloadHandler);\n document.addEventListener('visibilitychange', visibilityChangeHandler);\n window.addEventListener('pagehide', pageHideHandler);\n\n // Armazena handlers para limpeza posterior\n this.unloadListeners.push(() => {\n window.removeEventListener('beforeunload', beforeUnloadHandler);\n document.removeEventListener('visibilitychange', visibilityChangeHandler);\n window.removeEventListener('pagehide', pageHideHandler);\n });\n }\n\n /**\n * Função para enviar dados de abandono\n */\n private sendAbandonment(): void {\n if (!this.canSendAbandonment()) {\n return;\n }\n\n this.hasSent = true;\n\n // Limpa todos os timers\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Captura dados dos formulários\n const formsData = getFormData();\n\n // Prepara dados do evento\n const eventData: Record<string, unknown> = {\n event_type: 'form_abandonment',\n forms: formsData.map(form => ({\n form_id: form.formId,\n form_index: form.formIndex,\n fields: form.formData,\n field_count: Object.keys(form.formData).length,\n })),\n total_forms: formsData.length,\n timestamp: Date.now(),\n };\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Enviando evento de abandono:', eventData);\n }\n\n // Envia evento usando sendBeacon (síncrono, mais confiável para unload)\n this.sendAbandonmentEvent(eventData);\n }\n\n /**\n * Processa o abandono e envia dados se necessário (usado pelos handlers de unload)\n */\n private handleAbandonment(): void {\n if (this.canSendAbandonment()) {\n this.sendAbandonment();\n }\n }\n\n /**\n * Marca que o formulário foi submetido com sucesso\n */\n public markAsSubmitted(): void {\n this.hasSubmitted = true;\n\n // Limpa todos os timers quando submetido\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Formulário marcado como submetido');\n }\n }\n\n /**\n * Envia evento de abandono\n */\n private sendAbandonmentEvent(eventData: Record<string, unknown>): void {\n // Usa sendEvent que já tem suporte para sendBeacon\n sendEvent({\n eventData,\n config: this.config,\n sessionId: this.sessionId,\n version: this.version,\n scriptUrl: this.scriptUrl,\n }).catch(error => {\n if (this.config.debug) {\n console.error('[FormAbandonment] Erro ao enviar evento:', error);\n }\n });\n }\n\n /**\n * Limpa todos os listeners e timers\n */\n public destroy(): void {\n // Limpa todos os timers\n if (this.inactivityTimer) {\n clearTimeout(this.inactivityTimer);\n this.inactivityTimer = null;\n }\n\n if (this.visibilityTimer) {\n clearTimeout(this.visibilityTimer);\n this.visibilityTimer = null;\n }\n\n // Limpa todos os listeners\n this.formInteractionListeners.forEach(cleanup => cleanup());\n this.unloadListeners.forEach(cleanup => cleanup());\n this.activityListeners.forEach(cleanup => cleanup());\n\n this.formInteractionListeners = [];\n this.unloadListeners = [];\n this.activityListeners = [];\n\n if (this.config.debug) {\n console.log('[FormAbandonment] Sistema destruído');\n }\n }\n}\n\n/**\n * Função helper para inicializar o sistema de abandono\n */\nexport const initializeFormAbandonment = (\n config: FormAbandonmentConfig\n): FormAbandonment => {\n return new FormAbandonment(config);\n};\n","/**\n * GomarkePixel - Pixel Tracker para Facebook e Google Analytics\n * Versão: 1.0.0\n */\n\nimport { UpselyRecoveryConfig } from './types';\nimport { GetSession } from './utils/getSession';\nimport { FormAbandonment } from './utils/formAbandonment';\n\nclass Initialization {\n private config: UpselyRecoveryConfig;\n private version: string = '1.0.0';\n private sessionId: string;\n private sessionManager: GetSession;\n private formAbandonment?: FormAbandonment;\n\n constructor(config: UpselyRecoveryConfig) {\n if (!config.apiEndpoint) {\n throw new Error('apiEndpoint é obrigatório');\n }\n\n this.config = {\n debug: false,\n version: this.version,\n ...config,\n };\n\n // Inicializa sessão persistente\n this.sessionManager = new GetSession(undefined, this.config.debug);\n this.sessionId = this.sessionManager.getSessionId();\n\n // Inicializa o pixel\n this.initialize();\n }\n\n private async initialize(): Promise<void> {\n // Inicializa sistema de abandono de formulário apenas no browser\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n try {\n // Obtém URL do script se disponível\n const scriptUrl = this.getScriptUrl();\n\n this.formAbandonment = new FormAbandonment({\n config: this.config,\n sessionId: this.sessionId,\n version: this.version,\n scriptUrl,\n });\n\n if (this.config.debug) {\n console.log(\n '[Initialization] Sistema de abandono de formulário inicializado'\n );\n }\n } catch (error) {\n if (this.config.debug) {\n console.error(\n '[Initialization] Erro ao inicializar sistema de abandono:',\n error\n );\n }\n }\n }\n }\n\n /**\n * Obtém a URL do script atual se disponível\n */\n private getScriptUrl(): string | undefined {\n if (typeof document === 'undefined') {\n return undefined;\n }\n\n // Tenta encontrar o script atual\n const scripts = document.getElementsByTagName('script');\n for (let i = 0; i < scripts.length; i++) {\n const script = scripts[i];\n if (script.src && script.src.includes('upsely')) {\n return script.src;\n }\n }\n\n // Tenta usar currentScript se disponível\n const currentScript = document.currentScript as HTMLScriptElement | null;\n if (currentScript?.src) {\n return currentScript.src;\n }\n\n return undefined;\n }\n\n /**\n * Atualiza a configuração\n */\n public updateConfig(newConfig: Partial<UpselyRecoveryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n /**\n * Obtém a configuração atual\n */\n public getConfig(): UpselyRecoveryConfig {\n return { ...this.config };\n }\n\n /**\n * Obtém a versão\n */\n public getVersion(): string {\n return this.version;\n }\n\n /**\n * Obtém o session ID\n */\n public getSessionId(): string {\n // Atualiza o sessionId caso tenha mudado\n this.sessionId = this.sessionManager.getSessionId();\n return this.sessionId;\n }\n\n /**\n * Obtém dados da sessão\n */\n public getSessionData() {\n return this.sessionManager.getSessionData();\n }\n\n /**\n * Verifica se a sessão está ativa\n */\n public isSessionActive(): boolean {\n return this.sessionManager.isActive();\n }\n\n /**\n * Atualiza a última atividade da sessão\n */\n public updateSessionActivity(): void {\n this.sessionManager.updateLastActivity();\n }\n\n /**\n * Renova a sessão\n */\n public renewSession(): void {\n this.sessionManager.renewSession();\n this.sessionId = this.sessionManager.getSessionId();\n }\n\n /**\n * Limpa a sessão\n */\n public clearSession(): void {\n this.sessionManager.clearSession();\n // Cria nova sessão após limpar\n this.sessionManager = new GetSession(undefined, this.config.debug);\n this.sessionId = this.sessionManager.getSessionId();\n }\n\n /**\n * Exporta dados da sessão\n */\n public exportSessionData(): string {\n return this.sessionManager.exportSessionData();\n }\n\n /**\n * Destrói o sistema de abandono de formulário\n */\n public destroyFormAbandonment(): void {\n if (this.formAbandonment) {\n this.formAbandonment.destroy();\n this.formAbandonment = undefined;\n }\n }\n}\n\n// Exportação para uso em módulos\nexport default Initialization;\n","import { UpselyRecoveryConfig } from '../types';\n\nexport const parseConfigFromScriptTag = (\n scriptTag: HTMLScriptElement\n): UpselyRecoveryConfig => {\n const config: UpselyRecoveryConfig = {\n apiEndpoint: scriptTag.getAttribute('data-api-endpoint') || undefined,\n apiKey: scriptTag.getAttribute('data-api-key') || undefined,\n debug: scriptTag.getAttribute('data-debug') === 'true',\n timeout: scriptTag.getAttribute('data-timeout')\n ? Number(scriptTag.getAttribute('data-timeout'))\n : 5000,\n };\n\n return config;\n};\n"],"mappings":"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","names":["index_exports","__export","autoInitFromScriptTag","index_default","__toCommonJS","GetSession","sessionId","debug","providedSessionId","now","stored","cookieSessionId","finalSessionId","isFirstVisit","newSession","timestamp","random","random2","session","error","parsed","name","value","expirationDate","expires","nameEQ","ca","i","c","events","updateActivity","lastUpdate","throttledUpdate","event","newSessionId","getFormData","forms","results","form","index","formData","formId","field","name","value","radioGroup","checked","r","select","option","import_ua_parser_js","getDeviceInfo","result","APP_NAME","FINGERPRINT_KEY","APP_NAME","getFingerprint","cached","canvas","canvasData","gpuInfo","gl","debugInfo","vendor","renderer","pluginNames","p","timezoneOffset","locale","components","dataBuffer","hashBuffer","fingerprint","b","STORAGE_KEY","getCartData","cartData","sendEvent","eventData","config","sessionId","version","scriptUrl","deviceInfo","getDeviceInfo","fingerprint","getFingerprint","cartData","getCartData","payload","search","acc","curr","key","value","endPointUrl","response","error","MIN_TIME_ON_PAGE","INACTIVITY_TIMEOUT","VISIBILITY_TIMEOUT","FormAbandonment","config","sessionId","version","scriptUrl","timeOnPage","formsData","getFormData","form","value","focusHandler","changeHandler","fields","field","events","handleInteraction","event","beforeUnloadHandler","visibilityChangeHandler","pageHideHandler","eventData","sendEvent","error","cleanup","Initialization","config","GetSession","scriptUrl","FormAbandonment","error","scripts","script","currentScript","newConfig","init_default","parseConfigFromScriptTag","scriptTag","index_default","init_default","defaultConfig","autoInitFromScriptTag","scriptTag","config","parseConfigFromScriptTag","err","autoPixel"]}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/* UpselyRecovery - Script global para uso via CDN */
|
|
2
|
-
var v=class{constructor(e,i=!1){this.storageKey="upsely_session";this.cookieKey="upsely_session_id";this.sessionTimeout=1800*1e3;this.cookieExpirationDays=365;this.debug=!1;this.debug=i,this.sessionData=this.initializeSession(e),this.startActivityTracking()}initializeSession(e){let i=Date.now(),t=this.getStoredSession(),n=this.getCookie(this.cookieKey);if(t&&this.isSessionValid(t))return t.lastActivity=i,this.saveSession(t),n!==t.sessionId&&this.setCookie(this.cookieKey,t.sessionId),t;let o;e?o=e:n?o=n:o=this.generateSessionId();let r=!t&&!n,a={sessionId:o,lastActivity:i,createdAt:t?.createdAt||i,visitCount:t?t.visitCount+1:1,firstVisit:t?.firstVisit||i};return this.saveSession(a),this.setCookie(this.cookieKey,o),this.debug&&console.log("[GetSession] Nova sess\xE3o criada:",{sessionId:o,isFirstVisit:r,visitCount:a.visitCount}),a}generateSessionId(){let e=Date.now(),i=Math.random().toString(36).substring(2,15),t=Math.random().toString(36).substring(2,15);return`session_${e}_${i}${t}`}isSessionValid(e){return Date.now()-e.lastActivity<this.sessionTimeout}saveSession(e){try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(i){this.debug&&console.warn("[GetSession] Erro ao salvar sess\xE3o no localStorage:",i)}}getStoredSession(){try{if(typeof localStorage>"u")return null;let e=localStorage.getItem(this.storageKey);if(!e)return null;let i=JSON.parse(e);return!i.sessionId||!i.lastActivity?null:i}catch(e){return this.debug&&console.warn("[GetSession] Erro ao recuperar sess\xE3o do localStorage:",e),null}}setCookie(e,i){try{if(typeof document>"u")return;let t=new Date;t.setTime(t.getTime()+this.cookieExpirationDays*24*60*60*1e3);let n=`expires=${t.toUTCString()}`;document.cookie=`${e}=${i};${n};path=/;SameSite=Lax`}catch(t){this.debug&&console.warn("[GetSession] Erro ao definir cookie:",t)}}getCookie(e){try{if(typeof document>"u")return null;let i=`${e}=`,t=document.cookie.split(";");for(let n=0;n<t.length;n++){let o=t[n];for(;o.charAt(0)===" ";)o=o.substring(1,o.length);if(o.indexOf(i)===0)return o.substring(i.length,o.length)}return null}catch(i){return this.debug&&console.warn("[GetSession] Erro ao ler cookie:",i),null}}removeCookie(e){try{if(typeof document>"u")return;document.cookie=`${e}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`}catch(i){this.debug&&console.warn("[GetSession] Erro ao remover cookie:",i)}}startActivityTracking(){if(typeof window>"u")return;let e=["mousedown","mousemove","keypress","scroll","touchstart","click"],i=()=>{this.updateLastActivity()},t=0,n=()=>{let o=Date.now();o-t>6e4&&(t=o,i())};e.forEach(o=>{window.addEventListener(o,n,{passive:!0})}),window.addEventListener("focus",i,{passive:!0})}updateLastActivity(){let e=Date.now();this.sessionData.lastActivity=e,this.saveSession(this.sessionData)}renewSession(){if(this.isSessionValid(this.sessionData))this.updateLastActivity();else{let e=this.generateSessionId();this.sessionData=this.initializeSession(e)}}getSessionData(){return this.updateLastActivity(),{...this.sessionData}}getSessionId(){return this.sessionData.sessionId}isActive(){return this.isSessionValid(this.sessionData)}clearSession(){try{typeof localStorage<"u"&&localStorage.removeItem(this.storageKey),this.removeCookie(this.cookieKey),this.debug&&console.log("[GetSession] Sess\xE3o limpa")}catch(e){this.debug&&console.warn("[GetSession] Erro ao limpar sess\xE3o:",e)}}exportSessionData(){return JSON.stringify({session:this.sessionData,isActive:this.isActive(),timeUntilExpiration:this.sessionTimeout-(Date.now()-this.sessionData.lastActivity)},null,2)}};var S=()=>{if(typeof document>"u")return[];let s=document.querySelectorAll("form"),e=[];return s.forEach((i,t)=>{let n={},o=i.id||i.name||`form_${t}`;i.querySelectorAll("input, textarea, select").forEach(a=>{let l=a.name||a.id;if(!l)return;let d;if(a.type==="checkbox")d=a.checked;else if(a.type==="radio"){let c=i.querySelectorAll(`input[type="radio"][name="${l}"]`),m=Array.from(c).find(g=>g.checked);d=m?m.value:null}else if(a.tagName==="SELECT"){let c=a;c.multiple?d=Array.from(c.selectedOptions).map(m=>m.value):d=c.value}else d=a.value;d!=null&&d!==""&&(a.type==="checkbox"||a.type==="radio"||d!=="")&&(n[l]=d)}),Object.keys(n).length>0&&e.push({formId:o,formData:n,formIndex:t})}),e};import{UAParser as F}from"ua-parser-js";function I(){let e=new F(navigator.userAgent).getResult();return{id:crypto.randomUUID(),type:e.device.type||"desktop",os:{name:e.os.name||"Unknown",version:e.os.version||""},browser:{name:e.browser.name||"Unknown",version:e.browser.version||""},engine:{name:e.engine.name||"",version:e.engine.version||""},language:navigator.language,screen:{width:window.screen.width,height:window.screen.height,pixel_ratio:window.devicePixelRatio}}}var w="UPSELY";var T=`${w}_FINGERPRINT_V1`;async function D(){if(typeof window>"u")return"";let s=localStorage.getItem(T);if(s)return s;let e=document.createElement("canvas");e.getContext("2d")?.fillText(w,10,50);let t=e.toDataURL(),n="";try{let u=e.getContext("webgl");if(u){let f=u.getExtension("WEBGL_debug_renderer_info");if(f){let R=u.getParameter(f.UNMASKED_VENDOR_WEBGL),_=u.getParameter(f.UNMASKED_RENDERER_WEBGL);n=`${R} ${_}`}}}catch{}let o="";try{o=Array.from(navigator.plugins||[]).map(u=>u.name).join(",")}catch{}let r=new Date().getTimezoneOffset().toString(),a=Intl.DateTimeFormat().resolvedOptions().locale,l=[navigator.userAgent,navigator.language,navigator.platform,navigator.hardwareConcurrency?.toString()||"",navigator.deviceMemory?.toString()||"",screen.width.toString(),screen.height.toString(),screen.colorDepth.toString(),Intl.DateTimeFormat().resolvedOptions().timeZone,r,a,t,window.devicePixelRatio?.toString()||"",navigator.connection?.effectiveType||"",o,n,typeof window.WebGL2RenderingContext<"u"?"webgl2":"no-webgl2"],c=new TextEncoder().encode(l.join("|")),m=await crypto.subtle.digest("SHA-256",c),p=Array.from(new Uint8Array(m)).map(u=>u.toString(16).padStart(2,"0")).join("");return localStorage.setItem(T,p),p}var M="cartData",k=()=>{let s=localStorage.getItem(M);return s?JSON.parse(s):null};var x=async({eventData:s,config:e,sessionId:i,version:t,scriptUrl:n})=>{let o=I(),r=await D(),a=k(),l={sessionId:i??"",timestamp:Date.now(),fingerprint:r,user_agent:navigator.userAgent,page:{url:window.location.href,title:document.title,referrer:document.referrer,path:window.location.pathname,hostname:window.location.hostname},data:{...s,cart_data:a},device:o,meta:{version:t,recovery_source:"upsely",environment:"production",script_url:n??""},query_params:(()=>{let c=window.location.search;return!c||c.length<=1?{}:c.substring(1).split("&").reduce((g,p)=>{if(!p)return g;let[u,f=""]=p.split("=");return u&&(g[decodeURIComponent(u)]=decodeURIComponent(f)),g},{})})()},d=`${e.apiEndpoint}/webhooks/abandoned-cart`;e.debug&&console.log("Sending event:",l);try{if(navigator.sendBeacon&&(console.log("Sending beacon:",JSON.stringify(l)),navigator.sendBeacon(d,JSON.stringify(l))))return{success:!0,event_id:`beacon_${Date.now()}`,timestamp:Date.now()};let c=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l),keepalive:!0});if(!c.ok)throw new Error(`HTTP ${c.status}: ${c.statusText}`);return{success:!0,event_id:(await c.json()).event_id||`fetch_${Date.now()}`,timestamp:Date.now()}}catch(c){return e.debug&&console.error("Error sending event:",c),{success:!1,event_id:`error_${Date.now()}`,timestamp:Date.now()}}};var A=30*1e3,U=120*1e3,L=120*1e3,y=class{constructor({config:e,sessionId:i,version:t,scriptUrl:n}){this.hasInteracted=!1;this.hasSent=!1;this.hasSubmitted=!1;this.pageStartTime=Date.now();this.inactivityTimer=null;this.visibilityTimer=null;this.formInteractionListeners=[];this.unloadListeners=[];this.activityListeners=[];this.config=e,this.sessionId=i,this.version=t,this.scriptUrl=n,this.initialize()}initialize(){typeof window>"u"||typeof document>"u"||(this.trackFormInteractions(),this.setupActivityTracking(),this.setupUnloadListeners(),this.config.debug&&console.log("[FormAbandonment] Sistema inicializado"))}canSendAbandonment(){if(this.hasSubmitted||this.hasSent)return!1;let i=Date.now()-this.pageStartTime;if(i<A)return this.config.debug&&console.log(`[FormAbandonment] Tempo na p\xE1gina insuficiente: ${Math.round(i/1e3)}s < ${A/1e3}s`),!1;if(!this.hasInteracted)return this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio n\xE3o interagiu com formul\xE1rio"),!1;let t=S();return t.length===0?(this.config.debug&&console.log("[FormAbandonment] Nenhum dado de formul\xE1rio encontrado"),!1):t.some(o=>Object.values(o.formData).some(r=>r==null?!1:typeof r=="string"?r.trim().length>0:typeof r=="boolean"?r===!0:Array.isArray(r)?r.length>0:!0))?!0:(this.config.debug&&console.log("[FormAbandonment] Dados m\xEDnimos n\xE3o preenchidos"),!1)}updateActivity(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),Date.now()-this.pageStartTime>=A&&(this.inactivityTimer=setTimeout(()=>{this.sendAbandonment()},U),this.config.debug&&console.log(`[FormAbandonment] Timer de inatividade iniciado (${U/1e3}s)`))}trackFormInteractions(){document.querySelectorAll("form").forEach(i=>{let t=()=>{this.hasInteracted=!0,this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio interagiu com formul\xE1rio")},n=()=>{this.hasInteracted=!0,this.updateActivity()},o=i.querySelectorAll("input, textarea, select");o.forEach(r=>{r.addEventListener("focus",t,{passive:!0}),r.addEventListener("change",n,{passive:!0}),r.addEventListener("input",n,{passive:!0})}),this.formInteractionListeners.push(()=>{o.forEach(r=>{r.removeEventListener("focus",t),r.removeEventListener("change",n),r.removeEventListener("input",n)})})})}setupActivityTracking(){let e=["mousedown","keydown","scroll","input","touchstart"],i=()=>{this.updateActivity()};e.forEach(t=>{document.addEventListener(t,i,{passive:!0})}),this.activityListeners.push(()=>{e.forEach(t=>{document.removeEventListener(t,i)})})}handleVisibilityChange(){document.visibilityState==="hidden"?(this.visibilityTimer&&clearTimeout(this.visibilityTimer),this.visibilityTimer=setTimeout(()=>{document.visibilityState==="hidden"&&this.sendAbandonment()},L),this.config.debug&&console.log(`[FormAbandonment] Aba oculta - timer iniciado (${L/1e3}s)`)):(this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Aba vis\xEDvel novamente - timer cancelado"))}handleBeforeUnload(){this.canSendAbandonment()&&this.sendAbandonment()}setupUnloadListeners(){let e=()=>{this.handleBeforeUnload()},i=()=>{this.handleVisibilityChange()},t=()=>{this.handleAbandonment()};window.addEventListener("beforeunload",e),document.addEventListener("visibilitychange",i),window.addEventListener("pagehide",t),this.unloadListeners.push(()=>{window.removeEventListener("beforeunload",e),document.removeEventListener("visibilitychange",i),window.removeEventListener("pagehide",t)})}sendAbandonment(){if(!this.canSendAbandonment())return;this.hasSent=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null);let e=S(),i={event_type:"form_abandonment",forms:e.map(t=>({form_id:t.formId,form_index:t.formIndex,fields:t.formData,field_count:Object.keys(t.formData).length})),total_forms:e.length,timestamp:Date.now()};this.config.debug&&console.log("[FormAbandonment] Enviando evento de abandono:",i),this.sendAbandonmentEvent(i)}handleAbandonment(){this.canSendAbandonment()&&this.sendAbandonment()}markAsSubmitted(){this.hasSubmitted=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.config.debug&&console.log("[FormAbandonment] Formul\xE1rio marcado como submetido")}sendAbandonmentEvent(e){x({eventData:e,config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:this.scriptUrl}).catch(i=>{this.config.debug&&console.error("[FormAbandonment] Erro ao enviar evento:",i)})}destroy(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.formInteractionListeners.forEach(e=>e()),this.unloadListeners.forEach(e=>e()),this.activityListeners.forEach(e=>e()),this.formInteractionListeners=[],this.unloadListeners=[],this.activityListeners=[],this.config.debug&&console.log("[FormAbandonment] Sistema destru\xEDdo")}};var E=class{constructor(e){this.version="1.0.0";if(!e.apiEndpoint)throw new Error("apiEndpoint \xE9 obrigat\xF3rio");this.config={debug:!1,version:this.version,...e},this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId(),this.initialize()}async initialize(){if(typeof window<"u"&&typeof document<"u")try{let e=this.getScriptUrl();this.formAbandonment=new y({config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:e}),this.config.debug&&console.log("[Initialization] Sistema de abandono de formul\xE1rio inicializado")}catch(e){this.config.debug&&console.error("[Initialization] Erro ao inicializar sistema de abandono:",e)}}getScriptUrl(){if(typeof document>"u")return;let e=document.getElementsByTagName("script");for(let t=0;t<e.length;t++){let n=e[t];if(n.src&&n.src.includes("upsely"))return n.src}let i=document.currentScript;if(i?.src)return i.src}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}getVersion(){return this.version}getSessionId(){return this.sessionId=this.sessionManager.getSessionId(),this.sessionId}getSessionData(){return this.sessionManager.getSessionData()}isSessionActive(){return this.sessionManager.isActive()}updateSessionActivity(){this.sessionManager.updateLastActivity()}renewSession(){this.sessionManager.renewSession(),this.sessionId=this.sessionManager.getSessionId()}clearSession(){this.sessionManager.clearSession(),this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId()}exportSessionData(){return this.sessionManager.exportSessionData()}destroyFormAbandonment(){this.formAbandonment&&(this.formAbandonment.destroy(),this.formAbandonment=void 0)}},b=E;var C=s=>({apiEndpoint:s.getAttribute("data-api-endpoint")||void 0,apiKey:s.getAttribute("data-api-key")||void 0,debug:s.getAttribute("data-debug")==="true",timeout:s.getAttribute("data-timeout")?Number(s.getAttribute("data-timeout")):5e3});var oe=b,h={apiEndpoint:"https://api-upsely-webhook-dev.up.railway.app",debug:!0,timeout:5e3,version:"1.0.0"};async function P(){if(!(typeof window>"u"||typeof document>"u"))try{let s=document.currentScript;if(s){let e=C(s);return new b({apiEndpoint:e.apiEndpoint||h.apiEndpoint,debug:e.debug||h.debug,timeout:e.timeout||h.timeout,version:e.version||h.version,apiKey:e.apiKey||h.apiKey})}}catch(s){console.warn("[GomarkePixel] Erro no autoInitFromScriptTag:",s)}}typeof window<"u"&&(window.UpselyRecovery=b,(async()=>{let s=await P();s&&(window.upselyRecovery=s)})());export{P as autoInitFromScriptTag,oe as default};
|
|
2
|
+
var v=class{constructor(e,i=!1){this.storageKey="upsely_session";this.cookieKey="upsely_session_id";this.sessionTimeout=1800*1e3;this.cookieExpirationDays=365;this.debug=!1;this.debug=i,this.sessionData=this.initializeSession(e),this.startActivityTracking()}initializeSession(e){let i=Date.now(),t=this.getStoredSession(),n=this.getCookie(this.cookieKey);if(t&&this.isSessionValid(t))return t.lastActivity=i,this.saveSession(t),n!==t.sessionId&&this.setCookie(this.cookieKey,t.sessionId),t;let o;e?o=e:n?o=n:o=this.generateSessionId();let r=!t&&!n,a={sessionId:o,lastActivity:i,createdAt:t?.createdAt||i,visitCount:t?t.visitCount+1:1,firstVisit:t?.firstVisit||i};return this.saveSession(a),this.setCookie(this.cookieKey,o),this.debug&&console.log("[GetSession] Nova sess\xE3o criada:",{sessionId:o,isFirstVisit:r,visitCount:a.visitCount}),a}generateSessionId(){let e=Date.now(),i=Math.random().toString(36).substring(2,15),t=Math.random().toString(36).substring(2,15);return`session_${e}_${i}${t}`}isSessionValid(e){return Date.now()-e.lastActivity<this.sessionTimeout}saveSession(e){try{typeof localStorage<"u"&&localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(i){this.debug&&console.warn("[GetSession] Erro ao salvar sess\xE3o no localStorage:",i)}}getStoredSession(){try{if(typeof localStorage>"u")return null;let e=localStorage.getItem(this.storageKey);if(!e)return null;let i=JSON.parse(e);return!i.sessionId||!i.lastActivity?null:i}catch(e){return this.debug&&console.warn("[GetSession] Erro ao recuperar sess\xE3o do localStorage:",e),null}}setCookie(e,i){try{if(typeof document>"u")return;let t=new Date;t.setTime(t.getTime()+this.cookieExpirationDays*24*60*60*1e3);let n=`expires=${t.toUTCString()}`;document.cookie=`${e}=${i};${n};path=/;SameSite=Lax`}catch(t){this.debug&&console.warn("[GetSession] Erro ao definir cookie:",t)}}getCookie(e){try{if(typeof document>"u")return null;let i=`${e}=`,t=document.cookie.split(";");for(let n=0;n<t.length;n++){let o=t[n];for(;o.charAt(0)===" ";)o=o.substring(1,o.length);if(o.indexOf(i)===0)return o.substring(i.length,o.length)}return null}catch(i){return this.debug&&console.warn("[GetSession] Erro ao ler cookie:",i),null}}removeCookie(e){try{if(typeof document>"u")return;document.cookie=`${e}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`}catch(i){this.debug&&console.warn("[GetSession] Erro ao remover cookie:",i)}}startActivityTracking(){if(typeof window>"u")return;let e=["mousedown","mousemove","keypress","scroll","touchstart","click"],i=()=>{this.updateLastActivity()},t=0,n=()=>{let o=Date.now();o-t>6e4&&(t=o,i())};e.forEach(o=>{window.addEventListener(o,n,{passive:!0})}),window.addEventListener("focus",i,{passive:!0})}updateLastActivity(){let e=Date.now();this.sessionData.lastActivity=e,this.saveSession(this.sessionData)}renewSession(){if(this.isSessionValid(this.sessionData))this.updateLastActivity();else{let e=this.generateSessionId();this.sessionData=this.initializeSession(e)}}getSessionData(){return this.updateLastActivity(),{...this.sessionData}}getSessionId(){return this.sessionData.sessionId}isActive(){return this.isSessionValid(this.sessionData)}clearSession(){try{typeof localStorage<"u"&&localStorage.removeItem(this.storageKey),this.removeCookie(this.cookieKey),this.debug&&console.log("[GetSession] Sess\xE3o limpa")}catch(e){this.debug&&console.warn("[GetSession] Erro ao limpar sess\xE3o:",e)}}exportSessionData(){return JSON.stringify({session:this.sessionData,isActive:this.isActive(),timeUntilExpiration:this.sessionTimeout-(Date.now()-this.sessionData.lastActivity)},null,2)}};var S=()=>{if(typeof document>"u")return[];let s=document.querySelectorAll("form"),e=[];return s.forEach((i,t)=>{let n={},o=i.id||i.name||`form_${t}`;i.querySelectorAll("input, textarea, select").forEach(a=>{let l=a.name||a.id;if(!l)return;let d;if(a.type==="checkbox")d=a.checked;else if(a.type==="radio"){let c=i.querySelectorAll(`input[type="radio"][name="${l}"]`),m=Array.from(c).find(g=>g.checked);d=m?m.value:null}else if(a.tagName==="SELECT"){let c=a;c.multiple?d=Array.from(c.selectedOptions).map(m=>m.value):d=c.value}else d=a.value;d!=null&&d!==""&&(a.type==="checkbox"||a.type==="radio"||d!=="")&&(n[l]=d)}),Object.keys(n).length>0&&e.push({formId:o,formData:n,formIndex:t})}),e};import{UAParser as F}from"ua-parser-js";function I(){let e=new F(navigator.userAgent).getResult();return{id:crypto.randomUUID(),type:e.device.type||"desktop",os:{name:e.os.name||"Unknown",version:e.os.version||""},browser:{name:e.browser.name||"Unknown",version:e.browser.version||""},engine:{name:e.engine.name||"",version:e.engine.version||""},language:navigator.language,screen:{width:window.screen.width,height:window.screen.height,pixel_ratio:window.devicePixelRatio}}}var w="UPSELY";var T=`${w}_FINGERPRINT_V1`;async function D(){if(typeof window>"u")return"";let s=localStorage.getItem(T);if(s)return s;let e=document.createElement("canvas");e.getContext("2d")?.fillText(w,10,50);let t=e.toDataURL(),n="";try{let u=e.getContext("webgl");if(u){let f=u.getExtension("WEBGL_debug_renderer_info");if(f){let R=u.getParameter(f.UNMASKED_VENDOR_WEBGL),_=u.getParameter(f.UNMASKED_RENDERER_WEBGL);n=`${R} ${_}`}}}catch{}let o="";try{o=Array.from(navigator.plugins||[]).map(u=>u.name).join(",")}catch{}let r=new Date().getTimezoneOffset().toString(),a=Intl.DateTimeFormat().resolvedOptions().locale,l=[navigator.userAgent,navigator.language,navigator.platform,navigator.hardwareConcurrency?.toString()||"",navigator.deviceMemory?.toString()||"",screen.width.toString(),screen.height.toString(),screen.colorDepth.toString(),Intl.DateTimeFormat().resolvedOptions().timeZone,r,a,t,window.devicePixelRatio?.toString()||"",navigator.connection?.effectiveType||"",o,n,typeof window.WebGL2RenderingContext<"u"?"webgl2":"no-webgl2"],c=new TextEncoder().encode(l.join("|")),m=await crypto.subtle.digest("SHA-256",c),p=Array.from(new Uint8Array(m)).map(u=>u.toString(16).padStart(2,"0")).join("");return localStorage.setItem(T,p),p}var M="cartData",k=()=>{let s=localStorage.getItem(M);return s?JSON.parse(s):null};var x=async({eventData:s,config:e,sessionId:i,version:t,scriptUrl:n})=>{let o=I(),r=await D(),a=k(),l={sessionId:i??"",timestamp:Date.now(),fingerprint:r,user_agent:navigator.userAgent,page:{url:window.location.href,title:document.title,referrer:document.referrer,path:window.location.pathname,hostname:window.location.hostname},data:{...s,cart_data:a},device:o,meta:{version:t,recovery_source:"upsely",environment:"production",script_url:n??""},query_params:(()=>{let c=window.location.search;return!c||c.length<=1?{}:c.substring(1).split("&").reduce((g,p)=>{if(!p)return g;let[u,f=""]=p.split("=");return u&&(g[decodeURIComponent(u)]=decodeURIComponent(f)),g},{})})()},d=`${e.apiEndpoint}/webhooks/abandoned-cart`;e.debug&&console.log("Sending event:",l);try{if(navigator.sendBeacon&&(console.log("Sending beacon:",JSON.stringify(l)),navigator.sendBeacon(d,JSON.stringify(l))))return{success:!0,event_id:`beacon_${Date.now()}`,timestamp:Date.now()};let c=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l),keepalive:!0});if(!c.ok)throw new Error(`HTTP ${c.status}: ${c.statusText}`);return{success:!0,event_id:(await c.json()).event_id||`fetch_${Date.now()}`,timestamp:Date.now()}}catch(c){return e.debug&&console.error("Error sending event:",c),{success:!1,event_id:`error_${Date.now()}`,timestamp:Date.now()}}};var A=5*1e3,U=120*1e3,L=120*1e3,y=class{constructor({config:e,sessionId:i,version:t,scriptUrl:n}){this.hasInteracted=!1;this.hasSent=!1;this.hasSubmitted=!1;this.pageStartTime=Date.now();this.inactivityTimer=null;this.visibilityTimer=null;this.formInteractionListeners=[];this.unloadListeners=[];this.activityListeners=[];this.config=e,this.sessionId=i,this.version=t,this.scriptUrl=n,this.initialize()}initialize(){typeof window>"u"||typeof document>"u"||(this.trackFormInteractions(),this.setupActivityTracking(),this.setupUnloadListeners(),this.config.debug&&console.log("[FormAbandonment] Sistema inicializado"))}canSendAbandonment(){if(this.hasSubmitted||this.hasSent)return!1;let i=Date.now()-this.pageStartTime;if(i<A)return this.config.debug&&console.log(`[FormAbandonment] Tempo na p\xE1gina insuficiente: ${Math.round(i/1e3)}s < ${A/1e3}s`),!1;if(!this.hasInteracted)return this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio n\xE3o interagiu com formul\xE1rio"),!1;let t=S();return t.length===0?(this.config.debug&&console.log("[FormAbandonment] Nenhum dado de formul\xE1rio encontrado"),!1):t.some(o=>Object.values(o.formData).some(r=>r==null?!1:typeof r=="string"?r.trim().length>0:typeof r=="boolean"?r===!0:Array.isArray(r)?r.length>0:!0))?!0:(this.config.debug&&console.log("[FormAbandonment] Dados m\xEDnimos n\xE3o preenchidos"),!1)}updateActivity(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),Date.now()-this.pageStartTime>=A&&(this.inactivityTimer=setTimeout(()=>{this.sendAbandonment()},U),this.config.debug&&console.log(`[FormAbandonment] Timer de inatividade iniciado (${U/1e3}s)`))}trackFormInteractions(){document.querySelectorAll("form").forEach(i=>{let t=()=>{this.hasInteracted=!0,this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Usu\xE1rio interagiu com formul\xE1rio")},n=()=>{this.hasInteracted=!0,this.updateActivity()},o=i.querySelectorAll("input, textarea, select");o.forEach(r=>{r.addEventListener("focus",t,{passive:!0}),r.addEventListener("change",n,{passive:!0}),r.addEventListener("input",n,{passive:!0})}),this.formInteractionListeners.push(()=>{o.forEach(r=>{r.removeEventListener("focus",t),r.removeEventListener("change",n),r.removeEventListener("input",n)})})})}setupActivityTracking(){let e=["mousedown","keydown","scroll","input","touchstart"],i=()=>{this.updateActivity()};e.forEach(t=>{document.addEventListener(t,i,{passive:!0})}),this.activityListeners.push(()=>{e.forEach(t=>{document.removeEventListener(t,i)})})}handleVisibilityChange(){document.visibilityState==="hidden"?(this.visibilityTimer&&clearTimeout(this.visibilityTimer),this.visibilityTimer=setTimeout(()=>{document.visibilityState==="hidden"&&this.sendAbandonment()},L),this.config.debug&&console.log(`[FormAbandonment] Aba oculta - timer iniciado (${L/1e3}s)`)):(this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.updateActivity(),this.config.debug&&console.log("[FormAbandonment] Aba vis\xEDvel novamente - timer cancelado"))}handleBeforeUnload(){this.canSendAbandonment()&&this.sendAbandonment()}setupUnloadListeners(){let e=()=>{this.handleBeforeUnload()},i=()=>{this.handleVisibilityChange()},t=()=>{this.handleAbandonment()};window.addEventListener("beforeunload",e),document.addEventListener("visibilitychange",i),window.addEventListener("pagehide",t),this.unloadListeners.push(()=>{window.removeEventListener("beforeunload",e),document.removeEventListener("visibilitychange",i),window.removeEventListener("pagehide",t)})}sendAbandonment(){if(!this.canSendAbandonment())return;this.hasSent=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null);let e=S(),i={event_type:"form_abandonment",forms:e.map(t=>({form_id:t.formId,form_index:t.formIndex,fields:t.formData,field_count:Object.keys(t.formData).length})),total_forms:e.length,timestamp:Date.now()};this.config.debug&&console.log("[FormAbandonment] Enviando evento de abandono:",i),this.sendAbandonmentEvent(i)}handleAbandonment(){this.canSendAbandonment()&&this.sendAbandonment()}markAsSubmitted(){this.hasSubmitted=!0,this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.config.debug&&console.log("[FormAbandonment] Formul\xE1rio marcado como submetido")}sendAbandonmentEvent(e){x({eventData:e,config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:this.scriptUrl}).catch(i=>{this.config.debug&&console.error("[FormAbandonment] Erro ao enviar evento:",i)})}destroy(){this.inactivityTimer&&(clearTimeout(this.inactivityTimer),this.inactivityTimer=null),this.visibilityTimer&&(clearTimeout(this.visibilityTimer),this.visibilityTimer=null),this.formInteractionListeners.forEach(e=>e()),this.unloadListeners.forEach(e=>e()),this.activityListeners.forEach(e=>e()),this.formInteractionListeners=[],this.unloadListeners=[],this.activityListeners=[],this.config.debug&&console.log("[FormAbandonment] Sistema destru\xEDdo")}};var E=class{constructor(e){this.version="1.0.0";if(!e.apiEndpoint)throw new Error("apiEndpoint \xE9 obrigat\xF3rio");this.config={debug:!1,version:this.version,...e},this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId(),this.initialize()}async initialize(){if(typeof window<"u"&&typeof document<"u")try{let e=this.getScriptUrl();this.formAbandonment=new y({config:this.config,sessionId:this.sessionId,version:this.version,scriptUrl:e}),this.config.debug&&console.log("[Initialization] Sistema de abandono de formul\xE1rio inicializado")}catch(e){this.config.debug&&console.error("[Initialization] Erro ao inicializar sistema de abandono:",e)}}getScriptUrl(){if(typeof document>"u")return;let e=document.getElementsByTagName("script");for(let t=0;t<e.length;t++){let n=e[t];if(n.src&&n.src.includes("upsely"))return n.src}let i=document.currentScript;if(i?.src)return i.src}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}getVersion(){return this.version}getSessionId(){return this.sessionId=this.sessionManager.getSessionId(),this.sessionId}getSessionData(){return this.sessionManager.getSessionData()}isSessionActive(){return this.sessionManager.isActive()}updateSessionActivity(){this.sessionManager.updateLastActivity()}renewSession(){this.sessionManager.renewSession(),this.sessionId=this.sessionManager.getSessionId()}clearSession(){this.sessionManager.clearSession(),this.sessionManager=new v(void 0,this.config.debug),this.sessionId=this.sessionManager.getSessionId()}exportSessionData(){return this.sessionManager.exportSessionData()}destroyFormAbandonment(){this.formAbandonment&&(this.formAbandonment.destroy(),this.formAbandonment=void 0)}},b=E;var C=s=>({apiEndpoint:s.getAttribute("data-api-endpoint")||void 0,apiKey:s.getAttribute("data-api-key")||void 0,debug:s.getAttribute("data-debug")==="true",timeout:s.getAttribute("data-timeout")?Number(s.getAttribute("data-timeout")):5e3});var oe=b,h={apiEndpoint:"https://api-upsely-webhook-dev.up.railway.app",debug:!0,timeout:5e3,version:"1.0.0"};async function P(){if(!(typeof window>"u"||typeof document>"u"))try{let s=document.currentScript;if(s){let e=C(s);return new b({apiEndpoint:e.apiEndpoint||h.apiEndpoint,debug:e.debug||h.debug,timeout:e.timeout||h.timeout,version:e.version||h.version,apiKey:e.apiKey||h.apiKey})}}catch(s){console.warn("[GomarkePixel] Erro no autoInitFromScriptTag:",s)}}typeof window<"u"&&(window.UpselyRecovery=b,(async()=>{let s=await P();s&&(window.upselyRecovery=s)})());export{P as autoInitFromScriptTag,oe as default};
|
|
3
3
|
//# sourceMappingURL=index.esm.js.map
|