Web (multi-package)
@sankofa/browser
The core web SDK package. init, track, screen, identify, peopleSet/setPerson, reset, flush, shutdown — plus snapshot and transport status accessors.
@sankofa/browser is the heart of the web SDK. It manages the queue, owns the session, exposes the identity APIs, and registers the plugins from the other packages. Every web app integrating Sankofa installs this one.
Install
npm install @sankofa/browserSankofa.init(config)
Initialize the SDK exactly once at app entry. Subsequent calls are no-ops.
import { Sankofa } from "@sankofa/browser";
await Sankofa.init({
apiKey: process.env.NEXT_PUBLIC_SANKOFA_KEY!,
endpoint: "https://api.sankofa.dev",
});Common options
apiKeystringRequiredendpointstringRequireddebugbooleandefault falsetrackLifecycleEventsbooleanflushIntervalMsnumberbatchSizenumberpluginsPlugin[]releasestringenvironmentstringinit returns a Promise that resolves once initial setup completes. You don't need to await it for track/identify — those queue synchronously.
Sankofa.track(event, properties?)
Records an event.
Sankofa.track("checkout_started", {
cart_value: 49.99,
item_count: 3,
currency: "USD",
});Parameters
eventstringRequiredpropertiesRecord<string, unknown>Sankofa.screen(name, properties?)
Tags the current screen / route. Auto-fires $screen_view and stamps the screen name on subsequent events until the next screen() call.
Sankofa.screen("Checkout", { step: "review" });For SPAs with client-side routing, call screen from your route-change effect.
Sankofa.identify(userId)
Sets the active distinct ID. The previous anonymous ID is auto-aliased onto the new user.
Sankofa.identify("user_123");If you want to update profile traits at the same time, follow with peopleSet:
Sankofa.identify("user_123");
Sankofa.peopleSet({ email: "ada@example.com", plan: "pro" });Sankofa.peopleSet(traits) / setPerson(...)
Updates the user's People profile without changing identity.
// peopleSet — verbose, accepts any traits object
Sankofa.peopleSet({
plan: "growth",
signup_source: "referral",
});
// setPerson — named common traits + a properties bag
Sankofa.setPerson({
name: "Ada Lovelace",
email: "ada@example.com",
avatar: "https://...",
properties: { plan: "pro", signup_date: "2025-01-12" },
});Both update the same People profile. Use peopleSet when your traits are arbitrary; use setPerson when you want the named common traits to surface in the dashboard's People view.
Sankofa.reset()
Rotates the session, clears the active identity, and generates a fresh anonymous ID. Call this on logout.
Sankofa.reset();After reset, subsequent events use a new anonymous distinct_id. Decision handshakes refire to fetch flags / configs for the new identity.
Sankofa.flush()
Drains the queue immediately. Returns a Promise that resolves when in-flight requests complete.
await Sankofa.flush();Most apps don't need this — the queue flushes automatically on schedule and on pagehide. Useful before navigations that bypass the lifecycle hook.
Sankofa.shutdown()
Disposes the SDK — flushes pending events and detaches lifecycle listeners. Use it for tests or when your app needs to fully tear down.
await Sankofa.shutdown();Inspect SDK state
The browser SDK exposes a few read-only accessors useful for debugging or for your own analytics that want to attach the same identifiers:
// Snapshot of the current decision/flag/config payload at this instant.
const snapshot = Sankofa.getSnapshot();
// Transport health — useful for status banners ("offline", "syncing", etc).
const status = Sankofa.getTransportStatus();
// { state: "online" | "offline" | "syncing" | "error", lastSuccessAt: number }
const unsub = Sankofa.onTransportStatus((status) => {
if (status.state === "offline") showOfflineBanner();
});Lifecycle integration
The SDK auto-tracks lifecycle events alongside your custom events:
| Event | When |
|---|---|
$pageview | Tab loads, pushState, replaceState, popstate. |
$session_start | First event of a session. |
$session_end | Internal — fires on pagehide. Replays and Pulse consume this. |