# @suaveplan/delivery-tracking - Channel-agnostic delivery event tracking for campaigns and messages: lifecycle dedupe, in-memory + SurrealDB stores, time-series aggregation, tracking pixel / link tokens, multi-provider webhook parsing, OTel instrumentation Channel-agnostic delivery event tracking for campaigns and messages: lifecycle dedupe, in-memory + SurrealDB stores, time-series aggregation, tracking pixel and click-link tokens, multi-provider webhook parsing, and OpenTelemetry instrumentation. ## Documentation tree - [aggregator](./src/core/aggregator/aggregator.md) — `DeliveryAggregator` reads campaign and contact statistics from any `DeliveryEventStore` and exposes time-series bucket… - [aggregator](./src/core/aggregator/aggregator.md) — `DeliveryAggregator` reads campaign and contact statistics from any `DeliveryEventStore` and exposes time-series bucket… - [tracker](./src/core/tracker/tracker.md) — `DeliveryTracker` is the package's primary write-side surface. It validates inbound `CreateDeliveryEventInput`s against… - [tracker](./src/core/tracker/tracker.md) — `DeliveryTracker` is the package's primary write-side surface. It validates inbound `CreateDeliveryEventInput`s against… - [tracker.schemas](./src/core/tracker/tracker.schemas.md) — `tracker.schemas` declares the Zod boundary schemas applied to `DeliveryTracker.track` input. Centralising the schemas… - [tracking-link](./src/core/tracking-link/tracking-link.md) — `TrackingLinkWrapper` rewrites outbound URLs with click-tracking redirects. Each wrapped URL points at the tracking hos… - [tracking-link](./src/core/tracking-link/tracking-link.md) — `TrackingLinkWrapper` rewrites outbound URLs with click-tracking redirects. Each wrapped URL points at the tracking hos… - [tracking-pixel](./src/core/tracking-pixel/tracking-pixel.md) — `TrackingPixelGenerator` produces and parses the open-tracking pixel URLs embedded in outbound HTML emails. The pixel U… - [token-codec](./src/core/tracking-pixel/token-codec.md) — `token-codec` is the shared XOR + base64url encoder/decoder used by both `TrackingPixelGenerator` (open tracking) and `… - [tracking-pixel](./src/core/tracking-pixel/tracking-pixel.md) — `TrackingPixelGenerator` produces and parses the open-tracking pixel URLs embedded in outbound HTML emails. The pixel U… - [webhook-parser](./src/core/webhook-parser/webhook-parser.md) — `WebhookEventParser` normalises provider-specific delivery webhooks into `CreateDeliveryEventInput[]` ready for `Delive… - [webhook-parser](./src/core/webhook-parser/webhook-parser.md) — `WebhookEventParser` normalises provider-specific delivery webhooks into `CreateDeliveryEventInput[]` ready for `Delive… - [errors](./src/errors/delivery-tracking-error.md) — `DeliveryTrackingError` is the stable typed error class raised by every code path inside `@suaveplan/delivery-tracking`… - [delivery-tracking-error](./src/errors/delivery-tracking-error.md) — `DeliveryTrackingError` is the stable typed error class raised by every code path inside `@suaveplan/delivery-tracking`… - [otel](./src/otel/instruments.md) — `getDeliveryTrackingInstruments` lazily constructs and caches the OTel `Counter` set used by every production code path… - [instruments](./src/otel/instruments.md) — `getDeliveryTrackingInstruments` lazily constructs and caches the OTel `Counter` set used by every production code path… - [memory](./src/stores/memory/memory-store.md) — `memory-store` defines the `DeliveryEventStore` interface that every persistence backend must satisfy, ships the determ… - [memory-store](./src/stores/memory/memory-store.md) — `memory-store` defines the `DeliveryEventStore` interface that every persistence backend must satisfy, ships the determ… - [surreal](./src/stores/surreal/surreal-store.md) — `SurrealDeliveryEventStore` is the SurrealDB-backed implementation of the `DeliveryEventStore` contract. It uses positi… - [surreal-store](./src/stores/surreal/surreal-store.md) — `SurrealDeliveryEventStore` is the SurrealDB-backed implementation of the `DeliveryEventStore` contract. It uses positi… ## Install ```bash bun add @suaveplan/delivery-tracking ``` ## Quick start ```ts import { DeliveryAggregator, DeliveryTracker, InMemoryDeliveryEventStore, TrackingPixelGenerator, WebhookEventParser, } from "@suaveplan/delivery-tracking"; const store = new InMemoryDeliveryEventStore(); const tracker = new DeliveryTracker(store); const aggregator = new DeliveryAggregator(store); const parser = new WebhookEventParser(); const pixel = new TrackingPixelGenerator({ baseUrl: "https://t.example.com", secret: "tracking-secret", }); tracker.bus.on("delivery:opened", (e) => { console.log("opened", e.messageId); }); const events = parser.parse("sendgrid", { body: webhookBody }); await tracker.trackBatch(events); const stats = await aggregator.getCampaignStats("c1"); const pixelUrl = pixel.generatePixelUrl("m1", "u1", "c1"); ``` ## Modules | Module | Description | |---|---| | [`src/core/tracker/tracker.ts`](src/core/tracker/tracker.md) | Validates and records events, dedupes lifecycle types, emits on a typed bus. | | [`src/core/tracker/tracker.schemas.ts`](src/core/tracker/tracker.schemas.md) | Zod boundary schemas for `CreateDeliveryEventInput`. | | [`src/core/aggregator/aggregator.ts`](src/core/aggregator/aggregator.md) | Campaign rollups, contact histories, time-series bucketing. | | [`src/core/tracking-pixel/tracking-pixel.ts`](src/core/tracking-pixel/tracking-pixel.md) | Open-tracking pixel URL generator + parser. | | [`src/core/tracking-pixel/token-codec.ts`](src/core/tracking-pixel/token-codec.md) | Shared XOR + base64url codec used by pixel and link wrappers. | | [`src/core/tracking-link/tracking-link.ts`](src/core/tracking-link/tracking-link.md) | Click-tracking URL wrapper, HTML rewrite, token parse. | | [`src/core/webhook-parser/webhook-parser.ts`](src/core/webhook-parser/webhook-parser.md) | Pluggable provider webhook → input normaliser. | | [`src/stores/memory/memory-store.ts`](src/stores/memory/memory-store.md) | `DeliveryEventStore` contract + in-memory implementation + `computeStats`. | | [`src/stores/surreal/surreal-store.ts`](src/stores/surreal/surreal-store.md) | SurrealDB-backed implementation using positional SurQL. | | [`src/errors/delivery-tracking-error.ts`](src/errors/delivery-tracking-error.md) | `DeliveryTrackingError` + stable code registry. | | [`src/otel/instruments.ts`](src/otel/instruments.md) | Lazy OTel counter set (`tracked`, `deduped`, `webhook_parsed`, `token_issued`, `token_rejected`). | ## Features - Lifecycle dedupe per `messageId` for `opened`, `delivered`, `bounced`, `unsubscribed`, `complained`. - Typed `EventBus` with one topic per `DeliveryEventType`. - Backend-agnostic via `DeliveryEventStore` — drop-in `InMemoryDeliveryEventStore`, `SurrealDeliveryEventStore`, or your own. - Time-series bucketing by `hour`/`day`/`week`. - Pluggable webhook parsers for SendGrid, Mailgun, AWS SES, and a generic shape. - Zod boundary validation on every event the tracker accepts. - Counters emitted via `@opentelemetry/api` for ingest, dedupe, parser activity, and token issuance/rejection. ## Subpath exports `./tracker`, `./aggregator`, `./tracking-pixel`, `./tracking-link`, `./webhook-parser`, `./stores/memory`, `./stores/surreal`, `./errors`, `./otel`. ## Errors Every failure raised by the package extends `DeliveryTrackingError`. The stable code registry: - `DELIVERY_TRACKING.INVALID_INPUT` - `DELIVERY_TRACKING.INVALID_TOKEN` - `DELIVERY_TRACKING.UNSUPPORTED_PROVIDER` - `DELIVERY_TRACKING.STORE_FAILURE` - `DELIVERY_TRACKING.QUERY_FAILURE`