npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tracwell

v0.2.0

Published

Small, privacy-aware browser analytics SDK for Tracwell

Readme

SDK

Browser analytics SDK for page views, custom events, identity, batching, and bounded delivery retries.

Script installation

The production browser artifact is served from the existing Collector domain:

<script
  defer
  src="https://collect.tracwell.app/script.js"
  data-project-key="tw_live_..."
  data-collection-mode="private"
  data-consent="granted"
  data-respect-do-not-track="true"
></script>

Loading the script captures the initial page view and exposes the same client as window.tracwell for custom events:

window.tracwell?.track("signup_completed", { plan: "starter" });

The script derives /v1/events from its own origin, so the same artifact works against the loopback Collector during local development. The production bundle reports SDK version 0.2.0, targets ES2022-capable browsers, and has a 4.7 KB gzip budget enforced by build:cdn.

Public API

Install the npm package:

pnpm add tracwell
import { createTracwell } from "tracwell";

const tracwell = createTracwell({
  collectionMode: "private",
  projectKey: "tw_live_...",
});

tracwell.track("signup_completed", { plan: "starter" });
tracwell.identify("customer_123");

const session = tracwell.getSession();

createTracwell() starts collection immediately in the browser and captures the initial page view by default. It must be called after the document is available, not during server rendering.

Framework compatibility

The npm SDK is a framework-neutral ESM browser library. It has no React, Vue, Svelte, Angular, router, or rendering-framework dependency. Importing it during SSR is safe; call createTracwell() from that framework's browser mount or hydration lifecycle after document is available.

Multi-page applications capture a page view each time the browser loads the application. Single-page applications using the standard History API receive automatic page views for pushState, replaceState, and back/forward navigation. This covers the default path-based routers in modern web frameworks. Hash fragments remain intentionally excluded from analytics URLs; hash-only navigation does not create a page view.

Framework adapters should own only lifecycle integration and dependency injection. Event validation, identity, attribution, navigation observation, batching, retries, consent, and delivery remain in this core package.

Responsibilities

  • Generate stable event and batch IDs before delivery.
  • Capture initial page views, SPA navigation, referrer, UTM, and tagged-link context.
  • Expose typed custom-event and identity APIs.
  • Batch only against the limits exported by @tracwell/contracts.
  • Retry bounded transient failures without changing event IDs.
  • Respect configured consent and Do Not Track behavior before collection.

The SDK must remain browser-only, small, non-blocking, and unable to set trusted collector fields. It must not contain secrets or connect to ClickHouse.

Identity and attribution

Collection mode is explicit:

  • private is the default. It never reads or writes cookies, localStorage, or sessionStorage; identify() reports IDENTIFY_UNAVAILABLE. Anonymous and session values exist only in memory until the collector replaces them.

  • product persists first-party anonymous, session, and optional user identity in localStorage. Configure consent before collection where required.

  • Private mode rejects an explicit persistence: "localStorage" instead of silently weakening the project's privacy behavior.

  • anonymous_id is first-party and persists per project unless persistence is disabled or identity is reset.

  • session_id rotates after 30 minutes without a captured event.

  • A different non-empty UTM campaign starts a new session immediately.

  • The first external referrer and UTM values are preserved for the session.

  • The SDK preserves the absolute referrer. Trusted ClickHouse row mapping uses registered-domain/public-suffix parsing so sibling subdomains are not reported as external acquisition.

  • identify() validates the supplied opaque user ID before associating it with future events.

  • Identifying a different user on the same installation rotates both anonymous identity and session before recording the new identity. Call reset() on logout so an anonymous post-logout visit also starts cleanly.

  • getSession() returns the active Product-mode anonymousId, sessionId, and optional userId so a server-created checkout can carry the same identifiers into an authenticated revenue event. It returns undefined in Private mode, without consent, when Do Not Track blocks collection, or after shutdown.

  • Treat the returned IDs as attribution context, not authorization. Revenue user_id must come from the authenticated account or verified payment webhook rather than a client-supplied value.

  • Hash-only URL changes do not create duplicate SPA page views.

  • URL fragments are excluded from captured URLs and path contains only the pathname.

Product identity uses localStorage, never fingerprinting. If storage is disabled or unavailable, the SDK explicitly reports STORAGE_UNAVAILABLE through onError and uses in-memory identity for the page lifetime.

Delivery semantics

  • Events receive lightweight client preflight validation before entering memory. The Collector remains the canonical Zod validation boundary for all untrusted browser input.
  • Normal cross-origin delivery uses a safelisted text/plain JSON body so it does not add a CORS preflight request; the collector still parses and validates the body as JSON.
  • Batches default to 25 events and are reduced when necessary to remain within the shared 48 KiB limit.
  • Normal delivery reports accepted only after a matching 202 receipt confirms the batch ID and event count.
  • Network errors, 408, 429, and 5xx responses use bounded in-memory retry without changing event or batch IDs.
  • Other 4xx responses report DELIVERY_REJECTED and are not retried.
  • Page-hide and hidden-document delivery prefers sendBeacon; a successful browser handoff reports handed_off, never accepted.
  • Exhausted delivery is surfaced through onError with the affected event IDs.

The default collector endpoint is https://collect.tracwell.app/v1/events. Production overrides must use HTTPS; loopback HTTP is allowed only for local development.

Privacy controls

  • consent: "required" prevents identity creation and collection until setConsent("granted").
  • Revoking consent stops listeners, removes queued events, and resets identity.
  • Do Not Track is respected by default and can be disabled explicitly per customer configuration.
  • persistence: "none" keeps all identifiers in memory.
  • Private collection forces persistence: "none" and blocks identify().

Structure

src/
  index.ts         Stable public exports and browser-only factory
  script.ts        Lean self-starting CDN entry and `window.tracwell` exposure
  script-config.ts Strict script-dataset parsing and normalized CDN defaults
  client.ts        Consent-aware API and lifecycle orchestration
  config.ts        Defaults and configuration validation
  identity.ts      Anonymous, session, and user identity state
  attribution.ts   First-touch-per-session UTM and referrer capture
  events.ts        Context creation and contract-validated events
  transport.ts     Size-aware batching, receipts, beacon, and retries
  preflight.ts     Small client-side event and receipt checks
  runtime.ts       Browser API adapter
  types.ts         Public configuration, client, delivery, and error types
  client.test.ts   Deterministic SDK behavior and failure tests
  index.test.ts    SSR import and browser-initialization boundary
scripts/
  build-cdn.mjs    Minified browser build and gzip-size enforcement
  build-npm.mjs    Self-contained ESM package build
  smoke-npm.mjs    Packed runtime and TypeScript consumer smoke test
static/
  _headers         Cross-origin browser asset headers

Keep browser globals isolated in runtime.ts, keep index.ts as the stable public API, and test behavior through an injected deterministic runtime.

Dependencies

  • @tracwell/contracts for inferred types and shared limits
  • Browser platform APIs for navigation, lifecycle, and delivery
  • esbuild at build time for the minified browser artifact

The published npm artifact bundles its runtime contract constants and ships generated declarations, so consumers do not need the private contracts workspace. Compile-time compatibility checks keep the duplicated public property and issue types aligned with the canonical contracts package.

The npm package is distributed under the MIT License. Publishing the package does not make the private application repository public.

Verify

pnpm --filter {packages/sdk} typecheck
pnpm --filter {packages/sdk} test
pnpm --filter {packages/sdk} build:cdn
pnpm --filter {packages/sdk} check:package