No description
- TypeScript 100%
| .github/workflows | ||
| dist | ||
| node_modules | ||
| src | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| tsconfig.json | ||
| tsup.config.ts | ||
@sharevent/analytics-sdk
Framework-agnostic analytics + A/B testing SDK. Zero-dependency core (~3–4KB gz)
plus optional React bindings. Pairs with analytics-be. See
../../ANALYTICS.md.
Core
import { init, track, page, identify, getVariant, convert, flush } from "@sharevent/analytics-sdk";
init({ apiKey: "ak_...", endpoint: "https://analytics.example.com/v1" });
track("custom", { foo: "bar" });
page("/pricing");
identify(userId);
const variant = getVariant("landing_hero_copy"); // deterministic + sticky
convert("landing_hero_copy", "signup");
What init wires up automatically:
- page views — an initial
page_view; callpage()on client navigations. - clicks — one delegated listener;
data-analytics="cta_signup"names a CTA. - idle / dwell —
idle_start/idle_end {idleMs}after 30s;dwell {ms}on leave. - movement — throttled mouse/scroll samples as viewport %, for heatmaps.
- transport — batched; flush on a 10s timer / 20 events /
visibilitychange/pagehide(sendBeacon, else fetch keepalive). One retry, then drop. - session — permanent
anonId(localStorage);sessionId(sessionStorage) rotates after 30 min idle.
All of it is a no-op when disabled: true or outside a browser.
React
import { AnalyticsProvider, RouteTracker, useAnalytics, useVariant } from "@sharevent/analytics-sdk/react";
<AnalyticsProvider config={{ apiKey, endpoint }}>
<BrowserRouter>
<RouteTracker /> {/* emits page_view on every route change */}
<App />
</BrowserRouter>
</AnalyticsProvider>;
const variant = useVariant("landing_hero_copy");
const { track, convert } = useAnalytics();
A/B testing
getVariant(key, variants?) hashes fnv1a(anonId + ":" + key) % 100 against
cumulative variant weights — identical to the server, so client and server agree
with no round-trip. It fires one exposure per session and an async assign.
convert(key, goal) is deduped server-side. Default split is control/variant
50/50; pass variants for custom keys/weights (must match the server experiment).
Build
pnpm install
pnpm build # tsup → dist/ (esm + cjs + d.ts), core and ./react entries