Analytics
atroui/analyticsFreeUtility
trackEvent and experiment helpers.
Install it
npx shadcn@latest add https://atroui.com/r/analytics.jsonSource
1/** Lightweight analytics + A/B testing - no external SDK required. */23export type AnalyticsEvent = {4 name: string;5 properties?: Record<string, string | number | boolean>;6};78export type Experiment = {9 id: string;10 variants: string[];11 weights?: number[];12};1314const STORAGE_PREFIX = "ms_";15const EXPERIMENT_PREFIX = `${STORAGE_PREFIX}exp_`;1617function isBrowser(): boolean {18 return typeof window !== "undefined";19}2021/** Assign and persist a variant for an experiment (sticky per user). */22export function getExperimentVariant(experiment: Experiment): string {23 if (!isBrowser()) return experiment.variants[0] ?? "";2425 const key = `${EXPERIMENT_PREFIX}${experiment.id}`;26 const stored = localStorage.getItem(key);27 if (stored && experiment.variants.includes(stored)) return stored;2829 const weights = experiment.weights ?? experiment.variants.map(() => 1);30 const total = weights.reduce((a, b) => a + b, 0);31 let roll = Math.random() * total;32 let variant = experiment.variants[0] ?? "";33 for (let i = 0; i < experiment.variants.length; i++) {34 roll -= weights[i] ?? 0;35 if (roll <= 0) {36 variant = experiment.variants[i] ?? variant;37 break;38 }39 }4041 localStorage.setItem(key, variant);42 trackEvent("experiment_assigned", {43 experiment_id: experiment.id,44 variant,45 });46 return variant;47}4849/** Track an event - forwards to Plausible/GA if configured, always logs in dev. */50export function trackEvent(51 name: string,52 properties?: Record<string, string | number | boolean>53): void {54 if (!isBrowser()) return;5556 const payload: AnalyticsEvent = { name, properties };5758 if (process.env.NODE_ENV === "development") {59 console.debug("[analytics]", payload);60 }6162 // Plausible custom events63 const plausible = (64 window as Window & { plausible?: (e: string, o?: { props: Record<string, string | number | boolean> }) => void }65 ).plausible;66 if (plausible) {67 plausible(name, properties ? { props: properties } : undefined);68 }6970 // Google Analytics 471 const gtag = (72 window as Window & { gtag?: (...args: unknown[]) => void }73 ).gtag;74 if (gtag) {75 gtag("event", name, properties);76 }7778 // Local event buffer for debugging79 try {80 const key = `${STORAGE_PREFIX}events`;81 const existing = JSON.parse(localStorage.getItem(key) ?? "[]") as AnalyticsEvent[];82 existing.push({ ...payload, properties: { ...properties, ts: Date.now() } as Record<string, string | number | boolean> });83// … truncated
