Lead Scoring
Lead scoring ranks leads by conversion likelihood so teams can prioritize outreach and qualification effort.
Goals
- Rank leads in a consistent, explainable way
- Route high-intent leads faster to human follow-up
- Trigger automation (alerts, nurture enrollment, queue priority)
- Improve qualified-to-converted rate over time
Scoring model
score_total is calculated on a 0-100 scale from weighted signals:
- Fit signals (who the lead is)
- Intent signals (what the lead has shown interest in)
- Engagement signals (how the lead interacts with outreach)
- Negative signals (inactive/bad-fit/spam indicators)
Formula:
score_total = clamp(0, 100, fit_score + intent_score + engagement_score - negative_score)Suggested weights (v1.0)
| Category | Weight | Example factors |
|---|---|---|
| Fit | 40 | Company size match, industry match, geography, job title |
| Intent | 35 | Pricing page visit, demo request, high-value form answers |
| Engagement | 25 | Email open/reply, call connected, repeat site visits |
| Negative | -30 max | Bounce, unsubscribe, invalid contact, spam pattern |
Weights are tenant-configurable with sane defaults.
Score bands
| Band | Range | Meaning |
|---|---|---|
hot | 70-100 | High-priority follow-up now |
warm | 40-69 | Qualified for nurture or light-touch follow-up |
cold | 0-39 | Low-priority; monitor or disqualify |
Band thresholds are configurable per tenant.
Recalculation triggers
Score recalculation runs on:
- Lead created
- Enrichment completed
- New activity logged (
email_received,call, page intent event) - Status changed
- Manual recompute request
- Daily scheduled refresh for stale leads
Data model additions
leads (snapshot fields)
| Column | Type | Notes |
|---|---|---|
score_total | integer | 0-100 current score |
score_band | enum | cold | warm | hot |
score_version | varchar(50) | Scoring rule version |
score_updated_on | timestamptz | Last recompute time |
lead_score_factors
Stores explainability and audit trail for each recompute.
| Column | Type | Notes |
|---|---|---|
tenant_id | uuid FK → tenants | |
lead_id | uuid FK → leads | |
model_version | varchar(50) | e.g. v1.0 |
factor_key | varchar(100) | e.g. job_title_match |
factor_category | enum | fit | intent | engagement | negative |
points | integer | Signed points contribution |
details | jsonb | Raw evidence for the factor |
created_on | timestamptz |
Indexes:
CREATE INDEX idx_lead_score_factors_lead
ON lead_score_factors(tenant_id, lead_id, created_on DESC);Workflow usage
- Sort list views by
score_total DESC - Auto-assign hot leads to owners
- Trigger alerts when a lead crosses warm → hot
- Auto-enroll warm leads into nurture when no reply after N days
Guardrails
- Do not use protected-class attributes directly in scoring
- Keep factor-level explanations visible to users
- Version scoring rules and keep historical scores reproducible
- Allow manual override with required reason logging