Leads don’t “go cold.” They get stranded in whatever system nobody wants to own: a form on Webflow, a half-filled CRM record, a Slack thread with no next step, and a rep who opens it two hours later and pretends that was inevitable. It wasn’t. It was your wiring.
This playbook builds a working lead-capture-to-first-touch system using four tools with clear boundaries: Webflow for capture, n8n for routing logic, Supabase for an auditable event ledger, and HubSpot CRM for the human workflow. Each tool does one job. No heroics.
Webflow: Put a short form on your highest-intent pages and stop “qualifying” with eight fields you won’t trust anyway. Add hidden fields for source URL, UTM params, and page timestamp. Those three fields explain 80% of intent later.
n8n: Treat n8n as policy, not plumbing. On submit, n8n enriches lightly (company domain parsing, free email detection), scores using your actual constraints (territory, deal size proxy, product line), then decides: create/update contact in HubSpot, assign owner, and generate the first task with a deadline that’s measured in minutes, not days. If the score is ambiguous, route to a “triage” queue instead of guessing.
Supabase: Log every step as an immutable event: form_received, deduped, routed, owner_assigned, task_created, first_reply_sent. This is how you stop running pipeline reviews on vibes. HubSpot is not a ledger.
HubSpot: Keep it boring. Contacts, companies, deals, tasks. The rep works the task; they don’t interpret routing logic. If the rep changes fields, n8n writes those changes back into Supabase as events, so you can see when humans override the system.
Outcome: you can measure drop-offs by minute, prove where leads stall, and fix routing rules without rewriting your site or retraining the team. The bottleneck becomes visible. Then it becomes negotiable.
Routing and Logging Leads Before They Slip Away
Maya runs growth at a 12-person B2B SaaS. She’s the one who gets pinged when “leads are down,” even when traffic is fine. Last month, a partner webinar drove 47 form fills in 90 minutes. Good problem. Except half of them didn’t get touched until the next morning.
Why? The form posted into Slack. #inbound. No owner. Everyone assumed someone else had it. A rep finally copied emails into HubSpot at 6pm, missed three typos, and created duplicates for two existing customers. Then sales complained “marketing sends junk.”
So she rewired it.
Now a Webflow form submits name, email, company, plus hidden fields: source_url, utm_campaign, page_ts. That’s it. No “budget.” No “timeline.” You can’t trust those anyway.
n8n wakes up on submit. It parses the domain. Flags gmail/yahoo as “free.” Looks at country from the top-level domain and a crude deal-size proxy from employee count (Clearbit, or a cheaper fallback). Then it chooses: AE-owned task due in 10 minutes, SDR triage queue, or “nurture” list with no task.
Here’s the friction: the first version of the n8n workflow tried to dedupe in HubSpot by “email contains.” It matched “alex@acme.co” to “alex@acme.com” and merged two different people. Quietly. Nobody noticed until a renewal call went sideways. Now dedupe is strict on normalized email, with a separate “possible_duplicate” event if domain + name matches but email doesn’t.
Supabase gets an event for every step. form_received. enriched. routed. owner_assigned. task_created. Then, the ugly one: task_overdue. It happens. Reps go into meetings. Calendars don’t care about your SLA.
Maya opens a simple timeline view. She can see that 18% of leads stall at “triage” for more than 30 minutes when the SDR is out. So she adds a rule: if triage idle > 15 minutes, reassign to the on-call AE.
Will it always pick the right owner? With territory edges and fuzzy domains, who decides what “right” even means?
Lead Ownership Contracts That Make Automation Work
If you’re reading this and thinking “cool, we’ll just copy the workflow,” the real work hasn’t shown up yet. The workflow isn’t the hard part. Ownership is.
Inside a real company, you’ll discover that routing rules aren’t neutral—they’re political. The moment n8n assigns an AE in 10 minutes, you’ve created a de facto SLA. Sales leadership loves that until it starts generating “why did I get this lead?” pings. Marketing loves the ledger until it proves the lead wasn’t junk; it was ignored. The system forces a fight your org has been postponing.
So implement it like you’d implement comp: with explicit contracts. We usually start by writing three things on one page: what counts as a lead (and what doesn’t), who owns each class of lead, and what “touched” actually means. Not “email sent” if nobody reads it. Not “task created” if it sits there. Define “first-touch” as a logged outbound attempt plus a next step, and you’ll stop gaming.
Then, build the exception paths first. Triage is not a queue, it’s a role. If you don’t assign a named person per shift, “triage” becomes your new Slack channel. Same with “nurture”: if nobody owns it, it’s a polite graveyard. Put an on-call rotation on the calendar, and let n8n pull the on-call rep from a table, not a hardcoded user ID that breaks the moment someone quits.
A practical detail people skip: you need a correction loop. Create a lightweight “wrong owner” button (HubSpot property + workflow) that re-routes and logs why. After two weeks you’ll have the real data: territory edge cases, partner leads that look like inbound, students using company domains, customers filling demo forms. That’s the stuff that makes routing feel “smart” without pretending you can predict intent perfectly.
If you can’t stomach those conversations, the wiring won’t save you. It’ll just make the mess auditable.