The Problem With Manual Lead Triage
A SaaS founder was spending two hours every morning reviewing intake form submissions. Some leads were enterprise deals worth chasing hard. Others were students on free plans. The form data was all there โ company size, budget range, use case โ but someone had to read it, make a judgement, and route it to the right person.
The information for a decision already existed. The decision itself didn't need a human.
The Scoring Model
Before touching n8n, we spent an hour with the founder defining what a "good" lead looked like. We landed on five signals, each worth a different number of points:
| Signal | Criteria | Points |
|---|---|---|
| Company size | 50+ employees | +30 |
| Budget stated | $1k+/month | +25 |
| Use case fit | Core product use case | +20 |
| Timeline | Ready within 30 days | +15 |
| Decision maker | Self-identified as buyer | +10 |
Score โฅ 70 = Hot lead. Score 40โ69 = Warm. Below 40 = Nurture sequence. Simple, defensible, and the founder could tweak the weights in a Sheets config tab without touching the workflow.
The Workflow
โ n8n (JS node): Parse fields, run scoring formula against config
โ Switch node: Route by score โ Hot / Warm / Nurture
โ Hot path: Slack DM to founder + HubSpot contact (Hot tag)
โ Warm path: Add to HubSpot sequence + Slack #warm-leads channel
โ Nurture path: Add to email drip campaign + tag in HubSpot
โ All paths: Log to Google Sheets with score + timestamp
Plugging In the Webhook
Typeform has a native webhook option under Integrations. Tally does too, though the payload structure is slightly different โ you'll need to map field IDs to readable names in the first n8n node. We used a Set node to normalise the shape before the scoring logic so the formula works identically regardless of which form tool fires it.
The scoring JavaScript is about 25 lines. It reads weights from a Google Sheets "config" tab so the founder can adjust them without opening n8n. This was the single decision that saved the most back-and-forth later.
The CRM Step
We used HubSpot's n8n node to create or update a contact, set the lead score as a custom property, and apply a tag. If the contact already existed (returning lead), the workflow updated rather than duplicated. The deduplication check is two lines โ check by email, branch on exists/new. This is the step most people skip and regret.
What We Built in a Weekend
- Saturday morning: scoring model defined, Typeform webhook tested, n8n skeleton built
- Saturday afternoon: HubSpot integration, Slack notifications, Google Sheets logging
- Sunday: edge cases (missing fields, duplicate leads, malformed budgets), error handling
- Sunday evening: live on production, founder watching Slack DMs roll in
The Result
- Lead triage time: 2 hours/day โ zero
- Hot leads reach founder within 60 seconds of form submission
- Warm and nurture leads automatically enrolled in the right sequences
- Scoring weights adjustable via Sheets โ no developer needed
- ~44 hours/month returned to the founder
Can You Replicate This?
Yes. The hardest part isn't the code โ it's the scoring model. Spend an hour with whoever handles your sales and nail down what signals actually predict a closed deal. Once you have that, the n8n build is straightforward. Typeform or Tally both work well as the trigger; HubSpot, Pipedrive, and Attio all have solid n8n nodes.
If you'd rather skip the weekend and have it live on Monday, we can build it for you. Lead qualification bots are one of our most requested projects.