@14four/analytics
v0.2.1
Published
14four Analytics SDK — works in Node.js and browser
Readme
@14four/analytics
Privacy-first analytics SDK for Node.js and the browser. No cookies, no persistent identifiers.
Installation
npm install @14four/analyticsBrowser usage
Pass your public appId to instantiate. The SDK auto-collects referrer, screen dimensions, page title, language, and UTM parameters on every event.
import Analytics from "@14four/analytics";
const analytics = new Analytics({
appId: "your_app_id",
baseUrl: "https://your-ingest-url.com", // optional, defaults to same-origin
});
// Basic pageview
analytics.track("page_view");
// With custom properties
analytics.track("cta_click", {
props: { button: "hero", variant: "A" },
});
// Override the URL (useful for SPAs with virtual pageviews)
analytics.track("page_view", {
url: "/virtual/route",
});Browser auto-collected fields
These are always captured automatically — no configuration required:
| Field | Source |
|---|---|
| url | window.location.href |
| referrer | document.referrer |
| screen_width | window.screen.width |
| screen_height | window.screen.height |
| page_title | document.title |
| language | navigator.language |
| utm_source | URL search params |
| utm_medium | URL search params |
| utm_campaign | URL search params |
| utm_term | URL search params |
| utm_content | URL search params |
| engagement_time_msec | Accumulated visible time since last track call |
The SDK also fires an automatic engagement event via navigator.sendBeacon when the page unloads, capturing total time the page was visible.
Browser track options
analytics.track("event_name", {
url?: string; // Override auto-collected URL
props?: Record<string, string>; // Custom properties (see below)
});Node.js (server-side) usage
Pass your secret API key to instantiate. The user_id field is required on every server-side event and is used directly as the visitor identifier (no hashing).
import Analytics from "@14four/analytics";
const analytics = new Analytics({
apiKey: "sk_live_...",
baseUrl: "https://your-ingest-url.com", // optional
});
// Basic event
await analytics.track("signup", { user_id: "u_123" });
// With all available options
await analytics.track("purchase", {
user_id: "u_123",
app_id: "your_app_id", // required if your key covers multiple apps
url: "https://example.com/checkout",
referrer: "https://google.com",
utm_source: "newsletter",
utm_medium: "email",
utm_campaign: "spring_sale",
utm_term: "analytics",
utm_content: "banner",
props: { plan: "pro", seats: "5" },
});Server track options
analytics.track("event_name", {
user_id: string; // Required — used as the visitor identifier
app_id?: string; // App ID (if key covers multiple apps)
url?: string;
referrer?: string;
utm_source?: string;
utm_medium?: string;
utm_campaign?: string;
utm_term?: string;
utm_content?: string;
props?: Record<string, string>;
});Custom properties
Both browser and server modes support a props object for attaching arbitrary metadata to events. Values must be strings.
analytics.track("video_played", {
// browser: user_id not needed
props: {
video_id: "abc123",
duration_sec: "142",
quality: "1080p",
},
});Limits: max 20 keys, key length ≤ 50 chars, value length ≤ 500 chars.
Dev mode
Pass dev: true to suppress all network requests and log events to the console instead. Useful during local development to verify your instrumentation without polluting production data.
const analytics = new Analytics({
appId: "your_app_id",
dev: true,
});
analytics.track("page_view");
// [Analytics Dev] "page_view" (browser)
// ┌──────────────────┬──────────────────────────┐
// │ (index) │ Values │
// ├──────────────────┼──────────────────────────┤
// │ event_name │ 'page_view' │
// │ app_id │ 'your_app_id' │
// │ url │ 'http://localhost:3000/' │
// │ referrer │ '' │
// │ screen_width │ '1512' │
// └──────────────────┴──────────────────────────┘Dev mode works for both appId (browser) and apiKey (server) instantiation.
