---
# === IDENTITY ===
id: business/lead-generation/lead-scoring-implementation/2026
canonical_question: "How do I implement lead scoring — weighted model from ICP, threshold calibration, CRM/spreadsheet implementation?"
aliases:
  - "Lead scoring model implementation with ICP-weighted criteria"
  - "How to build a lead scoring system in spreadsheet or CRM"
  - "MQL SQL threshold calibration for lead scoring models"
entity_type: execution_recipe
domain: business > lead-generation > lead scoring implementation
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-03-11
confidence: 0.88
version: 1.0
first_published: 2026-03-11

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: null
  next_review: 2026-09-07
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Lead scoring requires minimum 50 historical closed-won deals for meaningful threshold calibration"
  - "Recalibrate scoring model quarterly — ICP fit degrades as market conditions change"
  - "Limit scoring criteria to 8-12 attributes maximum — more creates noise and maintenance burden"
  - "MQL threshold should yield 15-30% conversion to SQL; lower means threshold is too loose"
  - "Score decay: leads older than 90 days without engagement should lose 10-20 points/month"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need to source or enrich leads first"
    use_instead: "business/lead-generation/lead-enrichment-pipeline/2026"
  - condition: "Want predictive ML-based scoring, not rule-based"
    use_instead: null
  - condition: "Have fewer than 20 closed deals — insufficient calibration data"
    use_instead: null

# === AGENT HINTS ===
inputs_needed:
  - key: scoring_platform
    question: "Where will the scoring model be implemented?"
    type: choice
    options: ["spreadsheet (Google Sheets/Excel)", "HubSpot CRM", "Salesforce", "custom code (Python/JS)"]
  - key: data_completeness
    question: "How complete is the enriched lead data?"
    type: choice
    options: ["basic (name + company + title)", "standard (+ email + industry + size)", "full (+ phone + tech stack + revenue)"]
  - key: historical_deals
    question: "How many closed-won deals available for calibration?"
    type: choice
    options: ["0-20 (no calibration possible)", "20-100 (basic calibration)", "100+ (full calibration)"]

# === EXECUTION METADATA ===
execution:
  required_inputs:
    - name: "Enriched lead list"
      source: "agents/lead-enrichment"
      format: "CSV with firmographic + contact data"
    - name: "ICP definition"
      source: "agents/startup/persona-builder"
      format: "structured data with weighted criteria"
    - name: "Historical deal data (optional)"
      source: "CRM export"
      format: "CSV with won/lost deals and lead attributes"
  outputs:
    - name: "Scored lead database"
      format: "CSV"
      description: "Leads with composite score, tier (MQL/SQL/Nurture), and per-criterion breakdown"
    - name: "Scoring model documentation"
      format: "JSON"
      description: "Criteria, weights, thresholds, and calibration notes"
  tools_required:
    - name: "Google Sheets or Excel"
      purpose: "Scoring model implementation and calculation"
      tier: "free"
      cost: "$0"
      alternatives: ["HubSpot (free CRM)", "Python pandas", "Airtable"]
    - name: "HubSpot CRM (optional)"
      purpose: "Automated scoring with workflow triggers"
      tier: "paid"
      cost: "$0 (free CRM) to $890/mo (Marketing Hub Pro with scoring)"
      alternatives: ["Salesforce ($25+/mo)", "Pipedrive ($14/mo)"]
  credentials_needed:
    - service: "HubSpot"
      type: "API key or OAuth"
      where_to_get: "https://app.hubspot.com/settings/api"
      free_tier_limits: "Free CRM — manual scoring. Marketing Hub Pro ($890/mo) for automated scoring"
  estimated_duration: "30-60 minutes for model creation; 15 minutes per 500 leads for scoring"
  estimated_cost: "$0 (spreadsheet) to $890/month (HubSpot Marketing Hub Pro)"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/lead-generation/lead-scoring-implementation/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-11)"

# === RELATED UNITS ===
related_kos:
  depends_on:
    - id: "business/lead-generation/lead-enrichment-pipeline/2026"
      label: "Enriched lead data is required for scoring"
    - id: "business/customer-research/ideal-customer-profile-framework/2026"
      label: "Building an ICP — firmographic (B2B) or demographic (B2C) criteria, behavioral signals, disqualification criteria"
  feeds_into:
    - id: "business/lead-generation/email-verification-workflow/2026"
      label: "Verify emails for high-score leads before outreach"
  related_to: []
  alternative_to: []

# === SOURCES ===
sources:
  - id: src1
    title: "What is Lead Scoring? How to Build a Scoring Model"
    author: ZoomInfo
    url: https://pipeline.zoominfo.com/marketing/lead-scoring
    type: industry_report
    published: 2025-09-15
    reliability: high
  - id: src2
    title: "HubSpot Lead Scoring in 2025: Setup, Models, Automation"
    author: Pixcell
    url: https://www.pixcell.io/blog/lead-scoring-hubspot
    type: technical_blog
    published: 2025-10-20
    reliability: high
  - id: src3
    title: "Evolution of CRM Lead Scoring in 2025"
    author: Coefficient
    url: https://coefficient.io/lead-scoring/crm-lead-scoring
    type: technical_blog
    published: 2025-11-10
    reliability: high
  - id: src4
    title: "Lead Scoring Best Practices: Definitive Guide"
    author: Salespanel
    url: https://salespanel.io/blog/marketing/lead-scoring-best-practices/
    type: technical_blog
    published: 2025-08-25
    reliability: high
  - id: src5
    title: "Ultimate Guide to Demographic Lead Scoring Models"
    author: LeadBoxer
    url: https://www.leadboxer.com/learn/ultimate-guide-to-demographic-lead-scoring-models
    type: technical_blog
    published: 2025-07-15
    reliability: high
  - id: src6
    title: "Lead Scoring Models Explained"
    author: Distribution Engine
    url: https://nc-squared.com/blog/article/what-are-lead-scoring-models
    type: technical_blog
    published: 2025-12-01
    reliability: high
---

# Lead Scoring Implementation

## Purpose

This recipe creates a weighted lead scoring model that assigns a 0-100 composite score to each lead based on ICP fit (demographic/firmographic) and engagement signals, classifying leads into Nurture (0-49), MQL (50-74), and SQL (75+) tiers. The output is a scored lead database with per-criterion breakdowns, ready for prioritized outreach sequencing.

## Prerequisites

- [ ] **Enriched lead list** from enrichment pipeline — [Lead Enrichment Pipeline](/business/lead-generation/lead-enrichment-pipeline/2026)
- [ ] **ICP definition** from persona-builder — [ICP Definition](/business/customer-research/ideal-customer-profile-definition/2026)
- [ ] **Historical deal data** (optional but recommended) — CSV with closed-won/lost deals and attributes
- [ ] **Scoring platform** — Google Sheets, HubSpot CRM, or Python environment

## Constraints

- Minimum 50 historical closed-won deals needed for meaningful threshold calibration. Without historical data, use industry benchmarks for initial thresholds. [src1]
- Recalibrate quarterly — include feedback from sales on lead quality at each tier. [src4]
- Limit to 8-12 scoring criteria maximum. More creates complexity without improving signal-to-noise ratio. [src5]
- MQL-to-SQL conversion should be 15-30%. Below 15% means MQL threshold is too loose (passing bad leads). Above 30% means it is too tight (missing good leads). [src1]
- Score decay: leads without engagement for 90+ days should lose 10-20 points per month to prevent stale leads clogging the pipeline. [src4]

## Tool Selection Decision

```
Which path?
├── No CRM AND < 500 leads
│   └── PATH A: Google Sheets formula-based scoring
├── HubSpot CRM user
│   └── PATH B: HubSpot custom properties + workflows
├── Salesforce user
│   └── PATH C: Salesforce lead scoring rules
└── Developer with custom stack
    └── PATH D: Python scoring script + CSV/API output
```

| Path | Tools | Cost | Automation | Scalability |
|------|-------|------|-----------|-------------|
| A: Spreadsheet | Google Sheets | $0 | Manual | Up to 2,000 leads |
| B: HubSpot | HubSpot Marketing Hub | $0-$890/mo | Full | Unlimited |
| C: Salesforce | Salesforce + Einstein | $25-$300/mo | Full | Unlimited |
| D: Python | Python + pandas | $0 | Semi-auto | Unlimited |

## Execution Flow

### Step 1: Define Scoring Criteria and Weights

**Duration**: 15-20 minutes
**Tool**: Spreadsheet or document

Build the scoring model from ICP attributes. Each criterion gets a maximum point allocation that reflects its importance.

```
SCORING MODEL (100 points total)

FIT CRITERIA (60 points max):
  Title match        : 0-20 points (VP/C-level=20, Director=15, Manager=10, Other=0)
  Company size        : 0-15 points (ICP range=15, adjacent=8, outside=0)
  Industry match      : 0-10 points (target industry=10, related=5, other=0)
  Geography           : 0-5  points (target region=5, secondary=3, other=0)
  Revenue range       : 0-5  points (target range=5, adjacent=3, other=0)
  Tech stack match    : 0-5  points (uses target tech=5, compatible=3, none=0)

ENGAGEMENT CRITERIA (40 points max):
  Email verified      : 0-10 points (verified=10, unverified=0)
  Phone available     : 0-10 points (direct dial=10, main line=5, none=0)
  LinkedIn connected  : 0-5  points (connected=5, 2nd degree=3, 3rd=0)
  Data freshness      : 0-5  points (< 30 days=5, < 90=3, older=0)
  Data completeness   : 0-10 points (all fields=10, most=7, few=3)
```

**Verify**: All criteria weights sum to 100. No single criterion exceeds 25% of total. [src5]
**If failed**: Rebalance weights. The most predictive criteria for your business should carry the most weight.

### Step 2: Implement Scoring Formula

**Duration**: 15-20 minutes
**Tool**: Google Sheets or Python

```python
import pandas as pd

def score_lead(lead, icp_config):
    """Calculate composite lead score 0-100"""
    score = 0

    # Title match (0-20)
    title = str(lead.get("title", "")).lower()
    if any(t in title for t in ["vp", "vice president", "c-level", "ceo", "cto", "cfo", "cmo"]):
        score += 20
    elif any(t in title for t in ["director", "head of"]):
        score += 15
    elif "manager" in title:
        score += 10

    # Company size match (0-15)
    size = lead.get("company_size", 0)
    if icp_config["size_min"] <= size <= icp_config["size_max"]:
        score += 15
    elif size > 0:
        score += 8

    # Industry match (0-10)
    industry = str(lead.get("industry", "")).lower()
    if industry in icp_config["target_industries"]:
        score += 10
    elif industry in icp_config["related_industries"]:
        score += 5

    # Geography (0-5)
    geo = str(lead.get("state", lead.get("country", ""))).lower()
    if geo in icp_config["target_geos"]:
        score += 5

    # Revenue (0-5)
    revenue = lead.get("revenue_range", "")
    if revenue in icp_config["target_revenue"]:
        score += 5

    # Tech stack (0-5)
    tech = lead.get("tech_stack", [])
    if any(t in icp_config["target_tech"] for t in tech):
        score += 5

    # Email verified (0-10)
    if lead.get("email") and lead.get("email_confidence", 0) > 80:
        score += 10

    # Phone available (0-10)
    if lead.get("phone"):
        score += 10

    # Data completeness (0-10)
    fields_filled = sum(1 for f in ["email", "phone", "company_size", "industry", "title"]
                        if lead.get(f))
    score += min(10, fields_filled * 2)

    return min(100, score)

# ICP configuration
icp_config = {
    "size_min": 50, "size_max": 500,
    "target_industries": ["saas", "software", "technology"],
    "related_industries": ["fintech", "martech", "healthtech"],
    "target_geos": ["california", "new york", "texas"],
    "target_revenue": ["$10M-$50M", "$50M-$100M"],
    "target_tech": ["hubspot", "salesforce", "stripe"]
}

# Score all leads
leads = pd.read_csv("enriched_leads.csv")
leads["score"] = leads.apply(lambda row: score_lead(row, icp_config), axis=1)
```

**Verify**: Score distribution should be roughly normal. If > 50% score above 75, criteria are too loose.
**If failed**: Increase weight differentiation between tiers. Ensure "Other" values score 0, not a default.

### Step 3: Set and Calibrate Thresholds

**Duration**: 10-15 minutes
**Tool**: Python or Sheets analysis

```python
# Classify leads into tiers
def classify_lead(score):
    if score >= 75:
        return "SQL"
    elif score >= 50:
        return "MQL"
    else:
        return "Nurture"

leads["tier"] = leads["score"].apply(classify_lead)

# Distribution analysis
tier_counts = leads["tier"].value_counts()
print("Tier Distribution:")
print(tier_counts)
print(f"\nMQL rate: {tier_counts.get('MQL', 0) / len(leads) * 100:.1f}%")
print(f"SQL rate: {tier_counts.get('SQL', 0) / len(leads) * 100:.1f}%")

# Target: 10-20% SQL, 20-35% MQL, 45-70% Nurture
# If SQL > 25%, tighten threshold to 80
# If SQL < 5%, loosen threshold to 70
```

**Verify**: SQL tier = 10-20% of total leads. MQL tier = 20-35%. If outside these ranges, adjust thresholds. [src1]
**If failed**: If nearly all leads score similarly, the scoring criteria lack differentiation. Add more granularity to the highest-weighted criteria.

### Step 4: Validate Against Historical Data (if available)

**Duration**: 15-20 minutes
**Tool**: Python

```python
# If you have historical closed-won/lost data
if "deal_outcome" in leads.columns:
    won = leads[leads["deal_outcome"] == "won"]
    lost = leads[leads["deal_outcome"] == "lost"]

    print(f"Won deals avg score: {won['score'].mean():.1f}")
    print(f"Lost deals avg score: {lost['score'].mean():.1f}")
    print(f"Score difference: {won['score'].mean() - lost['score'].mean():.1f}")

    # Good model: won avg should be 15+ points higher than lost avg
    # If difference < 10, the model has poor discrimination
```

**Verify**: Won deal average score is at least 15 points higher than lost deal average. [src4]

### Step 5: Export Scored Leads with Documentation

**Duration**: 5-10 minutes

```python
# Sort by score descending
leads = leads.sort_values("score", ascending=False)

# Add scoring metadata
leads["scored_date"] = "2026-03-11"
leads["model_version"] = "v1.0"

leads.to_csv("scored_leads.csv", index=False)

# Export model documentation
model_doc = {
    "version": "1.0",
    "created": "2026-03-11",
    "criteria_count": 10,
    "total_points": 100,
    "thresholds": {"SQL": 75, "MQL": 50, "Nurture": 0},
    "tier_distribution": tier_counts.to_dict(),
    "next_calibration": "2026-06-11"
}

import json
with open("scoring_model.json", "w") as f:
    json.dump(model_doc, f, indent=2)
```

**Output files**:
- `scored_leads.csv` — Leads with scores, tiers, and per-criterion breakdowns
- `scoring_model.json` — Model documentation for reproducibility

## Output Schema

```json
{
  "output_type": "scored_lead_database",
  "format": "CSV",
  "columns": [
    {"name": "first_name", "type": "string", "description": "Contact first name", "required": true},
    {"name": "last_name", "type": "string", "description": "Contact last name", "required": true},
    {"name": "company", "type": "string", "description": "Company name", "required": true},
    {"name": "score", "type": "number", "description": "Composite lead score 0-100", "required": true},
    {"name": "tier", "type": "string", "description": "SQL, MQL, or Nurture", "required": true},
    {"name": "title_score", "type": "number", "description": "Title match sub-score", "required": false},
    {"name": "size_score", "type": "number", "description": "Company size sub-score", "required": false},
    {"name": "email", "type": "string", "description": "Work email", "required": false},
    {"name": "model_version", "type": "string", "description": "Scoring model version", "required": true}
  ],
  "expected_row_count": "200-5000",
  "sort_order": "score descending",
  "deduplication_key": "email"
}
```

## Quality Benchmarks

| Quality Metric | Minimum Acceptable | Good | Excellent |
|---------------|-------------------|------|-----------|
| SQL tier rate | 5-25% | 10-20% | 12-18% |
| MQL tier rate | 15-40% | 20-35% | 25-30% |
| Won vs lost score diff | > 10 pts | > 15 pts | > 20 pts |
| Criteria count | 6-15 | 8-12 | 8-10 |
| Quarterly recalibration | Yes | Yes + sales feedback | Yes + conversion tracking |

**If below minimum**: Review scoring criteria weights. Validate against closed deal data. Get sales team input.

## Error Handling

| Error | Likely Cause | Recovery Action |
|-------|-------------|----------------|
| All leads score similarly (low variance) | Criteria lack differentiation | Add more granularity to top-weighted criteria |
| SQL tier > 30% | Threshold too loose | Raise SQL threshold to 80-85 |
| SQL tier < 5% | Threshold too tight or ICP too narrow | Lower threshold to 70 or broaden ICP |
| Missing enrichment data | Upstream enrichment incomplete | Re-run enrichment pipeline for missing fields |
| Model disagrees with sales intuition | Wrong attribute weights | Interview sales, adjust weights based on feedback |

## Cost Breakdown

| Component | Free Tier | Paid Tier | At Scale |
|-----------|-----------|-----------|----------|
| Spreadsheet scoring | $0 | $0 | $0 |
| HubSpot lead scoring | N/A (Pro only) | $890/mo | $890/mo |
| Salesforce Einstein | N/A | $25-$300/mo | $300/mo |
| Custom Python script | $0 | $0 | $0 |
| **Total** | **$0** | **$25-$890/mo** | **$300-$890/mo** |

## Anti-Patterns

### Wrong: Scoring with more than 15 criteria
Adding every possible data point creates noise, makes the model hard to maintain, and obscures which factors actually predict conversion. [src5]

### Correct: Limit to 8-12 high-signal criteria
Focus on criteria with proven correlation to closed-won deals. Drop criteria that do not differentiate winners from losers. [src5]

### Wrong: Setting thresholds without data and never recalibrating
Static thresholds based on gut feel degrade over time as ICP evolves. MQL-to-SQL conversion drops below 10%, sales loses trust in marketing leads. [src4]

### Correct: Calibrate with historical data, recalibrate quarterly
Use closed-won/lost analysis to set initial thresholds. Review quarterly with sales feedback. Adjust if MQL-to-SQL drops below 15%. [src4]

## When This Matters

Use when the agent has an enriched lead list that needs prioritization before outreach. Converts raw data into actionable tiers (SQL/MQL/Nurture) that determine outreach sequence, messaging, and resource allocation. Requires enrichment pipeline output as input.

## Related Units

- [Lead Enrichment Pipeline](/business/lead-generation/lead-enrichment-pipeline/2026)
- [ICP Definition](/business/customer-research/ideal-customer-profile-definition/2026)
- [Email Verification Workflow](/business/lead-generation/email-verification-workflow/2026)
- [Apollo/ZoomInfo API Lead Pull](/business/lead-generation/apollo-zoominfo-api-lead-pull/2026)
- [LinkedIn Sales Navigator Scraping](/business/lead-generation/linkedin-sales-navigator-scraping-workflow/2026)
