Skip to content

Repository files navigation

FlexTrack TypeScript

Consent-aware, deterministic analytics routing for TypeScript, Node.js, and browsers.

CI npm license

FlexTrack keeps product code independent from analytics vendors. Events are enriched, routed by explicit rules, checked for consent, sampled deterministically, delivered to registered trackers, and durably queued when the application is offline or a destination fails.

Install

npm install flex-track

Configure

import {
  CallbackTracker,
  ConsoleLogger,
  ConsentManager,
  configureFlexTrack,
} from "flex-track";
import { IndexedDbEventQueue } from "flex-track/browser";

const consent = new ConsentManager();

const flexTrack = configureFlexTrack((config) => {
  config
    .tracker(new CallbackTracker("analytics", async (event) => {
      await analyticsClient.capture(event.name, event.properties);
    }))
    .tracker(new CallbackTracker("archive", sendToArchive))
    .queue(new IndexedDbEventQueue())
    .consent(() => consent.state)
    .online(() => navigator.onLine)
    .logger(new ConsoleLogger(import.meta.env.DEV));

  config.routing((routing) => {
    routing
      .defineGroup("product", "analytics", "archive")
      .routeCategory("business", (rule) =>
        rule.toGroup("product").priority(10).requiresConsent(),
      )
      .routePII((rule) =>
        rule.to("archive").priority(20).requiresPIIConsent(),
      )
      .routeHighVolume((rule) =>
        rule.to("analytics").sample(0.1).priority(5),
      )
      .routeDefault((rule) => rule.to("analytics"));
  });
});

await flexTrack.start();
consent.update({ general: true });

await flexTrack.track({
  name: "add_to_cart",
  category: "business",
  properties: { product_id: "sku-42", price: 19.99 },
  userId: "user-123",
});

Consent defaults to denied. Grant it only after your application has collected the corresponding user choice.

Durable offline delivery

Browser applications can use IndexedDB or localStorage:

import { IndexedDbEventQueue, LocalStorageEventQueue } from "flex-track/browser";

Node.js applications can use an atomic JSON file queue:

import { FileEventQueue } from "flex-track/node";

config.queue(new FileEventQueue("./data/flex-track-queue.json"));

When offline, FlexTrack queues one event with all pending tracker IDs. On partial failure, it stores only failed destinations. flush() retries pending destinations in FIFO order and preserves failed items with an incremented attempt count.

window.addEventListener("online", () => void flexTrack.flush());

Tracker adapters

CallbackTracker integrates an existing SDK. FetchTracker posts the normalized event as JSON. DebugTracker captures events for development and tests.

import { FetchTracker } from "flex-track";

config.tracker(new FetchTracker("warehouse", "https://events.example.com/v1/track", {
  headers: { authorization: `Bearer ${token}` },
}));

Logging and payload safety

Logging is opt-in. The default logger is a no-op. ConsoleLogger(false) reports routing decisions and property keys without values. Enable values only in trusted development environments:

config.logger(new ConsoleLogger(process.env.NODE_ENV !== "production"));

Runtime support

  • Node.js 18+
  • Modern browsers with ESM; IndexedDB is optional
  • ESM and CommonJS consumers
  • TypeScript declarations included

Quality contract

The SDK implements the same core/runtime contract used by the Flutter, Kotlin, and Swift SDKs: priority-tier routing, UTF-8 FNV-1a sampling, consent defaults, immutable event identity, idempotent FIFO queues, offline delivery, partial-failure retry, and idempotent lifecycle behavior.

npm run typecheck
npm test
npm run build
npm run pack:check

Contributing

See CONTRIBUTING.md. Security issues should follow SECURITY.md.

License

MIT © Reza Taghizadeh

About

Consent-aware, deterministic analytics routing for TypeScript, Node.js, and browsers.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages