# Opportunity Scoring Model ## Overview The scoring model assigns each prospect a score from 0-100 based on the opportunity potential for offering web services. Higher scores indicate better leads. The model supports two channels: **digital** (domain-based) and **offline** (in-person discovery). ## Score Components — Digital Channel ### Technical Health (Max 40 points) Issues that indicate immediate opportunities: | Issue | Points | Condition | |-------|--------|-----------| | No SSL | 15 | `uses_https = false` | | Very Slow | 15 | `performance_score < 30` | | Slow | 10 | `performance_score < 50` | | Moderate Speed | 5 | `performance_score < 70` | | Not Mobile Friendly | 10 | `is_mobile_friendly = false` | ### Modernity / Stack (Max 25 points) Outdated technology stack: | Issue | Points | Condition | |-------|--------|-----------| | Outdated CMS | 15 | CMS is Drupal, Joomla, or TYPO3 | | Unknown CMS | 5 | No CMS detected but has website | | Legacy JavaScript | 5 | Uses jQuery without modern framework | | No Analytics | 5 | No Google Analytics or similar | ### Business Value (Max 25 points) Indicators of business potential: | Factor | Points | Condition | |--------|--------|-----------| | Has Website | 10 | Active website exists | | Has E-commerce | 10 | E-commerce platform detected | | Short Domain | 5 | Domain name <= 15 characters | ### Engagement Potential (Max 10 points) Ability to contact the business: | Factor | Points | Condition | |--------|--------|-----------| | Has Contacts | 5 | Any contact info found | | Has Email | 3 | Email address found | | Has Phone | 2 | Phone number found | ## Score Components — Offline Channel Offline leads have a simplified scoring model based on the information captured during in-person encounters: | Scenario | Technical Health | Modernity | Business Value | Engagement | Total | |----------|-----------------|-----------|----------------|------------|-------| | No website at all | 30 | 20 | 20 | 0 | **70** (top_priority) | | Uses gmail/free email | +0 | +10 | +0 | +0 | +10 | | Met in person | +0 | +0 | +0 | +5 | +5 | | Has email contact | +0 | +0 | +0 | +3 | +3 | | Has phone contact | +0 | +0 | +0 | +2 | +2 | A business with no website met in person with contact info scores: 70 + 5 + 3 + 2 = **80** (top_priority). ## Lead Tiers Based on the total score: | Tier | Score Range | Description | |------|-------------|-------------| | `top_priority` | 70-100 | Best leads, multiple issues or no website at all | | `quick_win` | 50-69 | Good leads, 1-2 easy fixes | | `strategic` | 30-49 | Moderate potential | | `low_priority` | 0-29 | Low opportunity | ## Reason Flags Each score includes `reason_flags` that explain why points were awarded: ```json { "score": 78, "reason_flags": ["no_ssl", "slow", "outdated_cms"], "lead_tier": "top_priority" } ``` Common flags (digital): - `no_ssl` — Missing HTTPS - `very_slow` — Performance score < 30 - `slow` — Performance score < 50 - `not_mobile_friendly` — Fails mobile tests - `outdated_cms` — Using old CMS - `legacy_js` — Using jQuery only - `no_analytics` — No tracking installed Offline-specific flags: - `no_website` — Business has no website - `uses_gmail` — Uses free email provider - `met_in_person` — Lead captured in person (warm lead) ## Customizing the Model The scoring logic is in `app/modules/prospecting/services/scoring_service.py`. You can adjust: 1. **Point values** — Change weights for different issues 2. **Thresholds** — Adjust performance score cutoffs 3. **Conditions** — Add new scoring criteria 4. **Tier boundaries** — Change score ranges for tiers