Leads
Sources
Leads flow into the CRM from:
| Source | Mechanism |
|---|---|
| Website forms | Tenant embeds a script or webhook URL in their contact form |
| Facebook Lead Ads | Auto-captured via Meta Webhooks when a lead form is submitted |
| Google Ads Lead Form Extensions | Via Google Ads API or webhook |
| Manual entry | DM team or tenant manually adds a lead |
| CSV import | Bulk import via file upload |
Data model
leads
Contacts captured from any source.
| Column | Type | Notes |
|---|---|---|
tenant_id | uuid FK → tenants | |
source | enum | website_form | facebook_lead_ad | google_lead_form | manual | import | other |
source_channel_id | uuid FK → channels | NULL for manual/import |
source_campaign_id | uuid FK → ad_campaigns | NULL unless from a paid campaign |
first_name | varchar(255) | |
last_name | varchar(255) | |
email | varchar(255) | |
phone | varchar(50) | |
company | varchar(255) | |
job_title | varchar(255) | |
message | text | Message from form or lead ad answers |
source_url | varchar(1000) | Landing page or ad URL |
utm_source | varchar(255) | |
utm_medium | varchar(255) | |
utm_campaign | varchar(255) | |
status | enum | new | contacted | qualified | disqualified | converted |
score_total | integer | Current lead score from 0-100 |
score_band | enum | cold | warm | hot |
score_version | varchar(50) | Scoring model version, e.g. v1.0 |
score_updated_on | timestamptz | Last scoring update timestamp |
disqualification_reason | text | |
assigned_to | uuid FK → users | |
enrichment_data | jsonb | { linkedinUrl, companySize, industry, website } |
notes | text | |
last_activity_on | timestamptz | |
nurture_status | enum | not_enrolled | active | paused | completed | exited |
current_sequence_id | uuid FK → lead_nurture_sequences | NULL when not enrolled |
next_nurture_step_on | timestamptz | Next scheduled nurture step |
Indexes
CREATE INDEX idx_leads_tenant_status
ON leads(tenant_id, status, created_on);
CREATE INDEX idx_leads_source
ON leads(tenant_id, source, source_campaign_id);
CREATE INDEX idx_leads_score
ON leads(tenant_id, score_total DESC, status, last_activity_on DESC);
CREATE INDEX idx_leads_nurture_next_step
ON leads(tenant_id, nurture_status, next_nurture_step_on);Enrichment
When a new lead is captured, an optional auto-enrichment step runs to look up company info, LinkedIn profile, and other firmographic data. The result is stored in enrichment_data (jsonb) and an enrichment activity is logged on the lead’s timeline.
Scoring snapshot
The lead row stores the latest score snapshot (score_total, score_band, score_version, score_updated_on) for fast filtering and ranking. Detailed factor-level score breakdowns are stored separately (see lead-scoring.md).
Nurture sequence state
The lead row stores only the current nurture execution state for scheduling and queue pickup. Sequence definitions and per-step execution logs are stored in dedicated nurture tables (see nurture-sequences.md).
Related
- Pipeline — lead lifecycle and qualification workflow
- Activities — lead activity timeline
- Lead scoring — score model and ranking logic
- Nurture sequences — automated follow-up flows
- Database schema