Your sales team is drowning in leads. Some are hot prospects ready to buy. Others are tire-kickers who'll waste hours of your team's time. The problem? You can't tell them apart until it's too late.
Enter AI-powered lead qualification.
What We're Building
By the end of this tutorial, you'll have a system that:
- ✅ Captures leads from any source (forms, ads, emails)
- ✅ Enriches leads with company data automatically
- ✅ Scores leads based on fit and intent signals
- ✅ Routes qualified leads to the right sales rep
- ✅ Nurtures unqualified leads until they're ready
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Lead Sources │
│ [Website Forms] [LinkedIn Ads] [Email] [Referrals] │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ n8n Workflow │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Capture │─▶│ Enrich │─▶│ Score │─▶│ Route │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
[Hot Leads] [Warm Leads] [Cold Leads]
→ Sales Rep → Nurture → Long-term
→ Immediate → Email Seq → Newsletter
Step 1: Lead Capture
First, let's set up a unified lead capture webhook that works with any source.
Webhook Setup in n8n
Create a webhook node that accepts POST requests:
// Expected payload structure
{
"source": "website_form",
"email": "lead@company.com",
"name": "John Smith",
"company": "Acme Corp",
"message": "Interested in your enterprise plan",
"utm_source": "google",
"utm_campaign": "ai_automation"
}
Normalize the Data
Different sources send data differently. Normalize it:
// Normalize lead data
const normalizedLead = {
email: $input.item.json.email?.toLowerCase().trim(),
name: $input.item.json.name || $input.item.json.full_name,
company: $input.item.json.company || $input.item.json.organization,
source: $input.item.json.source || 'unknown',
rawMessage: $input.item.json.message || '',
capturedAt: new Date().toISOString(),
utmSource: $input.item.json.utm_source,
utmCampaign: $input.item.json.utm_campaign
};
return { json: normalizedLead };
Step 2: Data Enrichment
Raw form data tells you very little. Let's enrich it.
Company Data Enrichment
Use an enrichment API (Clearbit, Apollo, or similar):
// Enrich with company data
const domain = email.split('@')[1];
const enrichmentData = await fetch(
`https://api.enrichment.io/company?domain=${domain}`,
{ headers: { 'Authorization': `Bearer ${apiKey}` } }
).then(r => r.json());
return {
...lead,
company: {
name: enrichmentData.name,
industry: enrichmentData.industry,
size: enrichmentData.employeeCount,
revenue: enrichmentData.estimatedRevenue,
technologies: enrichmentData.techStack,
linkedin: enrichmentData.linkedinUrl
}
};
LinkedIn Profile Enrichment
For B2B leads, LinkedIn data is gold:
// Add LinkedIn data
const linkedinData = await enrichLinkedIn(lead.email);
return {
...lead,
person: {
title: linkedinData.title,
seniority: linkedinData.seniorityLevel,
department: linkedinData.department,
yearsAtCompany: linkedinData.tenure
}
};
Step 3: AI-Powered Scoring
Now the magic—using AI to score leads intelligently.
Build Your Scoring Model
const scoringPrompt = `
Analyze this lead and provide a qualification score from 0-100.
Lead Data:
- Email: ${lead.email}
- Company: ${lead.company.name}
- Industry: ${lead.company.industry}
- Company Size: ${lead.company.size} employees
- Job Title: ${lead.person.title}
- Message: "${lead.rawMessage}"
Scoring Criteria:
- Company fit (industry, size, revenue): 40 points max
- Buyer persona match (title, seniority): 30 points max
- Intent signals (message content, urgency): 30 points max
Respond with JSON:
{
"score": <number>,
"companyFitScore": <number>,
"personaScore": <number>,
"intentScore": <number>,
"reasoning": "<brief explanation>",
"suggestedAction": "<immediate_call|schedule_demo|add_to_nurture|disqualify>"
}
`;
const response = await callClaudeAPI(scoringPrompt);
const scoring = JSON.parse(response);
Score Interpretation
| Score Range | Classification | Action |
|---|---|---|
| 80-100 | 🔥 Hot Lead | Immediate sales call |
| 60-79 | 🌡️ Warm Lead | Schedule demo within 24h |
| 40-59 | ❄️ Cool Lead | Add to nurture sequence |
| 0-39 | ❌ Not Qualified | Newsletter only |
Step 4: Intelligent Routing
Route leads to the right person based on multiple factors.
const routingRules = [
{
condition: lead.company.size > 500,
assignTo: 'enterprise_team'
},
{
condition: lead.company.industry === 'Healthcare',
assignTo: 'healthcare_specialist'
},
{
condition: lead.scoring.score >= 80,
assignTo: 'senior_ae',
priority: 'urgent'
},
{
condition: true, // default
assignTo: 'general_queue'
}
];
// Find matching rule
const route = routingRules.find(rule => rule.condition);
Step 5: CRM Integration
Push everything to your CRM with full context:
// Create/update in HubSpot
const hubspotPayload = {
properties: {
email: lead.email,
firstname: lead.name.split(' ')[0],
lastname: lead.name.split(' ').slice(1).join(' '),
company: lead.company.name,
jobtitle: lead.person.title,
industry: lead.company.industry,
numberofemployees: lead.company.size,
lead_score: lead.scoring.score,
lead_source: lead.source,
ai_qualification_notes: lead.scoring.reasoning
}
};
await hubspotAPI.createContact(hubspotPayload);
Results You Can Expect
After implementing this system, our clients typically see:
| Metric | Before | After |
|---|---|---|
| Time to qualify | 2 hours | 2 seconds |
| Qualified lead accuracy | 45% | 82% |
| Sales rep productivity | Baseline | +40% |
| Lead response time | 4 hours | 5 minutes |
Next Steps
- Start simple: Begin with one lead source and basic scoring
- Iterate on scoring: Review AI decisions weekly and refine criteria
- Add more enrichment: The more data, the better the scoring
- Automate nurturing: Build email sequences for each score tier
Need help implementing this system? Contact Fluxo and we'll build it for you in 2-4 weeks.



