No description
  • TypeScript 100%
Find a file
2026-06-21 15:55:21 +03:00
.github/workflows Change tag pattern to allow all tags for publish 2026-06-21 15:55:21 +03:00
dist first commit 2026-06-21 15:52:42 +03:00
node_modules first commit 2026-06-21 15:52:42 +03:00
src first commit 2026-06-21 15:52:42 +03:00
package.json first commit 2026-06-21 15:52:42 +03:00
pnpm-lock.yaml first commit 2026-06-21 15:52:42 +03:00
README.md first commit 2026-06-21 15:52:42 +03:00
tsconfig.json first commit 2026-06-21 15:52:42 +03:00
tsup.config.ts first commit 2026-06-21 15:52:42 +03:00

@sharevent/analytics-sdk

Framework-agnostic analytics + A/B testing SDK. Zero-dependency core (~34KB 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; call page() on client navigations.
  • clicks — one delegated listener; data-analytics="cta_signup" names a CTA.
  • idle / dwellidle_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