getu-attribution-v2-sdk 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -176,6 +176,7 @@ await init({
176
176
  enum EventType {
177
177
  // Pre-conversion signals
178
178
  PAGE_VIEW = "page_view",
179
+ PAGE_CLICK = "page_click",
179
180
  VIDEO_PLAY = "video_play",
180
181
 
181
182
  // Registration funnel
@@ -221,6 +222,21 @@ await trackPageView({
221
222
  await trackPageView({ category: "dashboard" }, "user_123");
222
223
  ```
223
224
 
225
+ ### Track Page Click
226
+
227
+ ```javascript
228
+ // Basic
229
+ await trackPageClick();
230
+
231
+ // With click context
232
+ await trackPageClick("user_123", {
233
+ element_id: "btn_signup",
234
+ element_type: "button",
235
+ element_text: "Sign Up",
236
+ position: { x: 120, y: 360 },
237
+ });
238
+ ```
239
+
224
240
  ### Track Purchase
225
241
 
226
242
  ```javascript
@@ -28,6 +28,7 @@ export declare class AttributionSDK {
28
28
  trackEmailVerification(tracking_user_id: string, verificationData?: Record<string, any>): Promise<void>;
29
29
  trackProductView(tracking_user_id?: string, productData?: Record<string, any>): Promise<void>;
30
30
  trackAddToCart(tracking_user_id?: string, cartData?: Record<string, any>): Promise<void>;
31
+ trackPageClick(tracking_user_id?: string, clickData?: Record<string, any>): Promise<void>;
31
32
  getAttributionData(): AttributionData | null;
32
33
  addUTMToURL(url: string): string;
33
34
  getCurrentUTMParams(): Record<string, string>;
@@ -1 +1 @@
1
- {"version":3,"file":"AttributionSDK.d.ts","sourceRoot":"","sources":["../../src/core/AttributionSDK.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AttributionSDK.d.ts","sourceRoot":"","sources":["../../src/core/AttributionSDK.ts"],"names":[],"mappings":"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"}
@@ -231,6 +231,10 @@ export class AttributionSDK {
231
231
  async trackAddToCart(tracking_user_id, cartData) {
232
232
  await this.trackEvent(EventType.ADD_TO_CART, cartData, tracking_user_id);
233
233
  }
234
+ // Track page click for user click journey
235
+ async trackPageClick(tracking_user_id, clickData) {
236
+ await this.trackEvent(EventType.PAGE_CLICK, clickData, tracking_user_id);
237
+ }
234
238
  // Get attribution data
235
239
  getAttributionData() {
236
240
  return this.storage.getUTMData();
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.GetuAIAttribution=e():t.GetuAIAttribution=e()}(this,()=>(()=>{"use strict";var t,e,i={d:(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},r={};i.d(r,{default:()=>q}),function(t){t.PAGE_VIEW="page_view",t.VIDEO_PLAY="video_play",t.FORM_SUBMIT="form_submit",t.EMAIL_VERIFICATION="email_verification",t.LOGIN="login",t.SIGNUP="signup",t.PRODUCT_VIEW="product_view",t.ADD_TO_CART="add_to_cart",t.PURCHASE="purchase"}(t||(t={})),function(t){t.USD="USD"}(e||(e={}));const n="https://attribution.getu.ai/attribution/api",a=[t.PURCHASE,t.LOGIN,t.SIGNUP,t.FORM_SUBMIT,t.EMAIL_VERIFICATION];function s(){return Math.floor(Date.now()/1e3)}function o(){try{const t="__localStorage_test__";return localStorage.setItem(t,t),localStorage.removeItem(t),!0}catch{return!1}}class c{constructor(t=!0){this.enabled=t}debug(t,...e){this.enabled&&console.debug&&console.debug(`[GetuAI Debug] ${t}`,...e)}info(t,...e){this.enabled&&console.info&&console.info(`[GetuAI Info] ${t}`,...e)}warn(t,...e){this.enabled&&console.warn&&console.warn(`[GetuAI Warn] ${t}`,...e)}error(t,...e){this.enabled&&console.error&&console.error(`[GetuAI Error] ${t}`,...e)}}function u(){return document.referrer||""}function l(){return window.location.href}function h(){return document.title||""}function d(t,e){try{const i=new URL(t);return Object.entries(e).forEach(([t,e])=>{e&&!i.searchParams.has(t)&&i.searchParams.set(t,e)}),i.toString()}catch(e){return t}}function g(t,e=["utm_source","utm_medium","utm_campaign"]){const i={};return e.forEach(e=>{t[e]&&(i[e]=t[e])}),i}function m(t){try{const e=t||window.location.href;return new URL(e).search}catch(t){return""}}function p(t){try{const e=t||window.location.href,i=new URL(e),r={};return i.searchParams.forEach((t,e)=>{r[e]=t}),r}catch(t){return{}}}class w{constructor(t){this.logger=t}get(t){try{if(!o())return this.logger.warn("LocalStorage not supported"),null;const e=localStorage.getItem(t);return null===e?null:JSON.parse(e)}catch(t){return this.logger.error("Error reading from localStorage:",t),null}}set(t,e){try{if(!o())return void this.logger.warn("LocalStorage not supported");localStorage.setItem(t,JSON.stringify(e))}catch(t){this.logger.error("Error writing to localStorage:",t),this.handleQuotaExceeded()}}remove(t){try{o()&&localStorage.removeItem(t)}catch(t){this.logger.error("Error removing from localStorage:",t)}}clear(){try{o()&&localStorage.clear()}catch(t){this.logger.error("Error clearing localStorage:",t)}}handleQuotaExceeded(){try{const t=Object.keys(localStorage).filter(t=>t.startsWith("attribution_"));if(t.length>0){t.sort((t,e)=>{const i=this.get(t),r=this.get(e);return(i?.expiresAt||0)-(r?.expiresAt||0)});const e=Math.ceil(.2*t.length);t.slice(0,e).forEach(t=>{this.remove(t)}),this.logger.info(`Cleaned up ${e} old attribution records`)}}catch(t){this.logger.error("Error during quota cleanup:",t)}}}class f{constructor(t){this.dbName="attribution_events",this.dbVersion=1,this.storeName="events",this.db=null,this.logger=t}async init(){if("indexedDB"in window)return new Promise((t,e)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{this.logger.error("Failed to open IndexedDB:",i.error),e(i.error)},i.onsuccess=()=>{this.db=i.result,this.logger.info("IndexedDB initialized successfully"),t()},i.onupgradeneeded=t=>{const e=t.target.result;if(!e.objectStoreNames.contains(this.storeName)){const t=e.createObjectStore(this.storeName,{keyPath:"id",autoIncrement:!0});t.createIndex("timestamp","timestamp",{unique:!1}),t.createIndex("sent","sent",{unique:!1}),t.createIndex("queued_at","queued_at",{unique:!1})}}});this.logger.warn("IndexedDB not supported")}async addEvent(t){if(!this.db)throw new Error("IndexedDB not initialized");return new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),n={...t,queued_at:Date.now(),sent:!1},a=r.add(n);a.onsuccess=()=>{this.logger.debug("Event added to IndexedDB queue"),e()},a.onerror=()=>{this.logger.error("Failed to add event to IndexedDB:",a.error),i(a.error)}})}async getUnsentEvents(t=100){return this.db?new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).index("sent").getAll(IDBKeyRange.only(!1),t);r.onsuccess=()=>{const t=r.result.map(t=>{const{queued_at:e,sent:i,...r}=t;return r});e(t)},r.onerror=()=>{this.logger.error("Failed to get unsent events:",r.error),i(r.error)}}):[]}async markEventsAsSent(t){if(this.db&&0!==t.length)return new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName);let n=0,a=!1;t.forEach(s=>{const o=r.get(s);o.onsuccess=()=>{if(o.result){const s={...o.result,sent:!0},c=r.put(s);c.onsuccess=()=>{n++,n!==t.length||a||e()},c.onerror=()=>{a=!0,this.logger.error("Failed to mark event as sent:",c.error),i(c.error)}}else n++,n!==t.length||a||e()},o.onerror=()=>{a=!0,this.logger.error("Failed to get event for marking as sent:",o.error),i(o.error)}})})}async cleanupOldEvents(t=6048e5){if(!this.db)return;const e=Date.now()-t;return new Promise((t,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).index("queued_at").openCursor(IDBKeyRange.upperBound(e));r.onsuccess=()=>{const e=r.result;e?(e.delete(),e.continue()):(this.logger.info("Old events cleanup completed"),t())},r.onerror=()=>{this.logger.error("Failed to cleanup old events:",r.error),i(r.error)}})}async getQueueSize(){return this.db?new Promise((t,e)=>{const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).count();i.onsuccess=()=>{t(i.result)},i.onerror=()=>{this.logger.error("Failed to get queue size:",i.error),e(i.error)}}):0}async clear(){if(this.db)return new Promise((t,e)=>{const i=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).clear();i.onsuccess=()=>{this.logger.info("IndexedDB queue cleared"),t()},i.onerror=()=>{this.logger.error("Failed to clear IndexedDB queue:",i.error),e(i.error)}})}}class y{constructor(t){this.UTM_STORAGE_KEY="attribution_utm_data",this.SESSION_STORAGE_KEY="attribution_session",this.logger=t,this.localStorage=new w(t),this.indexedDB=new f(t)}async init(){await this.indexedDB.init()}storeUTMData(t){try{const e=this.getUTMData(),i={utm_source:"",utm_medium:"",utm_campaign:"",utm_term:"",utm_content:"",timestamp:Date.now()},r={firstTouch:e?.firstTouch||i,lastTouch:e?.lastTouch||i,touchpoints:e?.touchpoints||[],...t,expiresAt:Date.now()+2592e6};this.localStorage.set(this.UTM_STORAGE_KEY,r),this.logger.debug("UTM data stored successfully:",{firstTouch:r.firstTouch,lastTouch:r.lastTouch,touchpointsCount:r.touchpoints.length,expiresAt:new Date(r.expiresAt).toISOString()})}catch(t){this.logger.error("Failed to store UTM data:",t)}}getUTMData(){const t=this.localStorage.get(this.UTM_STORAGE_KEY);return t&&t.expiresAt&&t.expiresAt>Date.now()?t:(t&&this.localStorage.remove(this.UTM_STORAGE_KEY),null)}storeSession(t){this.localStorage.set(this.SESSION_STORAGE_KEY,t)}getSession(){return this.localStorage.get(this.SESSION_STORAGE_KEY)}async queueEvent(t){try{await this.indexedDB.addEvent(t)}catch(t){throw this.logger.error("Failed to queue event:",t),t}}async getUnsentEvents(t=100){return await this.indexedDB.getUnsentEvents(t)}async markEventsAsSent(t){await this.indexedDB.markEventsAsSent(t)}async getQueueSize(){return await this.indexedDB.getQueueSize()}async cleanupOldEvents(){await this.indexedDB.cleanupOldEvents()}async clearQueue(){await this.indexedDB.clear()}cleanupExpiredData(){this.getUTMData()}}class S{constructor(t,e,i,r=100,n=2e3,a=3,s=1e3,o){this.queue=[],this.processing=!1,this.batchTimer=null,this.logger=t,this.apiKey=e,this.apiEndpoint=i,this.batchSize=r,this.batchInterval=n,this.maxRetries=a,this.retryDelay=s,this.sendEvents=o,this.debouncedProcess=function(t){let e;return(...i)=>{clearTimeout(e),e=setTimeout(()=>t(...i),100)}}(this.process.bind(this))}add(t){this.queue.push(t),this.logger.debug(`Event added to queue: ${t.event_type}`),a.includes(t.event_type)?(this.logger.debug(`Immediate event detected: ${t.event_type}, processing immediately`),this.processImmediate(t)):this.scheduleBatchProcessing()}async process(){if(!this.processing&&0!==this.queue.length){this.processing=!0;try{const t=this.queue.splice(0,this.batchSize);this.logger.debug(`Processing ${t.length} events from queue`),await this.sendEvents(t),this.logger.info(`Successfully processed ${t.length} events`)}catch(t){this.logger.error("Failed to process events:",t);const e=this.queue.splice(0,this.batchSize);return this.queue.unshift(...e),void setTimeout(()=>{this.processing=!1,this.debouncedProcess()},this.retryDelay)}this.processing=!1,this.queue.length>0&&this.debouncedProcess()}}async processImmediate(t){try{this.logger.debug(`Processing immediate event: ${t.event_type}`),await this.sendEvents([t]),this.logger.info(`Immediate event processed successfully: ${t.event_type}`)}catch(e){this.logger.error(`Failed to process immediate event: ${t.event_type}`,e),this.queue.unshift(t)}}scheduleBatchProcessing(){this.batchTimer&&clearTimeout(this.batchTimer),this.batchTimer=setTimeout(()=>{this.debouncedProcess()},this.batchInterval)}clear(){this.queue=[],this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null),this.processing=!1,this.logger.info("Event queue cleared")}size(){return this.queue.length}getStats(){return{size:this.queue.length,processing:this.processing}}async flush(){for(this.logger.info("Flushing event queue");this.queue.length>0;)await this.process()}}class b{constructor(t,e,i,r=3,n=1e3){this.logger=t,this.apiKey=e,this.apiEndpoint=i,this.maxRetries=r,this.retryDelay=n}async sendEvents(t){if(0===t.length)return;const e={events:t.map(t=>({event_id:t.event_id,event_type:t.event_type,tracking_user_id:t.tracking_user_id,utm_source:t.utm_source||null,utm_medium:t.utm_medium||null,utm_campaign:t.utm_campaign||null,utm_term:t.utm_term||null,utm_content:t.utm_content||null,revenue:t.revenue||null,currency:t.currency||null,event_data:t.event_data||null,context:t.context||null,timestamp:t.timestamp||s()}))};await async function(t,e=3,i=1e3){let r;for(let n=0;n<=e;n++)try{return await t()}catch(t){if(r=t,n===e)throw r;const a=i*Math.pow(2,n);await new Promise(t=>setTimeout(t,a))}throw r}(async()=>{const i=await fetch(`${this.apiEndpoint}/attribution/events`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify(e)});if(!i.ok){const t=await i.text();throw new Error(`HTTP ${i.status}: ${t}`)}const r=await i.json();return this.logger.debug("Events sent successfully:",r),{result:r,sentEvents:t}},this.maxRetries,this.retryDelay)}async sendSingleEvent(t){await this.sendEvents([t])}async testConnection(){try{return(await fetch(`${this.apiEndpoint}/health`,{method:"GET",headers:{Authorization:`Bearer ${this.apiKey}`}})).ok}catch(t){return this.logger.error("Connection test failed:",t),!1}}}class T{constructor(t){this.session=null,this.initialized=!1,this.autoTrackEnabled=!1,this.pageViewTrackTimes=new Map,this.spaTrackingEnabled=!1,this.lastTrackedPath="",this.originalPushState=null,this.originalReplaceState=null,this.popstateHandler=null,this.config={apiEndpoint:n,batchSize:100,batchInterval:2e3,maxRetries:3,retryDelay:1e3,enableDebug:!1,autoTrack:!1,autoTrackPageView:!1,sessionTimeout:18e5,enableCrossDomainUTM:!0,crossDomainUTMParams:["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],excludeDomains:[],autoCleanUTM:!0,pageViewDebounceInterval:5e3,...t},this.logger=new c(this.config.enableDebug),this.storage=new y(this.logger),this.httpClient=new b(this.logger,this.config.apiKey,this.config.apiEndpoint||n,this.config.maxRetries,this.config.retryDelay),this.queue=new S(this.logger,this.config.apiKey,this.config.apiEndpoint||n,this.config.batchSize,this.config.batchInterval,this.config.maxRetries,this.config.retryDelay,t=>this.httpClient.sendEvents(t))}async init(){if(this.initialized)this.logger.warn("SDK already initialized");else try{this.logger.info("Initializing GetuAI Attribution SDK"),await this.storage.init(),this.initializeSession(),this.extractAndStoreUTMData(),this.config.autoTrack&&this.setupAutoTracking(),this.setupNetworkHandlers(),this.setupVisibilityHandlers(),this.setupBeforeUnloadHandler(),this.initialized=!0,this.logger.info("🚀 GetuAI Attribution SDK initialized successfully"),this.logger.info("📄 Auto track page view = "+this.config.autoTrackPageView),this.config.autoTrackPageView&&(this.logger.info("📄 Auto track page view enabled (including SPA route tracking)"),this.lastTrackedPath=this.getCurrentPath(),this.setupSPATracking(),setTimeout(()=>{this.trackPageView().then(()=>{this.logger.info("✅ Auto track page view completed")}).catch(t=>this.logger.error("❌ Auto track page view failed:",t))},100))}catch(t){throw this.logger.error("Failed to initialize SDK:",t),t}}async trackEvent(t,i,r,n,a=e.USD){if(this.initialized)try{const e=l();let o=null;try{o=await this.fetchPublicIP()}catch(t){}const c={domain:"undefined"!=typeof window?window.location.hostname:null,path:"undefined"!=typeof window?window.location.pathname:null,title:h(),referrer:u(),url:e.split("?")[0],querystring:m(e),query_params:p(e),ip_address:o},d={session_id:this.session?.sessionId,start_time:this.session?.startTime,last_activity:this.session?.lastActivity,page_views:this.session?.pageViews},g={event_id:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),event_type:t,tracking_user_id:r,timestamp:s(),event_data:i,context:{page:c,session:d},revenue:n,currency:a,...this.getUTMParams()};this.logger.debug(`Tracking event: ${t}`,g),this.queue.add(g)}catch(e){this.logger.error(`Failed to track event ${t}:`,e)}else this.logger.warn("SDK not initialized, event not tracked")}async trackPageView(e,i){const r=l(),n=r.split("?")[0],a=Date.now(),s=this.config.pageViewDebounceInterval||5e3,o=this.pageViewTrackTimes.get(n);if(o&&a-o<s)return void this.logger.debug(`Page view debounced: ${n} (last tracked ${a-o}ms ago)`);const c={url:r,title:h(),referrer:u(),user_agent:navigator.userAgent||"",...e};await this.trackEvent(t.PAGE_VIEW,c,i),this.pageViewTrackTimes.set(n,a),this.cleanupPageViewTrackTimes()}cleanupPageViewTrackTimes(){const t=Date.now()-36e5;for(const[e,i]of this.pageViewTrackTimes.entries())i<t&&this.pageViewTrackTimes.delete(e)}async fetchPublicIP(){try{const t=new AbortController,e=setTimeout(()=>t.abort(),2e3),i=await fetch("https://api.ipify.org?format=json",{signal:t.signal,headers:{Accept:"application/json"}});if(clearTimeout(e),!i.ok)return null;const r=await i.json();return"string"==typeof r?.ip?r.ip:null}catch(t){return this.logger.debug("Public IP fetch failed",t),null}}async trackPurchase(i,r,n=e.USD,a){await this.trackEvent(t.PURCHASE,a,i,r,n)}async trackLogin(e,i){await this.trackEvent(t.LOGIN,i,e)}async trackSignup(e,i){await this.trackEvent(t.SIGNUP,i,e)}async trackFormSubmit(e,i){await this.trackEvent(t.FORM_SUBMIT,i,e)}async trackVideoPlay(e,i){await this.trackEvent(t.VIDEO_PLAY,i,e)}async trackEmailVerification(e,i){await this.trackEvent(t.EMAIL_VERIFICATION,i,e)}async trackProductView(e,i){await this.trackEvent(t.PRODUCT_VIEW,i,e)}async trackAddToCart(e,i){await this.trackEvent(t.ADD_TO_CART,i,e)}getAttributionData(){return this.storage.getUTMData()}addUTMToURL(t){if(!this.config.enableCrossDomainUTM)return t;const e=this.getAttributionData();return e?d(t,g(e.lastTouch,this.config.crossDomainUTMParams)):t}getCurrentUTMParams(){const t=this.getAttributionData();return t?g(t.lastTouch,this.config.crossDomainUTMParams):{}}getUTMParams(){const t=this.getAttributionData();if(!t)return this.logger.debug("No attribution data available for UTM params"),{};const e={utm_source:t.lastTouch.utm_source||null,utm_medium:t.lastTouch.utm_medium||null,utm_campaign:t.lastTouch.utm_campaign||null,utm_term:t.lastTouch.utm_term||null,utm_content:t.lastTouch.utm_content||null},i={};return e.utm_source&&""!==e.utm_source.trim()?i.utm_source=e.utm_source:i.utm_source=null,e.utm_medium&&""!==e.utm_medium.trim()?i.utm_medium=e.utm_medium:i.utm_medium=null,e.utm_campaign&&""!==e.utm_campaign.trim()?i.utm_campaign=e.utm_campaign:i.utm_campaign=null,e.utm_term&&""!==e.utm_term.trim()?i.utm_term=e.utm_term:i.utm_term=null,e.utm_content&&""!==e.utm_content.trim()?i.utm_content=e.utm_content:i.utm_content=null,this.logger.debug("UTM params for event:",i),i}initializeSession(){const t=this.storage.getSession(),e=Date.now();t&&e-t.lastActivity<this.config.sessionTimeout?this.session={...t,lastActivity:e}:this.session={sessionId:`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,startTime:e,lastActivity:e,pageViews:0},this.storage.storeSession(this.session),this.logger.debug("Session initialized:",this.session)}extractAndStoreUTMData(){const t=l(),e=function(t){const e=function(t){const e={};try{new URL(t).searchParams.forEach((t,i)=>{e[i]=t})}catch(t){}return e}(t),i={};return["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(t=>{e[t]&&""!==e[t].trim()&&(i[t]=e[t].trim())}),i}(t);if(this.logger.debug("Extracting UTM params from URL:",t),this.logger.debug("Found UTM params:",e),0===Object.keys(e).length)return void this.logger.debug("No UTM parameters found in URL");const i={utm_source:e.utm_source||"",utm_medium:e.utm_medium||"",utm_campaign:e.utm_campaign||"",utm_term:e.utm_term||"",utm_content:e.utm_content||"",timestamp:Date.now()},r=this.getAttributionData(),n={firstTouch:r?.firstTouch||i,lastTouch:i,touchpoints:r?.touchpoints||[],expiresAt:Date.now()+2592e6};r&&r.lastTouch.utm_source===i.utm_source&&r.lastTouch.utm_campaign===i.utm_campaign||n.touchpoints.push(i),this.storage.storeUTMData(n),this.logger.info("UTM data extracted and stored successfully:",i),this.config.autoCleanUTM&&function(){try{const t=new URL(window.location.href);let e=!1;["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(i=>{t.searchParams.has(i)&&(t.searchParams.delete(i),e=!0)}),e&&window.history.replaceState({},document.title,t.toString())}catch(t){console.warn("Failed to clean URL:",t)}}()}setupAutoTracking(){this.autoTrackEnabled=!0,this.setupFormTracking(),this.setupLinkTracking(),this.logger.info("Auto-tracking enabled")}setupFormTracking(){document.addEventListener("submit",e=>{try{const i=e.target;if(!i)return;const r=this.serializeFormFields(i);this.trackEvent(t.FORM_SUBMIT,{...r,form_id:i.id||i.name,form_action:i.action,form_method:i.method})}catch(t){this.logger.error("Failed to auto-track form submit:",t)}})}serializeFormFields(t){const e={};try{const i=new FormData(t);for(const[t,r]of i.entries()){const i=this.serializeFormValue(r);if(Object.prototype.hasOwnProperty.call(e,t)){const r=e[t];Array.isArray(r)?(r.push(i),e[t]=r):e[t]=[r,i]}else e[t]=i}const r=Array.from(t.elements),n=new Map;for(const t of r){const e=t.name;e&&!t.disabled&&(n.has(e)||n.set(e,[]),n.get(e).push(t))}n.forEach((t,i)=>{const r=t.some(t=>"radio"===t.type),n=t.some(t=>"checkbox"===t.type),a=t.some(t=>"file"===t.type),s=t.some(t=>"SELECT"===t.tagName&&t.multiple),o=t.some(t=>"password"===t.type);if(n){const r=t.filter(t=>"checkbox"===t.type).filter(t=>t.checked).map(t=>t.value||"on");return void(Object.prototype.hasOwnProperty.call(e,i)?Array.isArray(e[i])||(e[i]=[e[i],...r]):e[i]=r)}if(r){const r=t.filter(t=>"radio"===t.type).find(t=>t.checked);return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=r?r.value:null))}if(s){const r=t.find(t=>"SELECT"===t.tagName&&t.multiple);if(r){const t=Array.from(r.selectedOptions).map(t=>t.value);return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=t))}}if(a){const r=t.find(t=>"file"===t.type);if(r){const t=r.files?Array.from(r.files):[];return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=t.map(t=>this.serializeFormValue(t))))}}if(o)Object.prototype.hasOwnProperty.call(e,i)?e[i]="string"==typeof e[i]?"*****":e[i]:e[i]="*****";else if(!Object.prototype.hasOwnProperty.call(e,i)){const r=t[0];if("SELECT"===r.tagName){const t=r;e[i]=t.multiple?Array.from(t.selectedOptions).map(t=>t.value):t.value}else r.type,e[i]=r.value??""}})}catch(t){this.logger.error("Failed to serialize form fields:",t)}return e}serializeFormValue(t){return t instanceof File?{file_name:t.name,file_size:t.size,file_type:t.type}:t}setupLinkTracking(){document.addEventListener("click",t=>{const e=t.target.closest("a");e&&function(t){try{const e=new URL(t),i=window.location.hostname;return e.hostname!==i}catch(t){return!1}}(e.href)&&this.handleCrossDomainUTM(e,t)})}handleCrossDomainUTM(t,e){if(!this.config.enableCrossDomainUTM)return;const i=t.href;if(function(t,e=[]){try{const i=new URL(t).hostname.toLowerCase();return e.some(t=>{const e=t.toLowerCase();return i===e||i.endsWith(`.${e}`)})}catch(t){return!1}}(i,this.config.excludeDomains))return void this.logger.debug(`Domain excluded from UTM passing: ${i}`);const r=this.getAttributionData();if(!r)return void this.logger.debug("No UTM data available for cross-domain passing");const n=g(r.lastTouch,this.config.crossDomainUTMParams);if(0===Object.keys(n).length)return void this.logger.debug("No UTM parameters to pass");const a=d(i,n);a!==i&&(t.href=a,this.logger.debug("UTM parameters added to external link:",{original:i,enhanced:a,utmParams:n}),this.logger.debug("Cross-domain UTM passed:",{link_url:a,original_url:i,utm_params_passed:n}))}setupNetworkHandlers(){window.addEventListener("online",()=>{this.logger.info("Network connection restored"),this.queue.flush()}),window.addEventListener("offline",()=>{this.logger.warn("Network connection lost")})}setupVisibilityHandlers(){document.addEventListener("visibilitychange",()=>{"visible"===document.visibilityState&&this.updateSessionActivity()})}setupBeforeUnloadHandler(){window.addEventListener("beforeunload",()=>{this.updateSessionActivity(),this.queue.flush()})}getCurrentPath(){return"undefined"==typeof window?"":window.location.pathname+window.location.search}setupSPATracking(){if("undefined"==typeof window||"undefined"==typeof history)return void this.logger.warn("⚠️ SPA tracking not available in this environment");if(this.spaTrackingEnabled)return void this.logger.warn("⚠️ SPA tracking already enabled");this.spaTrackingEnabled=!0,this.lastTrackedPath=this.getCurrentPath(),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history);const t=t=>{const e=this.getCurrentPath();e!==this.lastTrackedPath?(this.logger.debug(`🔄 [SPA] Route change detected (${t}): ${this.lastTrackedPath} -> ${e}`),this.lastTrackedPath=e,setTimeout(()=>{this.trackPageView().then(()=>{this.logger.debug(`✅ [SPA] Page view tracked for: ${e}`)}).catch(t=>{this.logger.error("❌ [SPA] Failed to track page view:",t)})},100)):this.logger.debug(`🔄 [SPA] Route change detected (${t}) but path unchanged: ${e}`)};history.pushState=(e,i,r)=>{const n=this.originalPushState(e,i,r);return t("pushState"),n},history.replaceState=(e,i,r)=>{const n=this.originalReplaceState(e,i,r);return t("replaceState"),n},this.popstateHandler=()=>{t("popstate")},window.addEventListener("popstate",this.popstateHandler),this.logger.info("🔄 SPA tracking setup completed")}cleanupSPATracking(){this.spaTrackingEnabled&&(this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null),this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.spaTrackingEnabled=!1,this.logger.info("🔄 SPA tracking cleaned up"))}updateSessionActivity(){this.session&&(this.session.lastActivity=Date.now(),this.storage.storeSession(this.session))}async flush(){await this.queue.flush()}getStatus(){return{initialized:this.initialized,session:this.session,queueSize:this.queue.size(),online:navigator.onLine,crossDomainUTM:{enabled:this.config.enableCrossDomainUTM||!0,currentParams:this.getCurrentUTMParams()},spaTracking:{enabled:this.spaTrackingEnabled,currentPath:this.lastTrackedPath}}}destroy(){this.queue.clear(),this.autoTrackEnabled=!1,this.cleanupSPATracking(),this.initialized=!1,this.logger.info("🗑️ SDK destroyed")}}let v=null;async function _(t){if(v)return console.warn("GetuAI SDK: Already initialized"),v;try{if(v=new T(t),await v.init(),t.enableDebug&&(window.GetuAISDK=v),console.log("GetuAI Attribution SDK initialized successfully"),"undefined"!=typeof window){const t=new CustomEvent("getuaiSDKReady",{detail:{sdk:v}});window.dispatchEvent(t)}return v}catch(t){if(console.error("GetuAI SDK: Failed to initialize:",t),"undefined"!=typeof window){const e=new CustomEvent("getuaiSDKError",{detail:{error:t}});window.dispatchEvent(e)}throw t}}function k(){return v}function E(){return new Promise((t,e)=>{if(v)return void t(v);const i=e=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),t(e.detail.sdk)},r=t=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),e(t.detail.error)};window.addEventListener("getuaiSDKReady",i),window.addEventListener("getuaiSDKError",r),setTimeout(()=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),e(new Error("SDK initialization timeout"))},1e4)})}async function D(t,i,r,n,a=e.USD){const s=k();s?await s.trackEvent(t,i,r,n,a):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function A(t,e){const i=k();i?await i.trackPageView(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function P(t,i,r=e.USD,n){const a=k();a?await a.trackPurchase(t,i,r,n):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function I(t,e){const i=k();i?await i.trackLogin(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function U(t,e){const i=k();i?await i.trackSignup(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function x(t,e){const i=k();i?await i.trackFormSubmit(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function M(t,e){const i=k();i?await i.trackVideoPlay(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function C(t,e){const i=k();i?await i.trackEmailVerification(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function K(t,e){const i=k();i?await i.trackProductView(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function z(t,e){const i=k();i?await i.trackAddToCart(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}function O(){const t=k();return t?t.getAttributionData():null}async function R(){const t=k();t?await t.flush():console.warn("GetuAI SDK: Not initialized. Call init() first.")}function N(){const t=k();return t?t.getStatus():null}function V(t){const e=k();return e?e.addUTMToURL(t):(console.warn("GetuAI SDK: Not initialized. Call init() first."),t)}function L(){const t=k();return t?t.getCurrentUTMParams():{}}function F(){v&&(v.destroy(),v=null,console.log("GetuAI SDK destroyed"))}class G extends T{static async init(t){return await _(t)}static async trackEvent(t,i,r,n,a=e.USD){return await D(t,i,r,n,a)}static async trackPageView(t,e){return await A(t,e)}static async trackPurchase(t,i,r=e.USD,n){return await P(t,i,r,n)}static async trackLogin(t,e){return await I(t,e)}static async trackSignup(t,e){return await U(t,e)}static async trackFormSubmit(t,e){return await x(t,e)}static async trackVideoPlay(t,e){return await M(t,e)}static async trackEmailVerification(t,e){return await C(t,e)}static async trackProductView(t,e){return await K(t,e)}static async trackAddToCart(t,e){return await z(t,e)}static getAttributionData(){return O()}static async flush(){return await R()}static getStatus(){return N()}static addUTMToURL(t){return V(t)}static getCurrentUTMParams(){return L()}static destroy(){F()}static getSDK(){return k()}static waitForSDK(){return E()}}"undefined"!=typeof document&&function(){if(v)return;const t=document.currentScript;if(!t)return void console.warn("GetuAI SDK: Could not find script tag for auto-initialization");const e=t.getAttribute("data-api-key");e?_({apiKey:e,apiEndpoint:t.getAttribute("data-api-endpoint")||n,enableDebug:"true"===t.getAttribute("data-debug"),autoTrack:"true"===t.getAttribute("data-auto-track"),autoTrackPageView:"true"===t.getAttribute("data-auto-track-page-view"),autoCleanUTM:"false"!==t.getAttribute("data-auto-clean-utm"),batchSize:parseInt(t.getAttribute("data-batch-size")||"100"),batchInterval:parseInt(t.getAttribute("data-batch-interval")||"2000")}):console.warn("GetuAI SDK: No API key provided. Please add data-api-key attribute to script tag.")}(),"undefined"!=typeof window&&(window.getuaiSDK={init:_,getSDK:k,waitForSDK:E,trackEvent:D,trackPageView:A,trackPurchase:P,trackLogin:I,trackSignup:U,trackFormSubmit:x,trackVideoPlay:M,trackEmailVerification:C,trackProductView:K,trackAddToCart:z,getAttributionData:O,flush:R,getStatus:N,addUTMToURL:V,getCurrentUTMParams:L,destroy:F,EventType:t,Currency:e,AttributionSDK:G},window.init=_,window.waitForSDK=E,window.trackEvent=D,window.trackPageView=A,window.trackPurchase=P,window.trackLogin=I,window.trackSignup=U,window.trackFormSubmit=x,window.trackVideoPlay=M,window.trackEmailVerification=C,window.trackProductView=K,window.trackAddToCart=z,window.getAttributionData=O,window.flush=R,window.getStatus=N,window.addUTMToURL=V,window.getCurrentUTMParams=L,window.destroy=F,window.AttributionSDK=G);const q={init:_,getSDK:k,waitForSDK:E,trackEvent:D,trackPageView:A,trackPurchase:P,trackLogin:I,trackSignup:U,trackFormSubmit:x,trackVideoPlay:M,trackEmailVerification:C,trackProductView:K,trackAddToCart:z,getAttributionData:O,flush:R,getStatus:N,addUTMToURL:V,getCurrentUTMParams:L,destroy:F,EventType:t,Currency:e,AttributionSDK:G};return r.default})());
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.GetuAIAttribution=e():t.GetuAIAttribution=e()}(this,()=>(()=>{"use strict";var t,e,i={d:(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},r={};i.d(r,{default:()=>$}),function(t){t.PAGE_VIEW="page_view",t.PAGE_CLICK="page_click",t.VIDEO_PLAY="video_play",t.FORM_SUBMIT="form_submit",t.EMAIL_VERIFICATION="email_verification",t.LOGIN="login",t.SIGNUP="signup",t.PRODUCT_VIEW="product_view",t.ADD_TO_CART="add_to_cart",t.PURCHASE="purchase"}(t||(t={})),function(t){t.USD="USD"}(e||(e={}));const n="https://attribution.getu.ai/attribution/api",a=[t.PURCHASE,t.LOGIN,t.SIGNUP,t.FORM_SUBMIT,t.EMAIL_VERIFICATION];function s(){return Math.floor(Date.now()/1e3)}function o(){try{const t="__localStorage_test__";return localStorage.setItem(t,t),localStorage.removeItem(t),!0}catch{return!1}}class c{constructor(t=!0){this.enabled=t}debug(t,...e){this.enabled&&console.debug&&console.debug(`[GetuAI Debug] ${t}`,...e)}info(t,...e){this.enabled&&console.info&&console.info(`[GetuAI Info] ${t}`,...e)}warn(t,...e){this.enabled&&console.warn&&console.warn(`[GetuAI Warn] ${t}`,...e)}error(t,...e){this.enabled&&console.error&&console.error(`[GetuAI Error] ${t}`,...e)}}function u(){return document.referrer||""}function l(){return window.location.href}function h(){return document.title||""}function d(t,e){try{const i=new URL(t);return Object.entries(e).forEach(([t,e])=>{e&&!i.searchParams.has(t)&&i.searchParams.set(t,e)}),i.toString()}catch(e){return t}}function g(t,e=["utm_source","utm_medium","utm_campaign"]){const i={};return e.forEach(e=>{t[e]&&(i[e]=t[e])}),i}function m(t){try{const e=t||window.location.href;return new URL(e).search}catch(t){return""}}function p(t){try{const e=t||window.location.href,i=new URL(e),r={};return i.searchParams.forEach((t,e)=>{r[e]=t}),r}catch(t){return{}}}class w{constructor(t){this.logger=t}get(t){try{if(!o())return this.logger.warn("LocalStorage not supported"),null;const e=localStorage.getItem(t);return null===e?null:JSON.parse(e)}catch(t){return this.logger.error("Error reading from localStorage:",t),null}}set(t,e){try{if(!o())return void this.logger.warn("LocalStorage not supported");localStorage.setItem(t,JSON.stringify(e))}catch(t){this.logger.error("Error writing to localStorage:",t),this.handleQuotaExceeded()}}remove(t){try{o()&&localStorage.removeItem(t)}catch(t){this.logger.error("Error removing from localStorage:",t)}}clear(){try{o()&&localStorage.clear()}catch(t){this.logger.error("Error clearing localStorage:",t)}}handleQuotaExceeded(){try{const t=Object.keys(localStorage).filter(t=>t.startsWith("attribution_"));if(t.length>0){t.sort((t,e)=>{const i=this.get(t),r=this.get(e);return(i?.expiresAt||0)-(r?.expiresAt||0)});const e=Math.ceil(.2*t.length);t.slice(0,e).forEach(t=>{this.remove(t)}),this.logger.info(`Cleaned up ${e} old attribution records`)}}catch(t){this.logger.error("Error during quota cleanup:",t)}}}class f{constructor(t){this.dbName="attribution_events",this.dbVersion=1,this.storeName="events",this.db=null,this.logger=t}async init(){if("indexedDB"in window)return new Promise((t,e)=>{const i=indexedDB.open(this.dbName,this.dbVersion);i.onerror=()=>{this.logger.error("Failed to open IndexedDB:",i.error),e(i.error)},i.onsuccess=()=>{this.db=i.result,this.logger.info("IndexedDB initialized successfully"),t()},i.onupgradeneeded=t=>{const e=t.target.result;if(!e.objectStoreNames.contains(this.storeName)){const t=e.createObjectStore(this.storeName,{keyPath:"id",autoIncrement:!0});t.createIndex("timestamp","timestamp",{unique:!1}),t.createIndex("sent","sent",{unique:!1}),t.createIndex("queued_at","queued_at",{unique:!1})}}});this.logger.warn("IndexedDB not supported")}async addEvent(t){if(!this.db)throw new Error("IndexedDB not initialized");return new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName),n={...t,queued_at:Date.now(),sent:!1},a=r.add(n);a.onsuccess=()=>{this.logger.debug("Event added to IndexedDB queue"),e()},a.onerror=()=>{this.logger.error("Failed to add event to IndexedDB:",a.error),i(a.error)}})}async getUnsentEvents(t=100){return this.db?new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).index("sent").getAll(IDBKeyRange.only(!1),t);r.onsuccess=()=>{const t=r.result.map(t=>{const{queued_at:e,sent:i,...r}=t;return r});e(t)},r.onerror=()=>{this.logger.error("Failed to get unsent events:",r.error),i(r.error)}}):[]}async markEventsAsSent(t){if(this.db&&0!==t.length)return new Promise((e,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName);let n=0,a=!1;t.forEach(s=>{const o=r.get(s);o.onsuccess=()=>{if(o.result){const s={...o.result,sent:!0},c=r.put(s);c.onsuccess=()=>{n++,n!==t.length||a||e()},c.onerror=()=>{a=!0,this.logger.error("Failed to mark event as sent:",c.error),i(c.error)}}else n++,n!==t.length||a||e()},o.onerror=()=>{a=!0,this.logger.error("Failed to get event for marking as sent:",o.error),i(o.error)}})})}async cleanupOldEvents(t=6048e5){if(!this.db)return;const e=Date.now()-t;return new Promise((t,i)=>{const r=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).index("queued_at").openCursor(IDBKeyRange.upperBound(e));r.onsuccess=()=>{const e=r.result;e?(e.delete(),e.continue()):(this.logger.info("Old events cleanup completed"),t())},r.onerror=()=>{this.logger.error("Failed to cleanup old events:",r.error),i(r.error)}})}async getQueueSize(){return this.db?new Promise((t,e)=>{const i=this.db.transaction([this.storeName],"readonly").objectStore(this.storeName).count();i.onsuccess=()=>{t(i.result)},i.onerror=()=>{this.logger.error("Failed to get queue size:",i.error),e(i.error)}}):0}async clear(){if(this.db)return new Promise((t,e)=>{const i=this.db.transaction([this.storeName],"readwrite").objectStore(this.storeName).clear();i.onsuccess=()=>{this.logger.info("IndexedDB queue cleared"),t()},i.onerror=()=>{this.logger.error("Failed to clear IndexedDB queue:",i.error),e(i.error)}})}}class y{constructor(t){this.UTM_STORAGE_KEY="attribution_utm_data",this.SESSION_STORAGE_KEY="attribution_session",this.logger=t,this.localStorage=new w(t),this.indexedDB=new f(t)}async init(){await this.indexedDB.init()}storeUTMData(t){try{const e=this.getUTMData(),i={utm_source:"",utm_medium:"",utm_campaign:"",utm_term:"",utm_content:"",timestamp:Date.now()},r={firstTouch:e?.firstTouch||i,lastTouch:e?.lastTouch||i,touchpoints:e?.touchpoints||[],...t,expiresAt:Date.now()+2592e6};this.localStorage.set(this.UTM_STORAGE_KEY,r),this.logger.debug("UTM data stored successfully:",{firstTouch:r.firstTouch,lastTouch:r.lastTouch,touchpointsCount:r.touchpoints.length,expiresAt:new Date(r.expiresAt).toISOString()})}catch(t){this.logger.error("Failed to store UTM data:",t)}}getUTMData(){const t=this.localStorage.get(this.UTM_STORAGE_KEY);return t&&t.expiresAt&&t.expiresAt>Date.now()?t:(t&&this.localStorage.remove(this.UTM_STORAGE_KEY),null)}storeSession(t){this.localStorage.set(this.SESSION_STORAGE_KEY,t)}getSession(){return this.localStorage.get(this.SESSION_STORAGE_KEY)}async queueEvent(t){try{await this.indexedDB.addEvent(t)}catch(t){throw this.logger.error("Failed to queue event:",t),t}}async getUnsentEvents(t=100){return await this.indexedDB.getUnsentEvents(t)}async markEventsAsSent(t){await this.indexedDB.markEventsAsSent(t)}async getQueueSize(){return await this.indexedDB.getQueueSize()}async cleanupOldEvents(){await this.indexedDB.cleanupOldEvents()}async clearQueue(){await this.indexedDB.clear()}cleanupExpiredData(){this.getUTMData()}}class S{constructor(t,e,i,r=100,n=2e3,a=3,s=1e3,o){this.queue=[],this.processing=!1,this.batchTimer=null,this.logger=t,this.apiKey=e,this.apiEndpoint=i,this.batchSize=r,this.batchInterval=n,this.maxRetries=a,this.retryDelay=s,this.sendEvents=o,this.debouncedProcess=function(t){let e;return(...i)=>{clearTimeout(e),e=setTimeout(()=>t(...i),100)}}(this.process.bind(this))}add(t){this.queue.push(t),this.logger.debug(`Event added to queue: ${t.event_type}`),a.includes(t.event_type)?(this.logger.debug(`Immediate event detected: ${t.event_type}, processing immediately`),this.processImmediate(t)):this.scheduleBatchProcessing()}async process(){if(!this.processing&&0!==this.queue.length){this.processing=!0;try{const t=this.queue.splice(0,this.batchSize);this.logger.debug(`Processing ${t.length} events from queue`),await this.sendEvents(t),this.logger.info(`Successfully processed ${t.length} events`)}catch(t){this.logger.error("Failed to process events:",t);const e=this.queue.splice(0,this.batchSize);return this.queue.unshift(...e),void setTimeout(()=>{this.processing=!1,this.debouncedProcess()},this.retryDelay)}this.processing=!1,this.queue.length>0&&this.debouncedProcess()}}async processImmediate(t){try{this.logger.debug(`Processing immediate event: ${t.event_type}`),await this.sendEvents([t]),this.logger.info(`Immediate event processed successfully: ${t.event_type}`)}catch(e){this.logger.error(`Failed to process immediate event: ${t.event_type}`,e),this.queue.unshift(t)}}scheduleBatchProcessing(){this.batchTimer&&clearTimeout(this.batchTimer),this.batchTimer=setTimeout(()=>{this.debouncedProcess()},this.batchInterval)}clear(){this.queue=[],this.batchTimer&&(clearTimeout(this.batchTimer),this.batchTimer=null),this.processing=!1,this.logger.info("Event queue cleared")}size(){return this.queue.length}getStats(){return{size:this.queue.length,processing:this.processing}}async flush(){for(this.logger.info("Flushing event queue");this.queue.length>0;)await this.process()}}class b{constructor(t,e,i,r=3,n=1e3){this.logger=t,this.apiKey=e,this.apiEndpoint=i,this.maxRetries=r,this.retryDelay=n}async sendEvents(t){if(0===t.length)return;const e={events:t.map(t=>({event_id:t.event_id,event_type:t.event_type,tracking_user_id:t.tracking_user_id,utm_source:t.utm_source||null,utm_medium:t.utm_medium||null,utm_campaign:t.utm_campaign||null,utm_term:t.utm_term||null,utm_content:t.utm_content||null,revenue:t.revenue||null,currency:t.currency||null,event_data:t.event_data||null,context:t.context||null,timestamp:t.timestamp||s()})),sdk_version:"2.0.0"};await async function(t,e=3,i=1e3){let r;for(let n=0;n<=e;n++)try{return await t()}catch(t){if(r=t,n===e)throw r;const a=i*Math.pow(2,n);await new Promise(t=>setTimeout(t,a))}throw r}(async()=>{const i=await fetch(`${this.apiEndpoint}/attribution/events`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`},body:JSON.stringify(e)});if(!i.ok){const t=await i.text();throw new Error(`HTTP ${i.status}: ${t}`)}const r=await i.json();return this.logger.debug("Events sent successfully:",r),{result:r,sentEvents:t}},this.maxRetries,this.retryDelay)}async sendSingleEvent(t){await this.sendEvents([t])}async testConnection(){try{return(await fetch(`${this.apiEndpoint}/health`,{method:"GET",headers:{Authorization:`Bearer ${this.apiKey}`}})).ok}catch(t){return this.logger.error("Connection test failed:",t),!1}}}class T{constructor(t){this.session=null,this.initialized=!1,this.autoTrackEnabled=!1,this.pageViewTrackTimes=new Map,this.spaTrackingEnabled=!1,this.lastTrackedPath="",this.originalPushState=null,this.originalReplaceState=null,this.popstateHandler=null,this.config={apiEndpoint:n,batchSize:100,batchInterval:2e3,maxRetries:3,retryDelay:1e3,enableDebug:!1,autoTrack:!1,autoTrackPageView:!1,sessionTimeout:18e5,enableCrossDomainUTM:!0,crossDomainUTMParams:["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],excludeDomains:[],autoCleanUTM:!0,pageViewDebounceInterval:5e3,...t},this.logger=new c(this.config.enableDebug),this.storage=new y(this.logger),this.httpClient=new b(this.logger,this.config.apiKey,this.config.apiEndpoint||n,this.config.maxRetries,this.config.retryDelay),this.queue=new S(this.logger,this.config.apiKey,this.config.apiEndpoint||n,this.config.batchSize,this.config.batchInterval,this.config.maxRetries,this.config.retryDelay,t=>this.httpClient.sendEvents(t))}async init(){if(this.initialized)this.logger.warn("SDK already initialized");else try{this.logger.info("Initializing GetuAI Attribution SDK"),await this.storage.init(),this.initializeSession(),this.extractAndStoreUTMData(),this.config.autoTrack&&this.setupAutoTracking(),this.setupNetworkHandlers(),this.setupVisibilityHandlers(),this.setupBeforeUnloadHandler(),this.initialized=!0,this.logger.info("🚀 GetuAI Attribution SDK initialized successfully"),this.logger.info("📄 Auto track page view = "+this.config.autoTrackPageView),this.config.autoTrackPageView&&(this.logger.info("📄 Auto track page view enabled (including SPA route tracking)"),this.lastTrackedPath=this.getCurrentPath(),this.setupSPATracking(),setTimeout(()=>{this.trackPageView().then(()=>{this.logger.info("✅ Auto track page view completed")}).catch(t=>this.logger.error("❌ Auto track page view failed:",t))},100))}catch(t){throw this.logger.error("Failed to initialize SDK:",t),t}}async trackEvent(t,i,r,n,a=e.USD){if(this.initialized)try{const e=l();let o=null;try{o=await this.fetchPublicIP()}catch(t){}const c={domain:"undefined"!=typeof window?window.location.hostname:null,path:"undefined"!=typeof window?window.location.pathname:null,title:h(),referrer:u(),url:e.split("?")[0],querystring:m(e),query_params:p(e),ip_address:o},d={session_id:this.session?.sessionId,start_time:this.session?.startTime,last_activity:this.session?.lastActivity,page_views:this.session?.pageViews},g={event_id:"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),event_type:t,tracking_user_id:r,timestamp:s(),event_data:i,context:{page:c,session:d},revenue:n,currency:a,...this.getUTMParams()};this.logger.debug(`Tracking event: ${t}`,g),this.queue.add(g)}catch(e){this.logger.error(`Failed to track event ${t}:`,e)}else this.logger.warn("SDK not initialized, event not tracked")}async trackPageView(e,i){const r=l(),n=r.split("?")[0],a=Date.now(),s=this.config.pageViewDebounceInterval||5e3,o=this.pageViewTrackTimes.get(n);if(o&&a-o<s)return void this.logger.debug(`Page view debounced: ${n} (last tracked ${a-o}ms ago)`);const c={url:r,title:h(),referrer:u(),user_agent:navigator.userAgent||"",...e};await this.trackEvent(t.PAGE_VIEW,c,i),this.pageViewTrackTimes.set(n,a),this.cleanupPageViewTrackTimes()}cleanupPageViewTrackTimes(){const t=Date.now()-36e5;for(const[e,i]of this.pageViewTrackTimes.entries())i<t&&this.pageViewTrackTimes.delete(e)}async fetchPublicIP(){try{const t=new AbortController,e=setTimeout(()=>t.abort(),2e3),i=await fetch("https://api.ipify.org?format=json",{signal:t.signal,headers:{Accept:"application/json"}});if(clearTimeout(e),!i.ok)return null;const r=await i.json();return"string"==typeof r?.ip?r.ip:null}catch(t){return this.logger.debug("Public IP fetch failed",t),null}}async trackPurchase(i,r,n=e.USD,a){await this.trackEvent(t.PURCHASE,a,i,r,n)}async trackLogin(e,i){await this.trackEvent(t.LOGIN,i,e)}async trackSignup(e,i){await this.trackEvent(t.SIGNUP,i,e)}async trackFormSubmit(e,i){await this.trackEvent(t.FORM_SUBMIT,i,e)}async trackVideoPlay(e,i){await this.trackEvent(t.VIDEO_PLAY,i,e)}async trackEmailVerification(e,i){await this.trackEvent(t.EMAIL_VERIFICATION,i,e)}async trackProductView(e,i){await this.trackEvent(t.PRODUCT_VIEW,i,e)}async trackAddToCart(e,i){await this.trackEvent(t.ADD_TO_CART,i,e)}async trackPageClick(e,i){await this.trackEvent(t.PAGE_CLICK,i,e)}getAttributionData(){return this.storage.getUTMData()}addUTMToURL(t){if(!this.config.enableCrossDomainUTM)return t;const e=this.getAttributionData();return e?d(t,g(e.lastTouch,this.config.crossDomainUTMParams)):t}getCurrentUTMParams(){const t=this.getAttributionData();return t?g(t.lastTouch,this.config.crossDomainUTMParams):{}}getUTMParams(){const t=this.getAttributionData();if(!t)return this.logger.debug("No attribution data available for UTM params"),{};const e={utm_source:t.lastTouch.utm_source||null,utm_medium:t.lastTouch.utm_medium||null,utm_campaign:t.lastTouch.utm_campaign||null,utm_term:t.lastTouch.utm_term||null,utm_content:t.lastTouch.utm_content||null},i={};return e.utm_source&&""!==e.utm_source.trim()?i.utm_source=e.utm_source:i.utm_source=null,e.utm_medium&&""!==e.utm_medium.trim()?i.utm_medium=e.utm_medium:i.utm_medium=null,e.utm_campaign&&""!==e.utm_campaign.trim()?i.utm_campaign=e.utm_campaign:i.utm_campaign=null,e.utm_term&&""!==e.utm_term.trim()?i.utm_term=e.utm_term:i.utm_term=null,e.utm_content&&""!==e.utm_content.trim()?i.utm_content=e.utm_content:i.utm_content=null,this.logger.debug("UTM params for event:",i),i}initializeSession(){const t=this.storage.getSession(),e=Date.now();t&&e-t.lastActivity<this.config.sessionTimeout?this.session={...t,lastActivity:e}:this.session={sessionId:`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,startTime:e,lastActivity:e,pageViews:0},this.storage.storeSession(this.session),this.logger.debug("Session initialized:",this.session)}extractAndStoreUTMData(){const t=l(),e=function(t){const e=function(t){const e={};try{new URL(t).searchParams.forEach((t,i)=>{e[i]=t})}catch(t){}return e}(t),i={};return["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(t=>{e[t]&&""!==e[t].trim()&&(i[t]=e[t].trim())}),i}(t);if(this.logger.debug("Extracting UTM params from URL:",t),this.logger.debug("Found UTM params:",e),0===Object.keys(e).length)return void this.logger.debug("No UTM parameters found in URL");const i={utm_source:e.utm_source||"",utm_medium:e.utm_medium||"",utm_campaign:e.utm_campaign||"",utm_term:e.utm_term||"",utm_content:e.utm_content||"",timestamp:Date.now()},r=this.getAttributionData(),n={firstTouch:r?.firstTouch||i,lastTouch:i,touchpoints:r?.touchpoints||[],expiresAt:Date.now()+2592e6};r&&r.lastTouch.utm_source===i.utm_source&&r.lastTouch.utm_campaign===i.utm_campaign||n.touchpoints.push(i),this.storage.storeUTMData(n),this.logger.info("UTM data extracted and stored successfully:",i),this.config.autoCleanUTM&&function(){try{const t=new URL(window.location.href);let e=!1;["utm_source","utm_medium","utm_campaign","utm_term","utm_content"].forEach(i=>{t.searchParams.has(i)&&(t.searchParams.delete(i),e=!0)}),e&&window.history.replaceState({},document.title,t.toString())}catch(t){console.warn("Failed to clean URL:",t)}}()}setupAutoTracking(){this.autoTrackEnabled=!0,this.setupFormTracking(),this.setupLinkTracking(),this.logger.info("Auto-tracking enabled")}setupFormTracking(){document.addEventListener("submit",e=>{try{const i=e.target;if(!i)return;const r=this.serializeFormFields(i);this.trackEvent(t.FORM_SUBMIT,{...r,form_id:i.id||i.name,form_action:i.action,form_method:i.method})}catch(t){this.logger.error("Failed to auto-track form submit:",t)}})}serializeFormFields(t){const e={};try{const i=new FormData(t);for(const[t,r]of i.entries()){const i=this.serializeFormValue(r);if(Object.prototype.hasOwnProperty.call(e,t)){const r=e[t];Array.isArray(r)?(r.push(i),e[t]=r):e[t]=[r,i]}else e[t]=i}const r=Array.from(t.elements),n=new Map;for(const t of r){const e=t.name;e&&!t.disabled&&(n.has(e)||n.set(e,[]),n.get(e).push(t))}n.forEach((t,i)=>{const r=t.some(t=>"radio"===t.type),n=t.some(t=>"checkbox"===t.type),a=t.some(t=>"file"===t.type),s=t.some(t=>"SELECT"===t.tagName&&t.multiple),o=t.some(t=>"password"===t.type);if(n){const r=t.filter(t=>"checkbox"===t.type).filter(t=>t.checked).map(t=>t.value||"on");return void(Object.prototype.hasOwnProperty.call(e,i)?Array.isArray(e[i])||(e[i]=[e[i],...r]):e[i]=r)}if(r){const r=t.filter(t=>"radio"===t.type).find(t=>t.checked);return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=r?r.value:null))}if(s){const r=t.find(t=>"SELECT"===t.tagName&&t.multiple);if(r){const t=Array.from(r.selectedOptions).map(t=>t.value);return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=t))}}if(a){const r=t.find(t=>"file"===t.type);if(r){const t=r.files?Array.from(r.files):[];return void(Object.prototype.hasOwnProperty.call(e,i)||(e[i]=t.map(t=>this.serializeFormValue(t))))}}if(o)Object.prototype.hasOwnProperty.call(e,i)?e[i]="string"==typeof e[i]?"*****":e[i]:e[i]="*****";else if(!Object.prototype.hasOwnProperty.call(e,i)){const r=t[0];if("SELECT"===r.tagName){const t=r;e[i]=t.multiple?Array.from(t.selectedOptions).map(t=>t.value):t.value}else r.type,e[i]=r.value??""}})}catch(t){this.logger.error("Failed to serialize form fields:",t)}return e}serializeFormValue(t){return t instanceof File?{file_name:t.name,file_size:t.size,file_type:t.type}:t}setupLinkTracking(){document.addEventListener("click",t=>{const e=t.target.closest("a");e&&function(t){try{const e=new URL(t),i=window.location.hostname;return e.hostname!==i}catch(t){return!1}}(e.href)&&this.handleCrossDomainUTM(e,t)})}handleCrossDomainUTM(t,e){if(!this.config.enableCrossDomainUTM)return;const i=t.href;if(function(t,e=[]){try{const i=new URL(t).hostname.toLowerCase();return e.some(t=>{const e=t.toLowerCase();return i===e||i.endsWith(`.${e}`)})}catch(t){return!1}}(i,this.config.excludeDomains))return void this.logger.debug(`Domain excluded from UTM passing: ${i}`);const r=this.getAttributionData();if(!r)return void this.logger.debug("No UTM data available for cross-domain passing");const n=g(r.lastTouch,this.config.crossDomainUTMParams);if(0===Object.keys(n).length)return void this.logger.debug("No UTM parameters to pass");const a=d(i,n);a!==i&&(t.href=a,this.logger.debug("UTM parameters added to external link:",{original:i,enhanced:a,utmParams:n}),this.logger.debug("Cross-domain UTM passed:",{link_url:a,original_url:i,utm_params_passed:n}))}setupNetworkHandlers(){window.addEventListener("online",()=>{this.logger.info("Network connection restored"),this.queue.flush()}),window.addEventListener("offline",()=>{this.logger.warn("Network connection lost")})}setupVisibilityHandlers(){document.addEventListener("visibilitychange",()=>{"visible"===document.visibilityState&&this.updateSessionActivity()})}setupBeforeUnloadHandler(){window.addEventListener("beforeunload",()=>{this.updateSessionActivity(),this.queue.flush()})}getCurrentPath(){return"undefined"==typeof window?"":window.location.pathname+window.location.search}setupSPATracking(){if("undefined"==typeof window||"undefined"==typeof history)return void this.logger.warn("⚠️ SPA tracking not available in this environment");if(this.spaTrackingEnabled)return void this.logger.warn("⚠️ SPA tracking already enabled");this.spaTrackingEnabled=!0,this.lastTrackedPath=this.getCurrentPath(),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history);const t=t=>{const e=this.getCurrentPath();e!==this.lastTrackedPath?(this.logger.debug(`🔄 [SPA] Route change detected (${t}): ${this.lastTrackedPath} -> ${e}`),this.lastTrackedPath=e,setTimeout(()=>{this.trackPageView().then(()=>{this.logger.debug(`✅ [SPA] Page view tracked for: ${e}`)}).catch(t=>{this.logger.error("❌ [SPA] Failed to track page view:",t)})},100)):this.logger.debug(`🔄 [SPA] Route change detected (${t}) but path unchanged: ${e}`)};history.pushState=(e,i,r)=>{const n=this.originalPushState(e,i,r);return t("pushState"),n},history.replaceState=(e,i,r)=>{const n=this.originalReplaceState(e,i,r);return t("replaceState"),n},this.popstateHandler=()=>{t("popstate")},window.addEventListener("popstate",this.popstateHandler),this.logger.info("🔄 SPA tracking setup completed")}cleanupSPATracking(){this.spaTrackingEnabled&&(this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null),this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.spaTrackingEnabled=!1,this.logger.info("🔄 SPA tracking cleaned up"))}updateSessionActivity(){this.session&&(this.session.lastActivity=Date.now(),this.storage.storeSession(this.session))}async flush(){await this.queue.flush()}getStatus(){return{initialized:this.initialized,session:this.session,queueSize:this.queue.size(),online:navigator.onLine,crossDomainUTM:{enabled:this.config.enableCrossDomainUTM||!0,currentParams:this.getCurrentUTMParams()},spaTracking:{enabled:this.spaTrackingEnabled,currentPath:this.lastTrackedPath}}}destroy(){this.queue.clear(),this.autoTrackEnabled=!1,this.cleanupSPATracking(),this.initialized=!1,this.logger.info("🗑️ SDK destroyed")}}let v=null;async function k(t){if(v)return console.warn("GetuAI SDK: Already initialized"),v;try{if(v=new T(t),await v.init(),t.enableDebug&&(window.GetuAISDK=v),console.log("GetuAI Attribution SDK initialized successfully"),"undefined"!=typeof window){const t=new CustomEvent("getuaiSDKReady",{detail:{sdk:v}});window.dispatchEvent(t)}return v}catch(t){if(console.error("GetuAI SDK: Failed to initialize:",t),"undefined"!=typeof window){const e=new CustomEvent("getuaiSDKError",{detail:{error:t}});window.dispatchEvent(e)}throw t}}function _(){return v}function E(){return new Promise((t,e)=>{if(v)return void t(v);const i=e=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),t(e.detail.sdk)},r=t=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),e(t.detail.error)};window.addEventListener("getuaiSDKReady",i),window.addEventListener("getuaiSDKError",r),setTimeout(()=>{window.removeEventListener("getuaiSDKReady",i),window.removeEventListener("getuaiSDKError",r),e(new Error("SDK initialization timeout"))},1e4)})}async function D(t,i,r,n,a=e.USD){const s=_();s?await s.trackEvent(t,i,r,n,a):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function A(t,e){const i=_();i?await i.trackPageView(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function P(t,i,r=e.USD,n){const a=_();a?await a.trackPurchase(t,i,r,n):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function I(t,e){const i=_();i?await i.trackLogin(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function U(t,e){const i=_();i?await i.trackSignup(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function x(t,e){const i=_();i?await i.trackFormSubmit(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function C(t,e){const i=_();i?await i.trackVideoPlay(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function M(t,e){const i=_();i?await i.trackEmailVerification(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function K(t,e){const i=_();i?await i.trackProductView(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function z(t,e){const i=_();i?await i.trackAddToCart(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}async function O(t,e){const i=_();i?await i.trackPageClick(t,e):console.warn("GetuAI SDK: Not initialized. Call init() first.")}function L(){const t=_();return t?t.getAttributionData():null}async function N(){const t=_();t?await t.flush():console.warn("GetuAI SDK: Not initialized. Call init() first.")}function R(){const t=_();return t?t.getStatus():null}function V(t){const e=_();return e?e.addUTMToURL(t):(console.warn("GetuAI SDK: Not initialized. Call init() first."),t)}function F(){const t=_();return t?t.getCurrentUTMParams():{}}function G(){v&&(v.destroy(),v=null,console.log("GetuAI SDK destroyed"))}class q extends T{static async init(t){return await k(t)}static async trackEvent(t,i,r,n,a=e.USD){return await D(t,i,r,n,a)}static async trackPageView(t,e){return await A(t,e)}static async trackPurchase(t,i,r=e.USD,n){return await P(t,i,r,n)}static async trackLogin(t,e){return await I(t,e)}static async trackSignup(t,e){return await U(t,e)}static async trackFormSubmit(t,e){return await x(t,e)}static async trackVideoPlay(t,e){return await C(t,e)}static async trackEmailVerification(t,e){return await M(t,e)}static async trackProductView(t,e){return await K(t,e)}static async trackAddToCart(t,e){return await z(t,e)}static async trackPageClick(t,e){return await O(t,e)}static getAttributionData(){return L()}static async flush(){return await N()}static getStatus(){return R()}static addUTMToURL(t){return V(t)}static getCurrentUTMParams(){return F()}static destroy(){G()}static getSDK(){return _()}static waitForSDK(){return E()}}"undefined"!=typeof document&&function(){if(v)return;const t=document.currentScript;if(!t)return void console.warn("GetuAI SDK: Could not find script tag for auto-initialization");const e=t.getAttribute("data-api-key");e?k({apiKey:e,apiEndpoint:t.getAttribute("data-api-endpoint")||n,enableDebug:"true"===t.getAttribute("data-debug"),autoTrack:"true"===t.getAttribute("data-auto-track"),autoTrackPageView:"true"===t.getAttribute("data-auto-track-page-view"),autoCleanUTM:"false"!==t.getAttribute("data-auto-clean-utm"),batchSize:parseInt(t.getAttribute("data-batch-size")||"100"),batchInterval:parseInt(t.getAttribute("data-batch-interval")||"2000")}):console.warn("GetuAI SDK: No API key provided. Please add data-api-key attribute to script tag.")}(),"undefined"!=typeof window&&(window.getuaiSDK={init:k,getSDK:_,waitForSDK:E,trackEvent:D,trackPageView:A,trackPageClick:O,trackPurchase:P,trackLogin:I,trackSignup:U,trackFormSubmit:x,trackVideoPlay:C,trackEmailVerification:M,trackProductView:K,trackAddToCart:z,getAttributionData:L,flush:N,getStatus:R,addUTMToURL:V,getCurrentUTMParams:F,destroy:G,EventType:t,Currency:e,AttributionSDK:q},window.init=k,window.waitForSDK=E,window.trackEvent=D,window.trackPageView=A,window.trackPageClick=O,window.trackPurchase=P,window.trackLogin=I,window.trackSignup=U,window.trackFormSubmit=x,window.trackVideoPlay=C,window.trackEmailVerification=M,window.trackProductView=K,window.trackAddToCart=z,window.getAttributionData=L,window.flush=N,window.getStatus=R,window.addUTMToURL=V,window.getCurrentUTMParams=F,window.destroy=G,window.AttributionSDK=q);const $={init:k,getSDK:_,waitForSDK:E,trackEvent:D,trackPageView:A,trackPageClick:O,trackPurchase:P,trackLogin:I,trackSignup:U,trackFormSubmit:x,trackVideoPlay:C,trackEmailVerification:M,trackProductView:K,trackAddToCart:z,getAttributionData:L,flush:N,getStatus:R,addUTMToURL:V,getCurrentUTMParams:F,destroy:G,EventType:t,Currency:e,AttributionSDK:q};return r.default})());
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ declare function trackVideoPlay(tracking_user_id?: string, videoData?: Record<st
13
13
  declare function trackEmailVerification(tracking_user_id: string, verificationData?: Record<string, any>): Promise<void>;
14
14
  declare function trackProductView(tracking_user_id?: string, productData?: Record<string, any>): Promise<void>;
15
15
  declare function trackAddToCart(tracking_user_id?: string, cartData?: Record<string, any>): Promise<void>;
16
+ declare function trackPageClick(tracking_user_id?: string, clickData?: Record<string, any>): Promise<void>;
16
17
  declare function getAttributionData(): AttributionData | null;
17
18
  declare function flush(): Promise<void>;
18
19
  declare function getStatus(): {
@@ -44,6 +45,7 @@ declare class AttributionSDKStatic extends AttributionSDK {
44
45
  static trackEmailVerification(tracking_user_id: string, verificationData?: Record<string, any>): Promise<void>;
45
46
  static trackProductView(tracking_user_id?: string, productData?: Record<string, any>): Promise<void>;
46
47
  static trackAddToCart(tracking_user_id?: string, cartData?: Record<string, any>): Promise<void>;
48
+ static trackPageClick(tracking_user_id?: string, clickData?: Record<string, any>): Promise<void>;
47
49
  static getAttributionData(): AttributionData | null;
48
50
  static flush(): Promise<void>;
49
51
  static getStatus(): {
@@ -67,7 +69,7 @@ declare class AttributionSDKStatic extends AttributionSDK {
67
69
  static waitForSDK(): Promise<AttributionSDK>;
68
70
  }
69
71
  export { EventType, Currency, type SDKConfig, type EventData, type AttributionData, };
70
- export { init, getSDK, waitForSDK, trackEvent, trackPageView, trackPurchase, trackLogin, trackSignup, trackFormSubmit, trackVideoPlay, trackEmailVerification, trackProductView, trackAddToCart, getAttributionData, flush, getStatus, addUTMToURL, getCurrentUTMParams, destroy, };
72
+ export { init, getSDK, waitForSDK, trackEvent, trackPageView, trackPageClick, trackPurchase, trackLogin, trackSignup, trackFormSubmit, trackVideoPlay, trackEmailVerification, trackProductView, trackAddToCart, getAttributionData, flush, getStatus, addUTMToURL, getCurrentUTMParams, destroy, };
71
73
  export { AttributionSDKStatic as AttributionSDK };
72
74
  declare const _default: {
73
75
  init: typeof init;
@@ -75,6 +77,7 @@ declare const _default: {
75
77
  waitForSDK: typeof waitForSDK;
76
78
  trackEvent: typeof trackEvent;
77
79
  trackPageView: typeof trackPageView;
80
+ trackPageClick: typeof trackPageClick;
78
81
  trackPurchase: typeof trackPurchase;
79
82
  trackLogin: typeof trackLogin;
80
83
  trackSignup: typeof trackSignup;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -3,6 +3,7 @@ var EventType;
3
3
  (function (EventType) {
4
4
  // Pre-conversion signals
5
5
  EventType["PAGE_VIEW"] = "page_view";
6
+ EventType["PAGE_CLICK"] = "page_click";
6
7
  EventType["VIDEO_PLAY"] = "video_play";
7
8
  // Registration funnel
8
9
  EventType["FORM_SUBMIT"] = "form_submit";
@@ -637,6 +638,12 @@ class AttributionStorageManager {
637
638
  }
638
639
  }
639
640
 
641
+ /**
642
+ * SDK Version
643
+ * This version should match the version in package.json
644
+ */
645
+ const SDK_VERSION = "2.0.0";
646
+
640
647
  class EventQueueManager {
641
648
  constructor(logger, apiKey, apiEndpoint, batchSize = 100, batchInterval = 2000, maxRetries = 3, retryDelay = 1000, sendEvents) {
642
649
  this.queue = [];
@@ -774,7 +781,10 @@ class EventHttpClient {
774
781
  context: event.context || null,
775
782
  timestamp: event.timestamp || getTimestamp(), // Convert to seconds
776
783
  }));
777
- const batchRequest = { events: transformedEvents };
784
+ const batchRequest = {
785
+ events: transformedEvents,
786
+ sdk_version: SDK_VERSION,
787
+ };
778
788
  await retry(async () => {
779
789
  const response = await fetch(`${this.apiEndpoint}/attribution/events`, {
780
790
  method: "POST",
@@ -1044,6 +1054,10 @@ class AttributionSDK {
1044
1054
  async trackAddToCart(tracking_user_id, cartData) {
1045
1055
  await this.trackEvent(EventType.ADD_TO_CART, cartData, tracking_user_id);
1046
1056
  }
1057
+ // Track page click for user click journey
1058
+ async trackPageClick(tracking_user_id, clickData) {
1059
+ await this.trackEvent(EventType.PAGE_CLICK, clickData, tracking_user_id);
1060
+ }
1047
1061
  // Get attribution data
1048
1062
  getAttributionData() {
1049
1063
  return this.storage.getUTMData();
@@ -1727,6 +1741,15 @@ async function trackAddToCart(tracking_user_id, cartData) {
1727
1741
  }
1728
1742
  await sdk.trackAddToCart(tracking_user_id, cartData);
1729
1743
  }
1744
+ // Track page click for user click journey
1745
+ async function trackPageClick(tracking_user_id, clickData) {
1746
+ const sdk = getSDK();
1747
+ if (!sdk) {
1748
+ console.warn("GetuAI SDK: Not initialized. Call init() first.");
1749
+ return;
1750
+ }
1751
+ await sdk.trackPageClick(tracking_user_id, clickData);
1752
+ }
1730
1753
  // Get attribution data
1731
1754
  function getAttributionData() {
1732
1755
  const sdk = getSDK();
@@ -1823,6 +1846,10 @@ class AttributionSDKStatic extends AttributionSDK {
1823
1846
  static async trackAddToCart(tracking_user_id, cartData) {
1824
1847
  return await trackAddToCart(tracking_user_id, cartData);
1825
1848
  }
1849
+ // Static method to track page click
1850
+ static async trackPageClick(tracking_user_id, clickData) {
1851
+ return await trackPageClick(tracking_user_id, clickData);
1852
+ }
1826
1853
  // Static method to get attribution data
1827
1854
  static getAttributionData() {
1828
1855
  return getAttributionData();
@@ -1870,6 +1897,7 @@ if (typeof window !== "undefined") {
1870
1897
  waitForSDK,
1871
1898
  trackEvent,
1872
1899
  trackPageView,
1900
+ trackPageClick,
1873
1901
  trackPurchase,
1874
1902
  trackLogin,
1875
1903
  trackSignup,
@@ -1893,6 +1921,7 @@ if (typeof window !== "undefined") {
1893
1921
  window.waitForSDK = waitForSDK;
1894
1922
  window.trackEvent = trackEvent;
1895
1923
  window.trackPageView = trackPageView;
1924
+ window.trackPageClick = trackPageClick;
1896
1925
  window.trackPurchase = trackPurchase;
1897
1926
  window.trackLogin = trackLogin;
1898
1927
  window.trackSignup = trackSignup;
@@ -1916,6 +1945,7 @@ var index = {
1916
1945
  waitForSDK,
1917
1946
  trackEvent,
1918
1947
  trackPageView,
1948
+ trackPageClick,
1919
1949
  trackPurchase,
1920
1950
  trackLogin,
1921
1951
  trackSignup,
@@ -1935,5 +1965,5 @@ var index = {
1935
1965
  AttributionSDK: AttributionSDKStatic, // 包含带静态方法的AttributionSDK类
1936
1966
  };
1937
1967
 
1938
- export { AttributionSDKStatic as AttributionSDK, Currency, EventType, addUTMToURL, index as default, destroy, flush, getAttributionData, getCurrentUTMParams, getSDK, getStatus, init, trackAddToCart, trackEmailVerification, trackEvent, trackFormSubmit, trackLogin, trackPageView, trackProductView, trackPurchase, trackSignup, trackVideoPlay, waitForSDK };
1968
+ export { AttributionSDKStatic as AttributionSDK, Currency, EventType, addUTMToURL, index as default, destroy, flush, getAttributionData, getCurrentUTMParams, getSDK, getStatus, init, trackAddToCart, trackEmailVerification, trackEvent, trackFormSubmit, trackLogin, trackPageClick, trackPageView, trackProductView, trackPurchase, trackSignup, trackVideoPlay, waitForSDK };
1939
1969
  //# sourceMappingURL=index.esm.js.map