UNPKG

@click-chutney/analytics

Version:

Complete website analytics solution. Everything you need to understand your visitors - no Google Analytics required.

4 lines (3 loc) 9.61 kB
"use client"; import{useState as e,useEffect as t}from"react";class i{static isLocalStorageAvailable(){if("undefined"==typeof window||"undefined"==typeof localStorage)return!1;try{const e="__cc_test__";return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch{return!1}}static get(e){if(!this.isLocalStorageAvailable())return null;try{return localStorage.getItem(e)}catch{return null}}static set(e,t){if(this.isLocalStorageAvailable())try{localStorage.setItem(e,t)}catch{}}static remove(e){if(this.isLocalStorageAvailable())try{localStorage.removeItem(e)}catch{}}}function n(){return`cc_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}function s(){return"undefined"==typeof window?"":window.location.href}function o(){return"undefined"==typeof window?"":window.location.hostname}function a(){return"undefined"==typeof document?"":document.referrer}class r{static getSession(){const e=i.get(this.SESSION_KEY);if(!e)return null;try{const t=JSON.parse(e);return Date.now()-t.lastActivity>this.SESSION_TIMEOUT?(this.clearSession(),null):t}catch{return this.clearSession(),null}}static createSession(){const e={id:n(),startTime:Date.now(),lastActivity:Date.now(),pageViews:0,events:0,isActive:!0};return this.saveSession(e),e}static updateSession(e){const t={...this.getSession()||this.createSession(),...e,lastActivity:Date.now()};return this.saveSession(t),t}static saveSession(e){i.set(this.SESSION_KEY,JSON.stringify(e))}static clearSession(){i.remove(this.SESSION_KEY)}}r.SESSION_KEY="__cc_session__",r.sessionTimeout=18e5,r.currentSession=null,r.SESSION_TIMEOUT=18e5;class c{static getUser(){const e=i.get(this.USER_KEY);if(!e)return null;try{return JSON.parse(e)}catch{return null}}static setUser(e){const t=this.getUser()||{},n=Date.now(),s={...t,...e,firstSeen:t.firstSeen||n,lastSeen:n};i.set(this.USER_KEY,JSON.stringify(s))}static clearUser(){i.remove(this.USER_KEY)}}c.USER_KEY="__cc_user__";class d{constructor(e){this.eventQueue=[],this.isInitialized=!1,this.config={debug:!1,autoTrack:!0,sessionTimeout:18e5,apiUrl:e.apiUrl||"https://qpbibuv2t3.execute-api.ap-south-1.amazonaws.com/v1/tracker",...e},this.config.debug&&console.log(`🚀 ClickChutney Analytics Initialized\n• Tracking ID: ${this.config.trackingId}\n• API URL: ${this.config.apiUrl}\n• Auto-tracking: ${this.config.autoTrack?"enabled":"disabled"}\n• Ready to track events!`),this.log("Initializing ClickChutney tracker",this.config),this.initialize()}initialize(){if(this.isInitialized)return;if("undefined"==typeof window||"undefined"==typeof document)return void this.log("Skipping initialization - not in browser environment");r.getSession()||r.createSession(),this.config.autoTrack&&this.setupAutoTracking(),this.setupPerformanceTracking(),this.flushTimer=setInterval(()=>{this.flush()},3e3);window.addEventListener("beforeunload",()=>{this.flush(!0)}),document.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush(!0)}),this.config.autoTrack&&this.page(),this.isInitialized=!0,this.log("ClickChutney tracker initialized")}setupAutoTracking(){"undefined"!=typeof document&&(document.addEventListener("visibilitychange",()=>{document.hidden?this.track("page_hidden"):this.track("page_visible")}),document.addEventListener("click",e=>{const t=e.target;"BUTTON"!==t.tagName&&"A"!==t.tagName||this.track("click",{element:t.tagName.toLowerCase(),text:t.textContent?.trim(),href:t.getAttribute("href"),className:t.className})}),document.addEventListener("submit",e=>{const t=e.target;this.track("form_submit",{formId:t.id,formName:t.name,action:t.action})}))}setupPerformanceTracking(){if("undefined"!=typeof document&&"undefined"!=typeof window)if("complete"===document.readyState)setTimeout(()=>this.trackPerformance(),1e3);else{const e=()=>{setTimeout(()=>this.trackPerformance(),1e3),window.removeEventListener("load",e)};window.addEventListener("load",e)}}trackPerformance(){const e=function(){if("undefined"==typeof window||!window.performance)return{};try{const e=performance.getEntriesByType("navigation")[0],t=performance.getEntriesByType("paint").find(e=>"first-contentful-paint"===e.name);let i;try{i=performance.getEntriesByType("largest-contentful-paint")[0]}catch{i=null}const n={};if(e&&e.loadEventEnd&&e.fetchStart){const t=e.loadEventEnd-e.fetchStart;t>0&&t<6e4&&(n.loadTime=Math.round(t))}return t&&t.startTime>0&&(n.fcp=Math.round(t.startTime)),i&&i.startTime>0&&(n.lcp=Math.round(i.startTime)),n}catch(e){return{}}}();Object.keys(e).length>0&&this.track("performance",e)}page(e,t){if("undefined"==typeof window)return void this.log("Skipping page tracking - not in browser environment");const i={type:"pageview",url:e||s(),title:t||("undefined"==typeof document?"":document.title),referrer:a(),path:"undefined"==typeof window?"":window.location.pathname};r.updateSession({pageViews:(r.getSession()?.pageViews||0)+1}),this.enqueueEvent("pageview",i),this.log("Page view tracked",i)}track(e,t){if("undefined"==typeof window)return void this.log("Skipping event tracking - not in browser environment");const i={type:"event",name:e,properties:t};r.updateSession({events:(r.getSession()?.events||0)+1}),this.enqueueEvent(e,i),this.log("Event tracked",i)}identify(e,t){c.setUser({id:e,traits:t}),this.enqueueEvent("identify",{type:"identify",userId:e,traits:t}),this.log("User identified",{userId:e,traits:t})}set(e){const t=c.getUser()||{};c.setUser({...t,traits:{...t.traits,...e}}),this.log("User properties set",e)}enqueueEvent(e,t){const i=r.getSession(),d=c.getUser(),l={trackingId:this.config.trackingId,event:e,domain:o(),timestamp:(new Date).toISOString(),sessionId:i?.id||n(),userId:d?.id,data:t,userAgent:"undefined"==typeof navigator?"":navigator.userAgent,url:s(),referrer:a()};this.eventQueue.push(l),this.log("Event enqueued",l),(this.eventQueue.length>=5||"pageview"===e)&&setTimeout(()=>this.flush(),100)}flush(e=!1){if("undefined"==typeof window||0===this.eventQueue.length)return Promise.resolve();const t=[...this.eventQueue];this.eventQueue=[],this.log("Flushing events",t);const i=async()=>{try{const i=await fetch(this.config.apiUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({events:t,trackingId:this.config.trackingId,domain:o()}),...e&&{keepalive:!0}});if(!i.ok)throw new Error(`HTTP ${i.status}`);this.log("Events sent successfully"),this.config.debug&&console.log("✅ ClickChutney: Successfully sent",t.length,"events to",this.config.apiUrl)}catch(e){this.log("Error sending events",e),this.config.debug&&(console.error("❌ ClickChutney: Failed to send events:",e),console.log("Retrying events:",t)),this.eventQueue.unshift(...t)}};return e?("undefined"!=typeof navigator&&navigator.sendBeacon&&navigator.sendBeacon(this.config.apiUrl,JSON.stringify({events:t,trackingId:this.config.trackingId,domain:o()})),Promise.resolve()):i()}reset(){r.clearSession(),c.clearUser(),this.eventQueue=[],this.log("Tracker reset")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush(!0),this.log("Tracker destroyed")}forceFlush(){return this.flush()}log(e,t){this.config.debug&&console.log(`[ClickChutney] ${e}`,t||"")}}function l(i={}){const{trackingId:n,debug:s,disableInDev:o=!0,config:a={}}=i,[r,c]=e(!1);t(()=>{c(!0)},[]);const l=n||"undefined"!=typeof process&&process.env.NEXT_PUBLIC_CLICKCHUTNEY_ID||"undefined"!=typeof process&&process.env.NEXT_PUBLIC_CLICKCHUTNEY_TRACKING_ID;if(!r)return null;if(!l)return console.warn('⚠️ ClickChutney Warning: No tracking ID found\n\nAnalytics will not track events because no tracking ID was provided.\n\nSolutions:\n• Add NEXT_PUBLIC_CLICKCHUTNEY_ID to your .env.local file\n• Or pass trackingId prop: <Analytics trackingId="your-id" />\n\nGet your tracking ID from: https://clickchutney.com/dashboard'),null;const u="undefined"!=typeof process&&!1,f=void 0!==s?s:u;return"undefined"==typeof window||window.__ccAnalyticsInitialized||(window.__ccAnalyticsInitialized=!0,setTimeout(()=>{try{const e=new d({trackingId:l,debug:f,autoTrack:!0,...a});window.__ccTracker=e,window.__ccReactAPI={page:(t,i)=>e.page(t,i),track:(t,i)=>e.track(t,i),identify:(t,i)=>e.identify(t,i),set:t=>e.set(t)},setTimeout(()=>{e.page()},100),f&&console.log("✅ ClickChutney: Initialized successfully with ID:",l)}catch(e){console.error("❌ ClickChutney: Failed to initialize:",e),window.__ccAnalyticsInitialized=!1}},0)),null}function u(){return{page:(e,t)=>{if("undefined"!=typeof window)if(window.__ccReactAPI)try{window.__ccReactAPI.page(e,t)}catch(e){console.warn("ClickChutney: Not initialized. Add <Analytics /> to your app.")}else console.warn("ClickChutney: Not loaded. Add <Analytics /> to your app.")},track:(e,t)=>{if("undefined"!=typeof window)if(window.__ccReactAPI)try{window.__ccReactAPI.track(e,t)}catch(e){console.warn("ClickChutney: Not initialized. Add <Analytics /> to your app.")}else console.warn("ClickChutney: Not loaded. Add <Analytics /> to your app.")},identify:(e,t)=>{if("undefined"!=typeof window)if(window.__ccReactAPI)try{window.__ccReactAPI.identify(e,t)}catch(e){console.warn("ClickChutney: Not initialized. Add <Analytics /> to your app.")}else console.warn("ClickChutney: Not loaded. Add <Analytics /> to your app.")},set:e=>{if("undefined"!=typeof window)if(window.__ccReactAPI)try{window.__ccReactAPI.set(e)}catch(e){console.warn("ClickChutney: Not initialized. Add <Analytics /> to your app.")}else console.warn("ClickChutney: Not loaded. Add <Analytics /> to your app.")}}}export{l as Analytics,l as ClickChutneyAnalytics,l as default,u as useAnalytics,u as useClickChutney}; //# sourceMappingURL=react.esm.js.map