@lodd/node
Server-side tracking SDK for Lodd. Built for API, MCP, agent, and CLI products — the headless stuff nothing else tracks well.
Install
npm install @lodd/node
Quick start
import { Lodd } from "@lodd/node";
const ca = new Lodd({
apiKey: process.env.LODD_API_KEY!,
siteId: process.env.CA_SITE_ID!,
});
ca.track("api_call", { endpoint: "/v1/search", duration_ms: 42 });
await ca.close();
Express middleware
import express from "express";
import { Lodd } from "@lodd/node";
import { caExpress } from "@lodd/node/express";
const app = express();
const ca = new Lodd({ apiKey, siteId });
app.use(caExpress(ca, {
ignore: (req) => req.path === "/health",
}));
The middleware captures path, method, status, and duration_ms. It never captures query strings, request bodies, or headers.
Options
apiKey | — | Required. |
siteId | — | Required. Overridable per track() call. |
baseUrl | https://api.lodd.dev | Production proxy. Override to point at a local Supabase stack (e.g. http://127.0.0.1:54321) or an alternate deploy. |
maxBatchSize | 50 | Events queued before forced flush. |
flushIntervalMs | 5000 | Timer-based flush cadence. |
onError | console.warn | Called for dropped events or failed batches. |
Guarantees
track() never throws.
- Events >8KB of properties are dropped (with
onError).
- Failed batches are retried up to 3× with exponential backoff; then dropped.
close() flushes any queued events.
Session granularity
Server-side events don't have natural session boundaries, so the SDK synthesises a session_id deterministically from user_id + site_id + UTC date. This makes Daily Active Users correct out of the box, but a single user active across multiple UTC days will count as multiple unique_visitors in weekly/monthly range aggregations. Supply your own session_id in a future ca.track() overload if you need different granularity.