Skip to main content

@adrper79-dot/analytics

Dual-track analytics: PostHog for product analytics and a first-party factory_events table for business intelligence. Depends on @adrper79-dot/errors and @adrper79-dot/neon.

Installation

npm install @adrper79-dot/analytics

Secrets required

wrangler secret put POSTHOG_API_KEY

Database

Run the DDL constant to create the table:
import { CREATE_FACTORY_EVENTS_TABLE } from '@adrper79-dot/analytics';
await db.execute(CREATE_FACTORY_EVENTS_TABLE);
Schema:
CREATE TABLE IF NOT EXISTS factory_events (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  app_id      TEXT NOT NULL,
  user_id     TEXT,
  event       TEXT NOT NULL,
  properties  JSONB DEFAULT '{}',
  created_at  TIMESTAMPTZ DEFAULT now()
);

API

track(opts)

Sends an event to PostHog and inserts into factory_events.
function track(opts: {
  db: Db;
  posthogKey: string;
  appId: string;
  event: string;
  userId?: string;
  properties?: Record<string, unknown>;
}): Promise<void>;

identify(opts)

Creates or updates a PostHog person profile.
function identify(opts: {
  posthogKey: string;
  userId: string;
  traits: Record<string, unknown>;
}): Promise<void>;

getEvents(db, opts)

Queries factory_events with optional filtering.
function getEvents(
  db: Db,
  opts: {
    appId: string;
    userId?: string;
    event?: string;
    limit?: number;
    since?: Date;
  },
): Promise<FactoryEvent[]>;

Example

import { track } from '@adrper79-dot/analytics';

await track({
  db: createDb(env.DB),
  posthogKey: env.POSTHOG_API_KEY,
  appId: 'focusbro',
  event: 'subscription.created',
  userId: user.id,
  properties: { plan: 'pro', mrr: 29 },
});