DEV Community

T.M. Gunderson
T.M. Gunderson

Posted on

I Built an AI Lead Scoring Agent That Prioritizes My Inbox While I Sleep (Full n8n Workflow JSON)

Every morning I'd open my inbox to 15–30 new inquiries. Half were spam. A quarter were tire-kickers. Maybe two were actually worth calling back. But I had to read all of them to figure out which two.

That's the lead scoring problem — and most small businesses solve it by... not solving it. They respond to everything equally, which means responding to nothing well.

Here's an n8n workflow that scores every incoming lead in under 2 seconds, tags the hot ones for immediate follow-up, and logs everything to a spreadsheet. Full importable JSON included.

The Problem: You're Spending 80% of Your Time on 20% of Your Leads

Harvard Business Review found that companies responding to leads within an hour are 7x more likely to qualify them (HBR, 2011). But if you're manually sorting leads, that hour disappears fast.

Meanwhile, Landbase reports that proper lead scoring creates 25% increases in lead conversion through improved prioritization.

The math is simple: if you can't identify which leads matter fast, you lose them.

What This Workflow Does

New Lead (Webhook/Form)
    → Enrich: pull company data from email domain
    → AI Score: GPT-4o evaluates the lead on 5 criteria
    → Route: Hot → Slack alert + priority tag
           Warm → CRM queue
           Cold → auto-archive
    → Log: Google Sheet with score, reasoning, and timestamp
Enter fullscreen mode Exit fullscreen mode

Cost: ~$0.02 per lead scored (GPT-4o-mini) or ~$0.08 per lead (GPT-4o).

Time to build: 20 minutes.

The 5 Scoring Criteria

The AI evaluates each lead on:

Criterion Weight What It Checks
Company fit 25% Does the company match your ideal customer profile?
Budget signals 25% Any mention of budget, pricing, or investment level?
Urgency 20% Timeline mentions, "ASAP," deadlines?
Authority 15% Job title and decision-making power
Engagement 15% How detailed is the inquiry? Specific needs > vague "tell me more"

Each criterion gets a 1–5 score. Weighted total produces a final score of 1–100.

The Full n8n Workflow JSON

Copy this entire block and paste it into n8n → Import from JSON:

{
  "name": "AI Lead Scoring Agent",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "lead-score",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-trigger",
      "name": "Webhook: New Lead",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://company.clearbit.com/v2/companies/find?domain={{ $json.body.email.split('@')[1] }}",
        "options": {},
        "headerParameters": {
          "parameters": [
            { "name": "Authorization", "value": "Bearer {{$env.CLEARBIT_API_KEY}}" }
          ]
        }
      },
      "id": "clearbit-enrich",
      "name": "Enrich: Company Data",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [220, 0]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {
          "temperature": 0.3
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a lead scoring assistant for a small business automation consultancy. Score each lead on a 1-100 scale based on these criteria:\n\n1. Company fit (25%): Does the company type/size match SMB automation services?\n2. Budget signals (25%): Any mention of budget, pricing, or investment range?\n3. Urgency (20%): Timeline mentions, deadlines, \"ASAP\" language?\n4. Authority (15%): Is the sender a decision-maker based on title?\n5. Engagement (15%): How specific and detailed is their inquiry?\n\nOutput ONLY valid JSON:\n{\n  \"score\": <number 1-100>,\n  \"tier\": \"<hot|warm|cold>\",\n  \"company_fit\": <1-5>,\n  \"budget_signal\": <1-5>,\n  \"urgency\": <1-5>,\n  \"authority\": <1-5>,\n  \"engagement\": <1-5>,\n  \"reasoning\": \"<2-3 sentence explanation>\",\n  \"suggested_action\": \"<specific next step>\"\n}"
            },
            {
              "role": "user",
              "content": "=Lead data:\nName: {{ $json.body.name }}\nEmail: {{ $json.body.email }}\nCompany: {{ $('Enrich: Company Data').item.json.name || $json.body.company || 'Unknown' }}\nIndustry: {{ $('Enrich: Company Data').item.json.category.industry || 'Unknown' }}\nEmployees: {{ $('Enrich: Company Data').item.json.metrics.employees || 'Unknown' }}\nMessage: {{ $json.body.message }}\nSource: {{ $json.body.source || 'website' }}"
            }
          ]
        }
      },
      "id": "ai-score",
      "name": "AI: Score Lead",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1.4,
      "position": [440, 0]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "operation": "equals",
              "value1": "={{ JSON.parse($json.message.content).tier }}",
              "value2": "hot"
            }
          ]
        }
      },
      "id": "check-hot",
      "name": "Is Hot Lead?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [660, 0]
    },
    {
      "parameters": {
        "channel": "lead-alerts",
        "text": "=🔥 HOT LEAD (Score: {{ JSON.parse($node['AI: Score Lead'].json.message.content).score }}/100)\n\n*{{ $node['Webhook: New Lead'].json.body.name }}* from *{{ JSON.parse($node['AI: Score Lead'].json.message.content).company_fit >= 4 ? $node['Enrich: Company Data'].json.name : 'Unknown' }}*\nEmail: {{ $node['Webhook: New Lead'].json.body.email }}\nMessage: {{ $node['Webhook: New Lead'].json.body.message }}\n\n*Why hot:* {{ JSON.parse($node['AI: Score Lead'].json.message.content).reasoning }}\n*Suggested action:* {{ JSON.parse($node['AI: Score Lead'].json.message.content).suggested_action }}",
        "otherFields": {}
      },
      "id": "slack-hot",
      "name": "Slack: Hot Lead Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.1,
      "position": [880, -100]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": "={{ $env.GOOGLE_SHEET_ID }}",
        "sheetName": "Leads",
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "timestamp": "={{ $now.toISO() }}",
            "name": "={{ $node['Webhook: New Lead'].json.body.name }}",
            "email": "={{ $node['Webhook: New Lead'].json.body.email }}",
            "company": "={{ $node['Enrich: Company Data'].json.name || 'Unknown' }}",
            "score": "={{ JSON.parse($node['AI: Score Lead'].json.message.content).score }}",
            "tier": "={{ JSON.parse($node['AI: Score Lead'].json.message.content).tier }}",
            "reasoning": "={{ JSON.parse($node['AI: Score Lead'].json.message.content).reasoning }}",
            "action": "={{ JSON.parse($node['AI: Score Lead'].json.message.content).suggested_action }}"
          }
        }
      },
      "id": "log-sheet",
      "name": "Log: Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.3,
      "position": [880, 100]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ score: JSON.parse($node['AI: Score Lead'].json.message.content).score, tier: JSON.parse($node['AI: Score Lead'].json.message.content).tier, reasoning: JSON.parse($node['AI: Score Lead'].json.message.content).reasoning }) }}"
      },
      "id": "respond-webhook",
      "name": "Respond: Score Result",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [1100, 0]
    }
  ],
  "connections": {
    "Webhook: New Lead": {
      "main": [
        [{ "node": "Enrich: Company Data", "type": "main", "index": 0 }]
      ]
    },
    "Enrich: Company Data": {
      "main": [
        [{ "node": "AI: Score Lead", "type": "main", "index": 0 }]
      ]
    },
    "AI: Score Lead": {
      "main": [
        [{ "node": "Is Hot Lead?", "type": "main", "index": 0 }]
      ]
    },
    "Is Hot Lead?": {
      "main": [
        [
          { "node": "Slack: Hot Lead Alert", "type": "main", "index": 0 },
          { "node": "Log: Google Sheet", "type": "main", "index": 0 }
        ],
        [
          { "node": "Log: Google Sheet", "type": "main", "index": 0 }
        ]
      ]
    },
    "Slack: Hot Lead Alert": {
      "main": [
        [{ "node": "Respond: Score Result", "type": "main", "index": 0 }]
      ]
    },
    "Log: Google Sheet": {
      "main": [
        [{ "node": "Respond: Score Result", "type": "main", "index": 0 }]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

How Each Node Works

1. Webhook Trigger

Receives lead data from your contact form, Calendly, or any HTTP POST. Expected fields: name, email, message, and optional company/source.

2. Clearbit Enrichment

Takes the email domain and pulls company metadata — name, industry, employee count. This gives the AI real data to score against instead of guessing.

No Clearbit account? You can skip this node — the AI still scores based on the lead's message alone. The enrichment improves accuracy but isn't required.

3. AI Scoring

GPT-4o-mini evaluates the lead against your 5 criteria and returns a structured JSON with score, tier, individual ratings, reasoning, and a suggested next action.

The system prompt is the heart of this workflow. Customize the company fit criteria to match your ideal customer profile. Sell to restaurants? Change "SMB automation services" to "restaurant operations." The more specific, the better the scoring.

4. Hot Lead Router

If the tier is "hot," it fires a Slack alert and logs to sheets. Warm and cold leads just get logged — no Slack noise.

5. Slack Alert

Only hot leads get an immediate Slack notification with score, reasoning, and suggested action. This means your team sees the important leads first, not buried under 20 low-priority inquiries.

6. Google Sheet Log

Every lead gets logged with timestamp, score, tier, and reasoning. Over time this becomes your conversion dataset — you can tune the scoring weights based on which leads actually closed.

Customization Tips

Tuning the scoring prompt is the highest-leverage thing you can do. After running 100 leads through this workflow, look at your Google Sheet and compare:

  • Leads that closed → what did they score?
  • Leads that ghosted → what did they score?

Then adjust the weights and criteria in the system prompt. Maybe urgency matters more for your business. Maybe company size is irrelevant. The AI adapts to whatever criteria you give it.

Other customizations worth trying:

  • Add a CRM node after logging — push hot leads directly to HubSpot, Pipedrive, or Close
  • Add email routing — auto-send a different welcome email based on tier
  • Add a Wait + Follow-up node — warm leads get an automated follow-up after 24 hours
  • Switch to GPT-4o for more nuanced scoring on high-value leads (costs ~4x more)

Cost Breakdown

Component Monthly Cost Notes
n8n (self-hosted) $0 Run on any $5/mo VPS
n8n (cloud) $20/mo Easier setup, no DevOps
GPT-4o-mini ~$0.40 At 200 leads/month
GPT-4o ~$1.60 At 200 leads/month
Clearbit Free Enrichment API free tier
Slack Free For hot lead alerts
Google Sheets Free Lead logging
Total $0.40/mo Self-hosted + free tiers

That's $0.002 per lead scored. A human takes 3–5 minutes per lead — this takes 2 seconds.

Why This Beats Manual Lead Triage

Most small businesses do one of three things:

  1. Respond to everything equally → slow responses to hot leads, wasted time on cold ones
  2. Ignore everything → leads go cold, conversion drops to zero
  3. Gut-feel prioritization → inconsistent, biased, doesn't scale

This workflow gives you option 4: consistent, fast, data-driven prioritization without adding headcount.

A study by Marketo (now Adobe Marketo Engage) found that organizations using lead scoring see 28% higher marketing ROI compared to those without (Salesforce research summary). The reason is simple: you stop spending time on leads that won't close.

What to Do Next

If you're already running n8n, this workflow imports in 30 seconds. Connect your Slack, add your OpenAI API key, and point your contact form at the webhook URL.

If you want more automations like this — invoice follow-ups, client onboarding sequences, weekly business reviews — grab the Boring Automation Pack ($15 CAD). It includes 5 copy-paste n8n workflows plus prompt templates.

Or start free with the AI Automation Cheat Sheet — 30+ automation ideas ranked by impact and difficulty.


We're building these tools and sharing what we learn. No fake case studies, no inflated numbers — just workflows we actually run and the data behind them.

Top comments (0)