Current model

Calendar analytics are first-party records in the D1 event_log table. recordEvent() writes one event name, optional internal subscriber/token/calendar ids, an optional deduplication key, and event-specific JSON context.

flowchart LR
  FLOW["Subscription, renewal,<br/>feed, cron, or webhook"] --> RECORD["recordEvent()"]
  RECORD --> D1[("D1 event_log")]
  D1 --> ADMIN["Admin observability,<br/>funnel, cohort, and replay views"]
  RECORD -. logging failure .-> CONTINUE["User flow continues"]

The write is awaited but best-effort: a D1 logging error is recorded to the Worker log and does not break the resident action.

What is recorded

Major groups include:

JourneyExample events
Magic-link requeststarted, Turnstile passed/failed, rate limited, request created, email sent/failed
Verificationlink clicked, request consumed, token minted/failed, subscriber disabled
Feed deliverytoken invalid/revoked/expired/seen, ICS fetched
Renewal14-day or 3-day warning, token extended, admin resend/extend/expire
Feed generationPrograms ICS regenerated
Email deliverydelivered, bounced, complained from the verified Resend webhook

This list explains the families, not an immutable enum. The recordEvent() call sites remain authoritative.

Privacy boundaries

  • event_log uses internal numeric subscriber and token ids when a flow has them; it does not copy the subscriber email into the event row.
  • Retryable cron and webhook paths use a dedup_key, and a partial unique index prevents duplicate events.
  • Feed-request security data such as hashed IP, user agent, country, status, and latency belongs to calendar_access_log, not to Mixpanel.
  • Raw subscriber email remains in the operational subscribers table because the service needs it to send and manage subscriptions.

Mixpanel history

Mixpanel was formerly a second event destination with a hashed distinct_id. That integration has been removed from server code, browser code, environment configuration, and the admin UI. There is no current /api/admin/mixpanel-test endpoint.

This file keeps its old mixpanel path so existing links do not break; its content describes the current D1 system.

Sources

  • ihnyc-rc-cal-landing/functions/_lib/events.ts
  • ihnyc-rc-cal-landing/functions/api/admin/events.ts
  • ihnyc-rc-cal-landing/functions/api/admin/funnel.ts
  • ihnyc-rc-cal-landing/functions/api/admin/cohort.ts
  • ihnyc-rc-cal-landing/functions/api/admin/replay.ts
  • ihnyc-rc-cal-landing/migrations/0006_events_and_email.sql