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

bash
npm install @sankofa/browser

Sankofa.init(config)

Initialize the SDK exactly once at app entry. Subsequent calls are no-ops.

TypeScript
import { Sankofa } from "@sankofa/browser";

await Sankofa.init({
apiKey: process.env.NEXT_PUBLIC_SANKOFA_KEY!,
endpoint: "https://api.sankofa.dev",
});

Common options

apiKeystringRequired
Project API key. The engine resolves environment (live/test) from the key.
endpointstringRequired
Server base URL.
debugbooleandefault false
Verbose logging during development.
trackLifecycleEventsboolean
Auto-track $app_opened and visibility transitions.
flushIntervalMsnumber
How often the queued events are uploaded while the tab is foregrounded.
batchSizenumber
Maximum events per upload batch.
pluginsPlugin[]
Ordered list of plugin instances (catchPlugin, switchPlugin, etc.) to register at init.
releasestring
Build identifier — used by Catch for source-map matching.
environmentstring
Free-form label (development, staging, production). Tagged onto every event.

init 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.

TypeScript
Sankofa.track("checkout_started", {
cart_value: 49.99,
item_count: 3,
currency: "USD",
});

Parameters

eventstringRequired
Event name. snake_case, present tense, verb-noun. See [naming guide](/concepts/events).
propertiesRecord<string, unknown>
Custom properties. Strings, numbers, booleans, arrays, and JSON objects supported.

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.

TypeScript
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.

TypeScript
Sankofa.identify("user_123");

If you want to update profile traits at the same time, follow with peopleSet:

TypeScript
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.

TypeScript
// 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.

TypeScript
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.

TypeScript
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.

TypeScript
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:

TypeScript
// 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:

EventWhen
$pageviewTab loads, pushState, replaceState, popstate.
$session_startFirst event of a session.
$session_endInternal — fires on pagehide. Replays and Pulse consume this.

What's next

Edit this page on GitHub