Leads Pipeline — Prospective-Student Prospects
Purpose
This page explains how HUPH's Leads Pipeline works: how prospects are
automatically captured from WhatsApp conversations, how their stage is
managed, and how to use the /leads-v2 page for follow-up. Intended
for counselors and marketing staff whose job is to turn leads into
enrolled students.
Prerequisites
- Logged in as counselor or marketing
- WhatsApp channel active (Web & Telegram are no longer used as of April 2026)
LEAD_CAPTURE_ENABLED=truein env (default, no change needed)
Lead vs Conversation
A lead is NOT the same as a conversation:
- Conversation = the stream of messages between the user and bot/counselor
- Lead = a structured record containing the user's contact data (name, phone, email, program interest) extracted from the conversation
One conversation can produce 0 or 1 lead. One lead can have many conversations (if the user WAs in multiple times).
Lead Stages
Real DB enum: incomplete | new | contacted | qualified | enrolled |
lost.
| Stage | Meaning | When reached |
|---|---|---|
| incomplete | Capture not yet complete | Only the name detected, phone/email missing |
| new | Basic contact data complete, not yet contacted | Name + phone/email present, just formed |
| contacted | Counselor has reached out | Counselor clicks "Mark Contacted" on detail page |
| qualified | Serious lead, deserves heavier follow-up | Contacted + showing register/visit intent |
| enrolled | Officially enrolled | Manual update by admission admin after form submitted |
| lost | Uninterested / unreachable | Manual mark by counselor |
Steps
1. Open Leads Pipeline
Click Leads in the sidebar, then Leads v2 (URL:
/admin/leads-v2). You see the leads list with 30-second polling —
data auto-refreshes without reload.
┌────────────────────────────────────────────────────┐
│ Filter: [actionable] [all] [new] [qualified] … │
│ Search: [_________] │
│ │
│ Name Phone Stage Updated │
│ ────────────────────────────────────────────────── │
│ Budi Santoso +628123… new 5m ago │
│ Siti Aulia +628567… qualified 1h ago │
│ Rudi Hartono +628901… contacted 3h ago │
└────────────────────────────────────────────────────┘
2. Filter & search
Filter chips: actionable (non-enrolled, non-lost), all, or
per-stage (new, qualified, etc). Default is actionable — focus
on leads that need action.
Search: type a name, phone, or email → instant filter.
3. Open lead detail
Click a row → the detail page /admin/leads-v2/[id]. Detail shows:
- Full contact info (name, formatted phone, email, program interest if any)
- Status actions — Mark Contacted, Mark Qualified, Mark Enrolled, Mark Lost buttons
- Source conversation — link to the origin conversation
- Capture metadata — when name/phone/email were first detected and from which message
4. Update stage
Click the appropriate action — e.g. Mark Contacted after you reply to the user via WhatsApp. The stage updates and the polling refreshes the list view too.
5. How capture works behind the scenes
HUPH's contact extractor uses a 4-tier hybrid pipeline:
- Regex Layer 1 (always on) — detects Indonesian patterns like "nama saya X", "panggil X", phone format 62xxx
- LLM Layer 2 (gated) — Claude Haiku is called when capture is
active, or the
share_personal_infointent is detected, or the regex hit is weak - State machine for multi-turn slot filling (awaiting_name → awaiting_email → captured), 6-hour TTL
- Lead store atomic upsert on
(user_id, channel)
Counselors don't need to trigger anything manually — it all runs automatically from the first WhatsApp message.
6. Analytics overview
From the sidebar Leads → Analytics v2 (/admin/analytics-v2),
you will see about 13 charts: lead growth, stage distribution, funnel
conversion, source breakdown, counselor performance, etc. All charts
are near real-time (30s polling).
Example scenarios
Follow up this morning's qualified leads. Open
/admin/leads-v2, filter by qualified, see 6 new leads. The
counselor opens each one, replies via WhatsApp with an intro template
+ info-session invitation. After sending, clicks Mark Contacted
on the detail page. Within a minute the other counselors' lists are
refreshed too.
Monday-morning weekly review. Marketing opens /admin/analytics-v2
→ looks at the weekly Lead Growth chart: 127 new leads Mon–Sun, 34
qualified. Exports CSV for the head-of-admission report.
Troubleshooting
Lead stuck at "incomplete" even though the user provided all
info. Symptom: the list shows a lead as incomplete even though
the user chatted full details like "my name is Rudi, phone 081234,
email rudi@..". Cause: the LLM extractor may have failed or timed
out. Fix: open the detail → check the capture metadata → if name,
phone, and email are all present, manually Advance Stage to
new. If it still errors, report to dev team — the feature flag
LEAD_CAPTURE_ENABLED may be off.
New lead doesn't appear 5 minutes after user chat. Symptom: user
WAs in and provides a name but nothing shows in /leads-v2. Cause:
possibly a webhook delay or a stuck state machine. Fix: refresh the
page (Ctrl+Shift+R), check the filter (may be hidden by the default
actionable), then check Conversations to see if the thread
actually exists.
Analytics v2 numbers don't match the list count. Symptom: the list shows 26 leads but Analytics says 28. Cause: 30s polling + aggregate delay — a few seconds of lag between list and chart. Fix: refresh after 1 minute; it usually reconciles.
Cannot "Mark Enrolled". Symptom: the Mark Enrolled button is
disabled or missing. Cause: the enrolled stage can only be set by
admission admins (role-gated). Fix: escalate to an admin for the
update.
See also
- Inbox — see the source conversation of a lead
- Follow-up — automated re-engagement for leads
- Escalation — how cluster ownership affects counselor access to leads