Score HubSpot leads based on firmographic and technographic fit using n8n

medium complexityCost: $0-24/moRecommended

Prerequisites

Prerequisites
  • n8n instance (cloud or self-hosted)
  • HubSpot private app token with crm.objects.contacts.read and crm.objects.contacts.write scopes
  • A custom HubSpot contact property for the fit score (e.g., icp_fit_score, number type, 0-100)
  • n8n HubSpot credential configured
  • Enriched contact data already in HubSpot (company size, industry, job title)

Step 1: Add a HubSpot Trigger node

Create a new workflow and add a HubSpot Trigger node:

  • Authentication: Select your HubSpot credential
  • Event: Contact Property Changed
  • Property: hs_analytics_source (or whichever property is updated when enrichment completes)

This fires when a contact's enrichment data is updated, signaling it's time to score.

Alternative triggers

You can also trigger on contact creation (Contact Created) to score every new lead immediately. Or use a Schedule Trigger to batch-score all contacts every hour.

Step 2: Fetch full contact details

The trigger only sends the contact ID. Add an HTTP Request node to get the full record:

  • Method: GET
  • URL: https://api.hubapi.com/crm/v3/objects/contacts/{{ $json.objectId }}
  • Authentication: Predefined -> HubSpot API
  • Query params: properties=firstname,lastname,jobtitle,company,numberofemployees,industry,hs_analytics_source

Step 3: Score the contact with a Code node

Add a Code node with your scoring model:

const contact = $('Fetch Contact').first().json.properties;
 
let score = 0;
 
// --- Company size scoring (0-30 points) ---
const employees = parseInt(contact.numberofemployees || '0');
if (employees >= 200 && employees <= 2000) score += 30;      // sweet spot
else if (employees >= 50 && employees < 200) score += 20;    // good fit
else if (employees >= 2000 && employees <= 10000) score += 15; // enterprise
else if (employees > 0) score += 5;                           // at least known
 
// --- Industry scoring (0-25 points) ---
const industry = (contact.industry || '').toLowerCase();
const idealIndustries = ['saas', 'technology', 'software', 'computer software'];
const goodIndustries = ['financial services', 'consulting', 'marketing'];
if (idealIndustries.includes(industry)) score += 25;
else if (goodIndustries.includes(industry)) score += 15;
else if (industry) score += 5;
 
// --- Seniority scoring (0-30 points) ---
const title = (contact.jobtitle || '').toLowerCase();
const cSuite = ['ceo', 'cto', 'cfo', 'coo', 'cmo', 'cro', 'chief'];
const vp = ['vp', 'vice president', 'head of'];
const director = ['director', 'senior director'];
const manager = ['manager', 'senior manager', 'lead'];
 
if (cSuite.some(t => title.includes(t))) score += 30;
else if (vp.some(t => title.includes(t))) score += 25;
else if (director.some(t => title.includes(t))) score += 20;
else if (manager.some(t => title.includes(t))) score += 10;
 
// --- Lead source scoring (0-15 points) ---
const source = (contact.hs_analytics_source || '').toLowerCase();
const sourceScores = {
  'organic_search': 15,
  'direct_traffic': 12,
  'referrals': 10,
  'paid_search': 8,
  'social_media': 5,
  'email_marketing': 5,
};
score += sourceScores[source] || 0;
 
return [{
  json: {
    contactId: $('HubSpot Trigger').first().json.objectId,
    score: Math.min(score, 100),
    name: `${contact.firstname || ''} ${contact.lastname || ''}`.trim(),
    title: contact.jobtitle,
    company: contact.company,
    employees,
  }
}];
Adjust weights to your ICP

These weights are a starting point. Replace the industry lists, employee ranges, and point values with your actual ICP criteria. The total should add up to 100 maximum.

Step 4: Write score to HubSpot

Add an HTTP Request node to update the contact's fit score:

  • Method: PATCH
  • URL: https://api.hubapi.com/crm/v3/objects/contacts/{{ $json.contactId }}
  • Body:
{
  "properties": {
    "icp_fit_score": "{{ $json.score }}"
  }
}

Step 5: Add a high-score notification (optional)

For leads scoring above 70, add an IF node followed by a Slack node to notify the team:

  • IF Condition: {{ $json.score }} greater than 70
  • Slack Channel: #high-fit-leads
  • Message:
🎯 *High-Fit Lead Scored*
*{{ $json.name }}* — {{ $json.title }} at {{ $json.company }} ({{ $json.employees }} employees)
Score: *{{ $json.score }}/100*

Step 6: Activate

  1. Click Execute Workflow to test with a real contact
  2. Check the contact's icp_fit_score property in HubSpot
  3. Toggle the workflow to Active

Cost

  • n8n Cloud Starter: $24/mo for 2,500 executions. Each scored contact = 1 execution.
  • Self-hosted: Free. Unlimited executions.

Need help implementing this?

We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.