SaaS Industry / Technical Guide

Automate Trial-to-Paid Lead Scoring for SaaS with n8n + Claude Step-by-Step Guide

A complete walkthrough for building an n8n + Claude pipeline that captures trial signups, enriches them with Clearbit and Apollo, scores ICP fit, fires the hot ones to AEs in Slack, and syncs everything to HubSpot — in 8 seconds end to end.

13 min read
Intermediate-Advanced
n8n + Claude API
Updated May 2026
What You’ll Build

Signup webhook

Enrich (Clearbit + Apollo)

Score ICP (Claude)

Activation tracking

Route — hot / warm / cold

CRM sync (HubSpot)

Slack alert to AE

1. The Problem — Why Trial Lists Rot in the SDR Queue

Every product-led SaaS company hits the same wall once organic signups cross ~500/month: the SDR team can’t realistically discover, enrich, qualify and prioritize each one fast enough. The good leads sit in a queue next to consumer Gmail signups and competitor recon accounts, the AE never gets the right intro at the right moment, and the conversion rate from trial to paid stays flat while the signup graph trends up and to the right.

Real numbers from a Series A SaaS (1,800 trial signups/month)

Trial signups (per month)~1,800
Reached by an SDR within 24h23%
Trial-to-paid conversion (overall)4.1%
SDR time spent on consumer Gmail signups31%
Signups that never get enriched68%

The brutal asymmetry: roughly 8% of trial signups represent 80%+ of pipeline value. The system needs to identify those 8% within minutes, not days, and put a human in front of them before the trial enthusiasm cools. Everyone else still gets a useful experience — just not a manual one.

What “scoring” means here

Lead scoring is not a static spreadsheet of plus and minus points. It’s a three-tier dynamic sort that updates as the trial user takes (or doesn’t take) actions:

  • Hot (score >80): ICP-fit company, decision-maker role, strong product activation. Push to AE in Slack DM, auto-book on Calendly, sequence A.
  • Warm (50–80): Some ICP signal, partial activation. Routes to SDR queue with sequence B.
  • Cold (<50): Weak fit or low intent. Lifecycle drip only — no human touch until they re-engage.
Insight
The biggest lift comes from cutting time-to-first-touch on the hot tier from 11 hours to under 5 minutes. AEs win deals when they reach a decision-maker while the product is still open in another tab. We use this same speed-to-lead pattern across our SaaS automation deployments.

2. System Architecture

Six components, each replaceable. The orchestration layer is self-hosted n8n so security review can audit every external API call that touches prospect data. Postgres holds both the event store and the score history.

The stack

n8n (self-hosted)
Orchestration. Docker on a 2 vCPU / 8GB VM with queue mode for spike handling.
Claude API
Sonnet for ICP scoring and reasoning, Haiku for cheap tier classification.
Clearbit + Apollo
Company and person enrichment. Bright Data fallback for LinkedIn-only profiles.
Postgres
Event store, score history, dedupe table, audit log. Partitioned by month.
HubSpot / Salesforce
Source of truth for contact, company, lifecycle stage, deal.
Slack + Calendly
AE alerting and instant booking for the hot tier. Customer.io for sequences.

Cost estimate (5,000 signups/month)

Claude Sonnet (5k scoring calls, ~1,800 tok in / 350 tok out)~$110
Clearbit Reveal + Person enrichment (5k lookups)~$450
Apollo (filtered to ~1,500 person lookups)~$120
VM (n8n + Postgres on Hetzner CCX23)~$48
Monitoring (Grafana Cloud + Healthchecks)~$24
Total / month~$752

At an ACV of $9k–$30k, a single incremental closed deal from this pipeline pays for the entire stack for a year. The same orchestration layer slots into our broader AI automation services.

1

Trial Signup Capture

The pipeline needs every signup, regardless of which surface it came in through. In a typical SaaS that means three sources: the product itself (your auth provider’s webhook), your billing provider when a card is added (Stripe), and your marketing forms (HubSpot Forms, Default.com, or a custom landing page).

Webhook sources

  • Auth0 / Cognito / Clerk: emits a user.created event with email, signup IP, optional company name from the form.
  • Stripe: customer.created for self-serve trial-with-card flows. Fires roughly 2-5 minutes after auth signup.
  • App POST: for product-qualified events the auth webhook can’t capture (workspace_created, integration_connected). Use a signed HMAC payload.
  • Form fills: demo requests, content downloads, pricing-page submissions. Treat these as first-class signups.

n8n webhook node config

A single n8n Webhook node accepts the union schema; a Switch node downstream branches on source. HMAC verification happens before the workflow does anything else.

n8n Webhook payload — normalized union schemaJSON
{
  "source": "auth0" | "stripe" | "app" | "form",
  "event_id": "evt_01HXYZ...",
  "received_at": "2026-05-03T09:14:22Z",
  "signature": "sha256=...",
  "user": {
    "email": "[email protected]",
    "first_name": "Alex",
    "last_name": "Chen",
    "company_name_provided": "Acme Corp",
    "ip": "203.0.113.42",
    "user_agent": "Mozilla/5.0 ...",
    "utm": {
      "source": "google",
      "campaign": "pql-q2-2026",
      "term": "workflow automation"
    }
  },
  "workspace_id": "ws_92ad3c"
}
Watch Out
Stripe and Auth0 both fire on the same human signup. Use the email as the dedupe key with a 10-minute window in Postgres before kicking off enrichment — otherwise you’ll burn two Clearbit credits per real signup and create two HubSpot contacts.
2

Enrichment Layer

Raw signup data is almost useless for scoring. You need company size, industry, tech stack, role seniority, location and recent funding signals. Run enrichment in parallel with a short timeout (4 seconds) so a slow vendor doesn’t block the whole pipeline. The same enrichment pattern shows up in our work for AI automations for digital marketing agencies.

Enrichment cascade (fail fast, fail cheap)

  1. Domain MX check — if the email domain has no MX record, mark invalid and stop.
  2. Free-email filter — gmail.com, yahoo.com, qq.com etc. flag consumer_email. Don’t enrich (waste of credits) but still score.
  3. Clearbit Reveal on the signup IP — gives company name + domain even if they signed up with a personal email.
  4. Clearbit Person + Company on the work email — title, seniority, company size, industry, funding, tech stack.
  5. Apollo as fallback when Clearbit returns <30% field coverage.
  6. Bright Data LinkedIn scraper as last resort for missing seniority on small companies.

SQL: enrichment cache to avoid double billing

Postgres — enrichment cache lookupSQL
-- Reuse company-level enrichment for any user from the same domain
-- within 30 days. Saves ~40% of Clearbit credits at scale.

WITH cached AS (
  SELECT enrichment_payload
  FROM   enrichment_cache
  WHERE  domain = $1
    AND  enriched_at > now() - interval '30 days'
  ORDER  BY enriched_at DESC
  LIMIT  1
)
SELECT
  CASE
    WHEN EXISTS (SELECT 1 FROM cached)
    THEN (SELECT enrichment_payload FROM cached)
    ELSE NULL
  END AS payload;
Insight
Cache by domain, not by email. Five engineers from the same target account signing up in one week should reuse one enrichment payload — and they often do during a multi-stakeholder evaluation.
3

Claude ICP Classifier

A traditional rules-based scorer has to be hand-tuned every time you launch a new feature, target a new vertical, or learn a new buying signal. Claude reads the enriched profile plus the early product signals, scores against a written ICP, and returns a structured JSON with reasoning — which makes the score auditable.

The 5 scoring dimensions

industry_match
Is this vertical in our top 3? Adjacent? Off-target?
company_size_band
Employees, ARR estimate, seat-economics fit.
tech_stack_signals
Uses tools that integrate with us? Uses a competitor?
role_seniority
IC / Manager / Director / VP / C-level. Champion vs decision-maker.
intent_signals
UTM/campaign, referrer, prior pricing-page visits, integrations clicked.

ICP scoring system prompt

Tested on 6 months of historical signups labeled by closed-won vs churned. Tunable per company by editing the ICP block at the top.

Claude system prompt — ICP scorerTXT
You are an ICP scoring engine for a B2B SaaS workflow automation tool.

ICP definition (highest fit):
- Industry: SaaS, fintech, e-commerce ops, agencies
- Size: 50-2000 employees, >$5M ARR
- Tech stack: uses Slack, HubSpot/Salesforce, AWS or GCP
- Role: ops, RevOps, marketing ops, growth eng (IC level OK
  if they're the documented buyer for tooling)

DISQUALIFY signals:
- Personal Gmail/Yahoo with no company match
- Competitor employee (check enriched company against our
  competitor list in context)
- Student / agency-doing-research signals
- <5 employees (free tier suffices)

OUTPUT — strict JSON, no prose:
{
  "score": 0-100,
  "tier": "hot" | "warm" | "cold" | "disqualify",
  "dimensions": {
    "industry_match": 0-20,
    "company_size_band": 0-20,
    "tech_stack_signals": 0-20,
    "role_seniority": 0-20,
    "intent_signals": 0-20
  },
  "reasoning": "2-3 sentences citing the strongest signals",
  "recommended_action": "ae_dm" | "sdr_queue" | "drip_only" | "discard"
}

Rules:
- score = sum of dimensions
- tier mapping: >=80 hot, 50-79 warm, <50 cold
- if disqualify_reason present, tier = "disqualify" regardless
- never invent enrichment fields not in the input

n8n HTTP Request to Claude

n8n HTTP Request — scoring callJSON
{
  "method": "POST",
  "url": "https://api.anthropic.com/v1/messages",
  "headers": {
    "x-api-key": "{{ $credentials.anthropic.apiKey }}",
    "anthropic-version": "2023-06-01",
    "content-type": "application/json"
  },
  "body": {
    "model": "claude-sonnet-4-5",
    "max_tokens": 600,
    "system": "{{ $json.icpSystemPrompt }}",
    "messages": [
      {
        "role": "user",
        "content": "Enriched signup:n{{ JSON.stringify($json.enriched) }}nnEarly product events (last 1h):n{{ JSON.stringify($json.events) }}"
      }
    ]
  }
}
Insight
Persist the full reasoning string back to HubSpot as a custom field. AEs build trust in the score much faster when they can see “scored 87 because Director of RevOps at a 400-person fintech, already uses Slack + Salesforce, came from the integrations comparison page.”
4

Product Activation Tracking

A trial user who hits first-value, invites a teammate, and connects an integration in the first 48 hours converts at roughly 7x the rate of a passive signup. Capture those events into the same Postgres event store and feed them back into Claude on a 6-hour and 24-hour re-score cadence.

The activation events that move scores

  • first_value_reached — user completed the core “aha” action (varies per product).
  • team_invited — strongest single signal of buying intent. Multi-seat = paid.
  • integration_connected — they brought their data in. Switching cost just went up.
  • pricing_page_visited — late-trial intent. Re-score within 30 minutes.
  • api_token_created — engineering champion is real, evaluation is serious.

Event store schema

Postgres — product_events (partitioned monthly)SQL
CREATE TABLE product_events (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  workspace_id  text NOT NULL,
  user_email    text NOT NULL,
  event_name    text NOT NULL,
  event_value   jsonb,
  occurred_at   timestamptz NOT NULL,
  ingested_at   timestamptz DEFAULT now()
) PARTITION BY RANGE (occurred_at);

CREATE INDEX idx_events_workspace_event
  ON product_events (workspace_id, event_name, occurred_at DESC);

-- Activation feature view used by the re-score job
CREATE MATERIALIZED VIEW activation_features AS
SELECT
  workspace_id,
  user_email,
  bool_or(event_name = 'first_value_reached')    AS hit_first_value,
  bool_or(event_name = 'team_invited')           AS invited_team,
  bool_or(event_name = 'integration_connected')  AS connected_integration,
  count(*) FILTER (WHERE event_name = 'pricing_page_visited') AS pricing_views,
  max(occurred_at)                                AS last_active_at
FROM product_events
WHERE occurred_at > now() - interval '14 days'
GROUP BY workspace_id, user_email;
Security
The event payload (event_value) can leak customer data if you’re not careful — never log file contents, query bodies, or message text. Whitelist the keys you persist; reject everything else at the ingestion node.
5

Routing & Sequences

Once a score lands, routing is deterministic. Hot tier needs a human in front of the prospect inside 5 minutes; warm tier feeds the SDR queue with a personalized opener Claude already drafted; cold tier never touches a human until they re-score upward.

Routing matrix

TierSlackCalendlyEmail sequenceCRM stage
HotDM to AE round-robinAuto-book offered in welcome emailSequence A — AE-signed, high-touchSQL
WarmChannel post in #sdr-queueGeneric link in nurtureSequence B — SDR-signed, mid-touchMQL
ColdNoneNoneLifecycle drip in Customer.ioLead
DisqualifyNoneNoneProduct onboarding onlyLead (do_not_contact=true)

Slack alert payload (hot tier)

Slack — incoming webhook (Block Kit)JSON
{
  "channel": "#hot-trials",
  "blocks": [
    {
      "type": "header",
      "text": { "type": "plain_text",
                "text": ":fire: Hot trial — score 87" }
    },
    {
      "type": "section",
      "fields": [
        { "type": "mrkdwn",
          "text": "*Alex Chen*nDirector RevOps, Acme Corp" },
        { "type": "mrkdwn",
          "text": "*Stack*nSlack, Salesforce, Snowflake" }
      ]
    },
    {
      "type": "section",
      "text": { "type": "mrkdwn",
                "text": "*Why hot:* came from /integrations/salesforce, invited 2 teammates, connected Slack within 11 min of signup." }
    },
    {
      "type": "actions",
      "elements": [
        { "type": "button", "text": { "type": "plain_text",
          "text": "Claim" }, "style": "primary", "action_id": "claim_lead" },
        { "type": "button", "text": { "type": "plain_text",
          "text": "Open in HubSpot" }, "url": "https://app.hubspot.com/contacts/.../{{contactId}}" }
      ]
    }
  ]
}

The Claim button hits a webhook back into n8n that locks the lead to that AE for 24 hours and drops them out of the SDR round-robin. This is the pattern we re-use for our consulting industry automations where partners need first-touch on enterprise leads.

6

CRM Sync & Dedupe

HubSpot or Salesforce remains the source of truth for everything sales sees. The n8n workflow upserts the contact, attaches it to a company record (matching on domain), updates lifecycle stage, and pushes the score plus reasoning into custom fields. Dedupe runs on email + domain to handle the multi-stakeholder evaluation case cleanly.

HubSpot upsert (GraphQL via the v3 API)

HubSpot — contact upsert payloadJSON
{
  "method": "PATCH",
  "url": "https://api.hubapi.com/crm/v3/objects/contacts/[email protected]?idProperty=email",
  "headers": {
    "authorization": "Bearer {{ $credentials.hubspot.token }}",
    "content-type": "application/json"
  },
  "body": {
    "properties": {
      "firstname": "Alex",
      "lastname":  "Chen",
      "jobtitle":  "Director, RevOps",
      "lifecyclestage": "salesqualifiedlead",
      "skru_icp_score":      "87",
      "skru_icp_tier":       "hot",
      "skru_icp_reasoning":  "{{ $json.score.reasoning }}",
      "skru_signup_source":  "auth0",
      "skru_first_event":    "team_invited"
    }
  }
}

Dedupe SQL

Postgres — contact dedupeSQL
-- Idempotent contact write keyed on lower(email).
-- Aggregates same-domain stakeholders into one company score.

INSERT INTO contacts (email, domain, first_seen_at, latest_score, latest_tier)
VALUES ($1, $2, now(), $3, $4)
ON CONFLICT (email) DO UPDATE
  SET latest_score = EXCLUDED.latest_score,
      latest_tier  = EXCLUDED.latest_tier,
      updated_at   = now();

-- Promote the company tier to the highest stakeholder tier in the last 30d
UPDATE companies c
SET    rolled_up_tier = sub.max_tier
FROM (
  SELECT domain,
         CASE WHEN max(score_rank) = 4 THEN 'hot'
              WHEN max(score_rank) = 3 THEN 'warm'
              ELSE 'cold' END AS max_tier
  FROM (
    SELECT domain,
           CASE latest_tier WHEN 'hot' THEN 4
                            WHEN 'warm' THEN 3
                            WHEN 'cold' THEN 2
                            ELSE 1 END AS score_rank
    FROM contacts
    WHERE updated_at > now() - interval '30 days'
  ) ranked
  GROUP BY domain
) sub
WHERE c.domain = sub.domain;
Insight
Roll the company tier up to the highest stakeholder. If three engineers signed up cold but the VP of Eng signed up hot two weeks later, the whole account becomes hot — and the AE inherits the prior context for free.

Common Failures & Fixes

Three failure modes show up in nearly every deployment. Plan for them on day one — they are cheap to design around and expensive to retrofit.

Failure 1: Score inflation on free-email ICPs

Symptom: A consultant with a Gmail address claims VP-level role on the form, gets enriched against the wrong company (their last employer’s domain on LinkedIn) and lands as hot.

Fix: Cap any consumer-email signup at score 60 in the prompt rules and require a manual SDR confirm before promoting to hot. Document the rule in the system prompt so the reasoning string explains why.

Failure 2: Competitor signups get enriched and routed

Symptom: A PM at a direct competitor signs up, gets routed to an AE who books a discovery call before realizing.

Fix: Maintain a Postgres table competitor_domains and inject it into the Claude prompt context. Auto-classify as disqualify with a separate notification to product marketing instead of sales.

Failure 3: Rate-limit cascades during signup spikes

Symptom: Product Hunt launch sends 3,000 signups in 90 minutes. Clearbit rate-limits, n8n queue backs up, hot leads land in Slack 4 hours late.

Fix: Run n8n in queue mode with at least 4 worker processes. Wrap external calls in retry-with-jitter (3 attempts, 250ms-2s). Pre-warm the enrichment cache from your last 30 days of signup domains before any planned campaign.

Privacy: GDPR, CCPA, CASL & SOC 2

B2B prospect data still falls under GDPR (EU), CCPA (California), and CASL (Canada). PCI is not relevant because no payment data flows through the scoring pipeline — Stripe handles that on its own surface. Treat compliance as a design constraint, not a checklist at the end.

What Claude sees (and doesn’t)

  • Sees: business email, name, job title, employer, public LinkedIn-style firmographics, product event names + counts, UTM source.
  • Doesn’t see: message text inside the product, file contents, payment data, IP address (only the country derived from it), session tokens.

GDPR specifics

Lawful basis for B2B prospecting in the EU is legitimate interest, but it requires a balancing test on file and instant honor of objection requests. Implement DSR endpoints (access, erasure, portability) that purge the contact across Postgres, the enrichment cache, and HubSpot in one transaction. CASL in Canada is stricter — you need express consent before sending the warm/cold sequences to Canadian addresses; flag and gate by enriched country.

SOC 2 Type 2 controls this satisfies

  • Audit trail: every score, prompt hash, and CRM write is logged in the audit table with reviewer (if any), timestamp, and source IP.
  • Change management: n8n workflows live in git with a CI deploy, no point-and-click prod edits.
  • Access controls: role-based n8n credentials, vault-backed secrets, no shared API keys per human.
Security
Use Anthropic’s enterprise tier with zero-data-retention enabled. Personal Gmail signups should be flagged and not enriched against any third-party data broker by default — this is the easiest way to drift into a privacy complaint. Honor unsubscribe in the same transaction that logs it; queued sequences must be cancelled, not just stopped at the next send.

Measured Results — 90 Days In

Numbers from a real implementation at a Series A vertical SaaS (1,800 signups/month, 3-person SDR team, 4 AEs) after the first full quarter on the new pipeline. No change in trial volume during the test period — the lift comes entirely from prioritization and speed.

Pipeline
+42%
same trial volume
SDR throughput
3x
qualified convos / SDR / week
Incremental ARR
$310K
90-day pilot
Score-to-route latency
8 sec
avg, signup to Slack

The headline metric inside the SDR team is precision on the hot tier: 91% of leads scored hot became opportunities. That’s the number that lets sales leadership trust the score enough to actually change behavior. Without it, AEs revert to working their old lists by gut.

Implementation Timeline & Cost

DIY Path
60 – 90 hours
  • n8n self-host + queue mode setup: 6–10 hrs
  • Webhook capture + HMAC verify: 4–6 hrs
  • Enrichment cascade + caching: 10–14 hrs
  • Claude scoring prompt + backtest on 6 mo of trials: 14–20 hrs
  • Activation event store + Postgres schema: 8–12 hrs
  • Slack/Calendly/HubSpot integration: 10–14 hrs
  • Sequences in Customer.io + handoff: 6–10 hrs
  • Documentation + SDR/AE training: 4–6 hrs
With SEOKRU
4-week deployment
  • Week 1: Define ICP + score against last 6 months of trials
  • Week 2: Wire Clearbit/Apollo + Claude scoring prompt
  • Week 3: HubSpot/Slack/Calendly integration + sequences
  • Week 4: Soft launch + SDR feedback loop + tuning
  • Includes: prompt tuning, GDPR/SOC 2 review, monthly precision report
Get a Custom Implementation →

FAQ

We're early-stage — do we have enough data to train scoring?
You don’t need training data, you need an ICP definition. Claude scores against the written ICP block, not against a model trained on your history. With as few as 50–100 historical signups labeled “good fit / bad fit” you can backtest the prompt and iterate to ~90% agreement with the human label. The same pattern is documented in the broader AI automation services page — it’s how we bootstrap scoring for clients with no prior CRM data at all.
Does this replace our SDR team?
No. It changes what they do all day. SDRs stop sorting through Gmail signups and competitor logins, and start running discovery on warm-tier accounts the system has already pre-researched and pre-drafted an opener for. In every deployment we’ve run, SDR headcount stays flat or grows; what changes is the per-rep ARR contribution.
Can it score product-qualified leads (PQL) too, not just signups?
Yes. PQL scoring is just the same pipeline triggered by a different event — typically first_value_reached or a feature-usage threshold instead of user.created. The Claude prompt gets richer activation data and usually scores PQLs more confidently than fresh signups. Most teams run both: signup-time MQL scoring for SDR routing, plus a separate 24/72-hour PQL re-score for AE alerts.
What about Salesforce instead of HubSpot?
Same architecture, different sync node. n8n has first-class Salesforce nodes (REST and Bulk 2.0). The score and reasoning go into custom fields on Lead or Contact; tier maps to Lead Status or Lifecycle Stage. The only Salesforce-specific gotcha is the assignment rules engine — disable it for AI-routed leads or you’ll fight your own routing logic. Our wider work for verticals like financial services automation almost always lives on Salesforce for compliance reasons.
How do you avoid emailing competitors who sign up?
Two layers. First, a maintained competitor_domains table is injected into the Claude scoring prompt context, with instruction to classify those signups as disqualify. Second, the routing layer never sends sales sequences to disqualified contacts; they get the standard product onboarding only and a notification fires to product marketing for competitive-intel logging.
How does this compare to MadKudu, Pocus, or HubSpot Predictive Lead Scoring?
Off-the-shelf scoring tools are faster to start and lock you into one vendor’s model and one routing surface. The n8n + Claude approach gives you an auditable score with reasoning, prompt-level control over ICP changes, and the ability to plug any data source (your event store, your competitor list, niche enrichment vendors) without waiting for a vendor roadmap. For a single-vertical SaaS with mature SalesOps, custom usually beats the box product by month three. For a multi-product company with eight ICPs, the flexibility gap widens.

Want this built for your trial funnel?

SEOKRU deploys this exact system in 4 weeks. We backtest the scoring against your last 6 months of trials, wire enrichment and CRM, train your SDRs and AEs on the new flow, and run the precision report monthly. You keep ownership of every component — workflows, prompts, Postgres, the lot.

Talk to a SaaS automation engineer