Lead Scoring Flow
Overview
The lead scoring system processes Typeform webhook events to score leads and fire Facebook CAPI events. It runs on the FastAPI backend (www/web_app/backend).
Endpoint: POST /api/v1/leadscoring/webhook
Entry point: services/leadscoring.py → leadscoring_webhook()
Flow Diagram
Typeform Webhook
│
├─ event_type != "form_response" (partial)
│ │
│ ├─ 1. fire_capi_lead()
│ │ → Fire Facebook CAPI with event_name = "Lead"
│ │ → Logged to logs.facebook_capi_event_log (PostgreSQL)
│ │
│ ├─ 2. upsert_capi_lead_result()
│ │ → If email+client_id exists → update capi_lead=1, updated_at
│ │ → If not exists → insert new row (source="LEAD-SCORING", capi_lead=1)
│ │
│ └─ return OK
│
└─ event_type == "form_response" (full)
│
├─ Check scoring_method from client config
│ └─ If not "AI" → log warning, return OK (ML not supported yet)
│
└─ Run lead scoring in background (run_leadscoring_webhook)
│
├─ 1. Parse payload
│ → typeform_payload_to_dataframe() for Typeform clients
│ → parse_blush_payload_to_df() for Blush (client_id=30)
│
├─ 2. Extract fields
│ → email, phone, first_name, last_name (by role)
│ → question/answer pairs for AI prompt
│
├─ 3. Call Form AI
│ → call_form_ai_api_with_prompt()
│ → Primary: Gemini 2.0 Flash (temperature=0)
│ → Fallback: OpenAI GPT-4o (temperature=0)
│ → Returns: ai_fin, ai_show, ai_sql scores (0-1)
│ → Plus signals: scheduling_commitment, emotional_urgency,
│ personal_responsibility, financial_stability, investment_readiness
│
├─ 4. Calculate Rotator (config-driven)
│ → If p_fin >= a_rotator_fin AND p_show >= a_rotator_show → "A"
│ → Elif p_fin >= b_rotator_fin AND p_show >= b_rotator_show → "B"
│ → Else → "C"
│
├─ 5. Determine CAPI SubmitApplication (config-driven)
│ → Fire if p_fin >= fb_capi_fin AND p_show >= fb_capi_show
│ → event_name = "SubmitApplication" (hardcoded)
│ → Logged to logs.facebook_capi_event_log (PostgreSQL)
│
├─ 6. Save results
│ → Upsert to leadscoring.results (source="LEAD-SCORING")
│ → Stores: p_fin_model, p_show_model, p_sql_model, rotator,
│ capi_data, signals, capi_submitapp (1/0), updated_at
│
└─ Done
Manual CAPI Fire
Endpoint: POST /api/v1/leadscoring/fire-capi-event/{client_id}/{email}
Entry point: services/leadscoring.py → fire_lead_scoring_capi_event()
1. Look up existing LEAD-SCORING result for email+client_id
2. Read thresholds from settings (not capi_data):
- fb_capi_fin, fb_capi_show, capi_token, pixel_id
- event_name, event_source_url, action_source, test_event_code
3. Fire condition: p_fin >= fb_capi_fin AND p_show >= fb_capi_show
4. If fire → fire_facebook_capi_event() with event_name from settings
5. Update DB: capi_submitapp=1, capi_fired_to_fb=1, updated_at
6. Logged to logs.facebook_capi_event_log (PostgreSQL)
Configuration (Client Settings)
Stored in app.clients.lead_scoring_config (JSONB column).
Managed via UI: Lead Scoring Settings page.
Scoring Settings
| Field | Description | Default |
|---|---|---|
scoring_method | AI or ML (only AI supported) | AI |
fb_capi_fin | FB CAPI Financial Threshold (decimal 0-1) | 0.8 |
fb_capi_show | FB CAPI Show Threshold (decimal 0-1) | 0.6 |
a_rotator_fin | A Rotator Financial Threshold | 0.8 |
a_rotator_show | A Rotator Show Threshold | 0.8 |
b_rotator_fin | B Rotator Financial Threshold | 0.6 |
b_rotator_show | B Rotator Show Threshold | 0.3 |
c_rotator_fin | C Rotator Financial Threshold | 0 |
c_rotator_show | C Rotator Show Threshold | 0 |
Facebook CAPI Settings
| Field | Description |
|---|---|
capi_token | Facebook CAPI access token |
pixel_id | Facebook pixel ID |
event_name | CAPI event name (e.g., SubmitApplication) |
event_source_url | Event source URL |
action_source | Action source (website, email, app, etc.) |
test_event_code | Test event code (optional) |
capi_trigger_logic | Always "threshold" |
API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/leadscoring/webhook | Typeform webhook (partial → Lead CAPI, full → scoring) |
| GET | /api/v1/leadscoring?client_id=X&email=Y | Get scoring result |
| POST | /api/v1/leadscoring/fire-capi-event/{client_id}/{email} | Manually fire CAPI |
| GET | /api/v1/leadscoring/config/{client_id} | Get client config |
| PUT | /api/v1/leadscoring/config/{client_id} | Update client config |
| POST | /api/v1/leadscoring/predictions/{client_id} | Generate predictions |