Cold email outreach tracker with automated Day 0 / Day 3 / Day 7 follow-up sequence, Kanban dashboard, per-category templates, open tracking, and thread-safe email delivery via Autosend.
Stack: Node.js, Express 5, Prisma 6, PostgreSQL, Autosend API, Vercel
- Kanban board with 9 stages: New Leads → Queued → Day 0 Sent → Day 3 Sent → Day 7 Sent → Opened → Replied → Bounced → Dead
- Two outreach categories with separate template sets: Ignition and Instagram Collab
- Per-lead email timeline in detail panel (sent time, opens, follow-up status)
- Open tracking pixel + Autosend webhook for opens and bounces
- Follow-ups auto-cancel when lead is marked Replied or Bounced
- All 3 emails in one thread (shared
In-Reply-To+Referencesheaders) - Daily cap + configurable send window (default 7–11pm IST, Mon–Sat)
- Batch dispatcher sends oldest 5 new leads; individual 📤 send button per card
- CSV import and export
cron-job.org (7pm IST daily) cron-job.org (every 2 min)
POST /api/dispatch GET /api/cron
│ │
▼ ▼
┌──────────────────────────────────────────────────┐
│ Vercel Serverless Functions │
│ dispatch cron leads template track │
└──────────────────────────┬───────────────────────┘
│
PostgreSQL (Prisma)
Lead · EmailTemplate · ScheduledEmail
Flow:
- Add leads via UI or CSV import
- Dispatcher queues oldest N new leads (default 5)
- Cron picks one pending email per tick, sends it, queues next follow-up
- Open tracking pixel + Autosend webhook update lead stage automatically
Each category (Ignition / Instagram Collab) has 3 slots:
| Slot | Sent | Subject |
|---|---|---|
| Day 0 | Immediately after dispatch | Your template subject |
| Day 3 | 3 days after Day 0 | Same subject (for threading) |
| Day 7 | 4 days after Day 3 | Same subject (for threading) |
Variables: {{firstName}} {{lastName}} {{companyName}} {{email}}
Edit templates via Edit Templates button in the dashboard.
| Method | Path | Description |
|---|---|---|
| GET | /api/leads |
All leads with scheduled emails |
| POST | /api/leads |
Create lead |
| PUT | /api/leads |
Update lead (stage change cancels pending follow-ups) |
| DELETE | /api/leads |
Delete leads by IDs |
| POST | /api/dispatch |
Queue N new leads { limit, leadIds } |
| GET | /api/cron |
Send one pending email |
| GET | /api/track |
Open tracking pixel |
| GET/PUT | /api/template |
Read / update email templates |
| POST | /api/import |
CSV bulk import |
| POST | /api/webhooks/inbound |
Reply detection webhook |
| POST | /api/webhooks/autosend |
Autosend opened/bounced events |
| Setting | Value |
|---|---|
| URL | https://your-app.vercel.app/api/dispatch |
| Method | POST |
| Body | {"limit":5} |
| Header | Content-Type: application/json |
| Schedule | 30 13 * * 1-6 (7pm IST Mon–Sat) |
| Timezone | UTC |
| Setting | Value |
|---|---|
| URL | https://your-app.vercel.app/api/cron |
| Method | GET |
| Schedule | */2 * * * * |
DATABASE_URL=postgresql://user:pass@host:5432/outreach_tracker
AUTOSEND_API_KEY=AS_your_key_here
FROM_EMAIL=you@yourdomain.com
FROM_NAME=Your Name
FROM_DOMAIN=yourdomain.com
PUBLIC_URL=https://your-app.vercel.app
DAILY_CAP=10
SEND_WINDOW_START=19
SEND_WINDOW_END=23
SEND_WINDOW_DAYS=Mon,Tue,Wed,Thu,Fri,Sat
SEND_TIMEZONE=Asia/Kolkata
SKIP_WINDOW_CHECK=0
DISPATCH_BATCH_SIZE=5
PORT=3001git clone https://github.com/Varnan-Tech/outreach-tracker.git
cd outreach-tracker
npm install
cp .env.example .env # fill in your values
npx prisma db push
node scripts/seed-templates.js # seeds default templates
node server.jsOpen http://localhost:3001
npx vercel --prodSet all environment variables in Vercel dashboard → Settings → Environment Variables. Then wire the two cron jobs on cron-job.org.
All 3 emails in a sequence share the same In-Reply-To and References headers (<thread-{leadId}@yourdomain.com>), causing email clients to group them in one conversation thread. Keep Day 0, Day 3, and Day 7 subject lines identical for best results.