Skip to main content

Convex Integration

Convex provides real-time database capabilities for Kinetic Email's tracking system.

Why Convex?

Email interaction tracking requires:

  • Real-time updates — See opens and clicks as they happen
  • High write throughput — Tracking pixels fire frequently
  • Low-latency reads — Station dashboard needs instant data
  • Simple schema — Event-based data is naturally document-oriented

Convex handles all of these better than polling a traditional database.

Schema

// convex/schema.ts (abridged)
kinetic_events: defineTable({
userId: v.string(), // hashed recipient ID
sendId: v.string(),
emailName: v.string(),
actionId: v.string(),
timestamp: v.number(),
source: v.optional(v.string()), // 'kinetic' | 'amp'
databaseId: v.optional(v.string()), // workspace tracking_uuid
projectId: v.optional(v.string()),
metadata: v.optional(v.object({ ... })),
})

email_sends: defineTable({
sendId: v.string(),
userId: v.string(),
emailName: v.string(),
recipientEmail: v.string(),
subject: v.string(),
sentAt: v.number(),
htmlContent: v.optional(v.string()), // for View in Browser
// ...
})

Data Flow

Email opened in client


Tracking pixel loads: GET /api/track-pixel?u=...&s=...&e=...&a=...


Vercel function logs event to Convex


Convex triggers real-time subscription


Station dashboard updates instantly

Configuration

Set VITE_CONVEX_URL (frontend) and NEXT_PUBLIC_CONVEX_URL (serverless API functions) to your Convex deployment URL. Deploy Convex functions with:

npx convex deploy

The build pipeline runs Convex deploy first, before the Vite build.

Station Dashboard

The Kinetic Database page (/station/database) queries Convex in real-time to display:

  • Open rates by send
  • Interaction heatmaps
  • Engagement timelines
  • Action breakdowns (which tabs/options were most popular)