better-analytics
Version:
Zero-dependency micro-analytics JavaScript SDK < 3KB gzipped with React/Next.js/Expo support
2 lines (1 loc) • 5.28 kB
JavaScript
import y,{useEffect as E,useRef as h}from"react";import a from"@react-native-async-storage/async-storage";import{Platform as p,Dimensions as b}from"react-native";import*as c from"expo-device";import*as s from"expo-application";import*as g from"expo-localization";import*as w from"expo-network";import{usePathname as O,useSegments as B,useGlobalSearchParams as M}from"expo-router";var d="ba_event_queue",i=null;function C(e){i=e,e.debug&&(console.log("\u{1F4F1} Better Analytics Expo initialized"),console.log("\u{1F4CD} Endpoint:",e.endpoint||"https://better-analytics.app/api/collect"),console.log("\u{1F3F7}\uFE0F Site:",e.site),console.log("\u{1F4F1} Platform:",p.OS),console.log("\u{1F9ED} Auto Navigation Tracking:",e.trackNavigation!==!1?"enabled":"disabled")),S()}async function A(){let{width:e,height:t}=b.get("window"),n=b.get("screen");try{let o=s.nativeApplicationVersion||void 0,r=s.nativeBuildVersion||void 0,l=s.applicationId||void 0,u=await R(),D=c.brand||void 0,k=c.modelName||void 0,N=p.Version?.toString(),I=!c.isDevice,P=g.timezone,_=g.locale;return{device:{userAgent:i?.userAgent||`Expo/${p.OS}`,screenWidth:n.width,screenHeight:n.height,language:_,timezone:P,platform:p.OS,platformVersion:N,brand:D,model:k,isEmulator:I},deviceId:u,sessionId:await q(),app:{version:i?.appVersion||o,buildNumber:r,bundleId:l}}}catch(o){return console.warn("Better Analytics Expo: Error getting device info",o),{device:{platform:p.OS,screenWidth:n.width,screenHeight:n.height}}}}async function R(){try{let e=await a.getItem("ba_device_id");return e||(e=`expo_${Date.now()}_${Math.random().toString(36).substring(2)}`,await a.setItem("ba_device_id",e)),e}catch{return`expo_${Date.now()}_${Math.random().toString(36).substring(2)}`}}async function q(){try{let t=await a.getItem("ba_session");if(t){let{id:n,timestamp:o}=JSON.parse(t);if(Date.now()-o<18e5)return await a.setItem("ba_session",JSON.stringify({id:n,timestamp:Date.now()})),n}}catch{}let e=`expo_session_${Date.now()}_${Math.random().toString(36).substring(2)}`;try{await a.setItem("ba_session",JSON.stringify({id:e,timestamp:Date.now()}))}catch{}return e}async function f(e,t){if(!i){console.warn("Better Analytics Expo: Not initialized. Call init() first.");return}if(!i.site){console.warn("Better Analytics Expo: No site identifier provided.");return}if(S(),!(await w.getNetworkStateAsync()).isConnected){i.debug&&console.log("\u{1F4F1} Better Analytics Expo: Offline, queuing event");let l=s.applicationId||"unknown";await v({event:e,timestamp:Date.now(),site:i.site,url:`app://${l}`,referrer:"",...t&&{props:t}});return}let o=await A(),r={event:e,timestamp:Date.now(),url:`app://${o.app?.bundleId||"unknown"}`,referrer:"",site:i.site,...o,...t&&{props:t}};if(i.beforeSend){let l={type:e==="screen_view"?"pageview":"event",name:e,url:r.url,data:r},u=await i.beforeSend(l);if(!u||!u.data)return;await m(u.data)}else await m(r);i.debug&&console.log("\u{1F4F1} Better Analytics Expo tracked:",e,t)}async function x(e,t){await f("screen_view",{screen_name:e,...t})}async function m(e){if(!i)return;let t=i.endpoint||"https://better-analytics.app/api/collect";try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":e.device?.userAgent||"BetterAnalytics-Expo/0.8.0"},body:JSON.stringify(e)});n.ok||(i.debug&&console.warn("Better Analytics Expo: Failed to send event, queuing.",{status:n.status,event:e.event}),await v(e))}catch(n){i.debug&&console.warn("Better Analytics Expo: Network error, queuing event.",n),await v(e)}}async function v(e){try{let t=await a.getItem(d),n=t?JSON.parse(t):[],o={event:e.event,timestamp:e.timestamp,url:e.url,referrer:e.referrer,site:e.site,props:e.props};n.push(o),await a.setItem(d,JSON.stringify(n))}catch(t){i?.debug&&console.warn("Better Analytics Expo: Failed to queue event.",t)}}async function S(){if(!i)return;if(!(await w.getNetworkStateAsync()).isConnected){i.debug&&console.log("\u{1F4F1} Better Analytics Expo: Offline, skipping queue processing.");return}try{let t=await a.getItem(d);if(!t)return;let n=JSON.parse(t);if(n.length===0)return;i.debug&&console.log(`\u{1F4F1} Better Analytics Expo: Processing event queue (${n.length} events).`),await a.setItem(d,JSON.stringify([]));let o=await A();for(let r of n)await m({...o,...r})}catch(t){i.debug&&console.warn("Better Analytics Expo: Error processing event queue.",t)}}function $(){let e=O(),t=B(),n=M(),o=h(null);E(()=>{if(!(!i||i.trackNavigation===!1)&&e&&e!==o.current){o.current=e;let r=e==="/"?"index":e.replace(/^\//,"").replace(/\//g,"_");x(r,{pathname:e,segments:t.join("/"),params:Object.keys(n).length>0?n:void 0}),i.debug&&(console.log("\u{1F4F1} Better Analytics Expo: Auto-tracked screen change"),console.log(" \u{1F4CD} Pathname:",e),console.log(" \u{1F500} Screen Name:",r),console.log(" \u{1F4CA} Segments:",t),Object.keys(n).length>0&&console.log(" \u{1F4CC} Params:",n))}},[e,t,n])}function T({children:e,...t}){let n=h(!1);return E(()=>{n.current||(C(t),n.current=!0)},[t]),$(),y.createElement(y.Fragment,null,e)}function j(){return{track:f,trackScreen:x,identify:async(e,t)=>{await f("identify",{user_id:e,...t})}}}export{T as AnalyticsProvider,C as init,S as processEventQueue,f as track,x as trackScreen,j as useAnalytics,$ as useExpoRouterTracking};