@statlark/web
v0.1.1
Published
Statlark browser SDK — initStatlark() for SPAs and frameworks. A typed wrapper over the Statlark tracker: pageviews, goals, identify, payment, reset on sign-out, plus an optional React provider.
Maintainers
Readme
@statlark/web
The Statlark browser SDK for SPAs and frameworks. Install with npm and initialize in
code instead of pasting a <script> tag — you get a typed API for goals, identify,
and revenue, plus an optional React provider.
It's a thin, typed wrapper: initStatlark() injects the hosted Statlark tracker and
hands back a handle that proxies it, so the tracker keeps owning cookies, first-touch
attribution, automatic pageviews, and transport. One source of truth.
Install
npm install @statlark/webQuick start
import { initStatlark } from "@statlark/web";
const statlark = await initStatlark({ site: "sl_ab12cd34" });
statlark.goal("signup", { plan: "pro" });
statlark.identify({ user_id: "u_123", user_email: "[email protected]" });
statlark.payment({ amount: 4900, transaction_id: "pi_123", currency: "usd" });Your site is the website public id (sl_…) from Settings → Install in your
Statlark dashboard. For parity with DataFast-style snippets you can pass it as
websiteId instead.
Pageviews are automatic — on load and on History API navigations (which is how
Next.js App Router, React Router and friends navigate). Call statlark.pageview()
yourself only for views your framework doesn't route through the History API.
You can start calling methods before await resolves; calls are buffered and
flushed, in order, once the tracker is ready.
React
// app/providers.tsx — a client component at your root
"use client";
import { StatlarkProvider } from "@statlark/web/react";
export function Providers({ children }: { children: React.ReactNode }) {
return <StatlarkProvider config={{ site: "sl_ab12cd34" }}>{children}</StatlarkProvider>;
}// any client component
"use client";
import { useStatlark } from "@statlark/web/react";
export function UpgradeButton() {
const statlark = useStatlark();
return <button onClick={() => statlark.goal("upgrade_click")}>Go Pro</button>;
}StatlarkProvider is a client component. It injects the tracker once and provides a
handle that's callable from the first render. react is an optional peer dependency —
the base @statlark/web import has no React dependency.
Server-side rendering
initStatlark() is SSR-safe: on the server it resolves to a no-op handle, so calling
it (or any handle method) during render never throws. The tracker only ever runs in
the browser.
API
initStatlark(config): Promise<StatlarkHandle>
Injects the tracker and resolves once it's ready. Safe to call multiple times — every
call shares one tracker and resolves to the same handle. The tracker is single-instance
per page, so the first initStatlark() owns the configuration; a later call with a
different site/api/scriptSrc is ignored with a console warning. If a tracker for a
different site is already running on the page, this instance disables itself rather
than mis-attributing your events.
Config (a camel-cased mirror of the tracker's data-*
snippet options):
| Option | Type | Default | Notes |
| ----------------- | --------- | -------------------------------- | ----- |
| site | string | — | Required. Your website public id (sl_…). |
| websiteId | string | — | Alias for site. |
| api | string | hosted collector | Set to your first-party proxy path (e.g. /q3v/e) for ad-blocker resistance. |
| scriptSrc | string | https://statlark.com/script.js | Override to self-host or version-pin the tracker. |
| domain | string | — | Declared site domain (informational). |
| cookieDomain | string | auto (registrable domain) | "none" for host-only, or an explicit domain. |
| trackLocalhost | boolean | false | Send events from localhost / private hosts. |
| outbound | boolean | true | Auto-track outbound link clicks. |
| honorDnt | boolean | false | Honor the browser Do Not Track signal. |
| debug | boolean | false | Log each tracked hit to the console. |
| disableConsole | boolean | false | Silence tracker console output. |
| disablePayments | boolean | false | Make payment() a no-op. |
| cookieless | boolean | false | GDPR cookieless mode (hosted collector only). |
Handle
| Method | Description |
| ---------------------------- | ----------- |
| statlark(name, props?) | Shorthand for goal(). |
| pageview(path?) | Record a pageview (auto-tracked on load + SPA navigation). |
| goal(name, props?) | Record a conversion goal. |
| event(name, props?) | Record a custom event. |
| identify(opts) | Attach a known identity to the visitor. |
| payment(opts) | Record revenue (needs amount + transaction_id). |
| getVisitorId() | Current visitor id (_slk_vid), or null before ready / when not tracking. |
| reset() | Forget the visitor + session — call on sign-out. |
Sign-out
Call reset() when a user logs out so the next person on that browser starts as a
fresh anonymous visitor instead of inheriting the previous user's identity and
first-touch attribution:
async function onSignOut() {
await auth.signOut();
statlark.reset();
}It takes effect immediately — no page reload needed. Call it from your auth state-change handler so every open tab resets, not just the one that signed out.
Not an identity boundary in
cookielessmode. There is no id stored on the device to clear — the visitor id is derived server-side from a daily-rotating hash of the request, soreset()starts a new session but the same browser keeps the same visitor id until the hash rotates at UTC midnight. On a shared device in cookieless mode, sign-out does not separate the two people.
License
MIT
