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)