Ein n8n-Flow, der Website-Besucher auf Personenebene von Warmly und RB2B über deren ausgehende Webhooks abfängt, jede identifizierte Person gegen ein konfigurierbares ICP-Rubric bewertet, alle aussortiert, die nicht passen, innerhalb eines wochenweiten Fensters dedupliziert, Salesforce auf einen bestehenden Kontakt und jede laufende Motion prüft, die man besser nicht stört, den Übriggebliebenen an den Account-Owner oder einen Territory-SDR-Pool routet, Claude bittet, eine warme Erstansprache zu verfassen, die an der konkreten Seite verankert ist, die die Person angesehen hat, und den Kontext — Entwurf inklusive — als Slack-Benachrichtigung plus Salesforce-Lead oder -Task ausliefert. Das Bundle unter apps/web/public/artifacts/visitor-deanon-to-outreach-n8n/ liefert den vollständigen n8n-Export plus eine _README.md, die Import, Umgebungsvariablen, Credential-Setup, das ICP-Rubric und die Verifizierung pro Branch abdeckt.
When to use this
Setzen Sie ihn ein, wenn ein De-Anonymisierungs-Tool Ihren anonymen Traffic bereits zu namentlich benannten Personen auflöst, der Rohfeed aber unbrauchbar ist. RB2B pusht jeden identifizierten US-Besucher ohne ICP-Filter in einen Slack-Channel; innerhalb einer Woche hören die Reps auf, ihn zu lesen, weil die meisten Identifizierungen Jobsuchende, Studierende, Wettbewerber und Personen drei Ebenen neben Ihrem Käufer sind. Warmlys eigener Autopilot kann auf Besuche reagieren, aber er ist eine kostenpflichtige Blackbox auf der 30.000-USD/Jahr-Stufe und verfasst Entwürfe, ohne die offenen Opportunities in Ihrem CRM zu sehen. Das Symptom ist in beiden Fällen dasselbe: Identifizierte Besucher, die exakt zu Ihrem ICP passen, werden genauso behandelt wie das Rauschen, sodass niemand bei denen schnell handelt, auf die es ankommt.
Dieser Flow sitzt zwischen dem De-Anon-Tool und dem Rep. Er wendet Ihr ICP-Rubric an — Titelfunktion, Seniorität, Unternehmensgrößen-Band, Länder-Allowlist und Seitenintention — in einem einzigen Code-Node, das das Ops-Team lesen und ändern kann, sodass nur die Besucher einen Rep erreichen, die eine warme Ansprache wert sind. Weil De-Anon Ihnen eine Person und die Seite, die sie angesehen hat liefert, kann der Claude-Entwurf auf “Sie haben sich die Pricing-Seite angesehen” verweisen statt auf generischen Branchen-Schmerz. Genau diese Spezifität ist der ganze Sinn, auf einen Website-Besuch zu reagieren statt auf eine kalte Liste.
Es ist auch das richtige Muster, wenn Sie beide — Warmly und RB2B — betreiben oder vorhaben, das eine gegen das andere zu tauschen. Das Normalize Visitor Payload-Node verarbeitet beide Webhook-Formen sowie einen generischen Fallback, sodass es die nachgelagerte Routing-, Filter- und Draft-Logik nicht kümmert, welcher Anbieter ausgelöst hat.
When NOT to use this
Lassen Sie es, wenn Ihr De-Anon-Tool nicht so konfiguriert ist, dass es ausgehende Webhooks sendet. Sowohl Warmly (Settings → Webhooks) als auch RB2B (Integrations → Webhook / Zapier) unterstützen Echtzeit-Webhooks auf Personenebene, aber wenn Sie sie nicht aktiviert haben, gibt es nichts aufzunehmen, und die Polling-Fallbacks, die für Intent-Daten auf Account-Ebene funktionieren, existieren für Reveals auf Personenebene nicht.
Lassen Sie es, wenn Ihr Identifizierungsvolumen niedrig ist und Ihre ICP-Trefferquote bereits hoch. RB2Bs Standard-Stufe löst rund 250 identifizierte Besucher/Monat auf; wenn die meisten davon ohnehin im ICP liegen, weil Ihr Traffic eng zugeschnitten ist, fügen ein ICP-Filter und eine CRM-Suppression-Schicht Infrastruktur hinzu, die Sie nicht brauchen — der Slack-Push, den RB2B mitliefert, reicht aus.
Verwenden Sie es nicht, um identifizierte Besucher automatisch in eine kalte Sequenz einzuschreiben. Es wäre trivial, den Entwurf direkt in Instantly oder Smartlead zu verdrahten, und genau das ist der aggressive Zug, der Sending-Domains flaggen lässt. Ein Website-Besuch ist Einwilligung in nichts. Das Draft-not-send-Design hält einen Menschen zwischen dem Reveal und dem Versand, was bei De-Anon auf Personenebene mehr zählt als bei Intent auf Account-Ebene, weil der Match eine probabilistische Identität ist, kein Formular-Eintrag — RB2Bs eigene Genauigkeit liegt bei etwa 50–70 % auf US-ICP-Traffic, und Warmlys Auflösung auf Account-Ebene landet bei rund 15–25 % der Besucher.
Schließlich ist dies keine Compliance-Kontrolle. Es kann Outreach im ICP-Gate auf eine Länder-Allowlist beschränken, aber das Snippet in Warmly/RB2B auf US-Traffic zu begrenzen, identifizierte Personen durch Ihre Suppression-Liste laufen zu lassen und die Handhabung von CA/VA/CO/CT mit einem Rechtsbeistand zu prüfen — all das geschieht außerhalb von n8n.
Setup
Importieren Sie das Bundle. Ziehen Sie apps/web/public/artifacts/visitor-deanon-to-outreach-n8n/visitor-deanon-to-outreach-n8n.json über Workflows → Import from File in n8n. Ein Einstiegspunkt: ein Webhook unter /webhook/visitor-deanon, an den sowohl Warmly als auch RB2B posten.
Setzen Sie die Umgebungsvariablen. Der Flow verwendet Umgebungsvariablen für die ICP-Schwellenwerte (ICP_MIN_EMPLOYEES, ICP_MAX_EMPLOYEES, ICP_COUNTRY_ALLOWLIST, ICP_TITLE_ALLOWLIST, ICP_TITLE_DENYLIST), die Salesforce-Instanz und das -Token sowie die drei SDR-Pool-E-Mails und Slack-Handles. Die vollständige Liste und wo Sie jeden Wert finden, steht in _README.md. Jede Variable hat einen In-Code-Fallback, sodass der Flow bei einer fehlenden Variable nie wirft — aber die Defaults sind bewusst generisch, setzen Sie sie also vor dem Livegang.
Verdrahten Sie die Credentials. Drei Credentials sind erforderlich:
PLACEHOLDER_ANTHROPIC_CRED_ID — HTTP Header Auth mit x-api-key, gesetzt auf Ihren Anthropic-Key
PLACEHOLDER_SLACK_CRED_ID — HTTP Header Auth mit Authorization: Bearer xoxb-…
PLACEHOLDER_SALESFORCE_CRED_ID — HTTP Header Auth mit Authorization: Bearer <sfdc_token> (oder ein Connected-App-OAuth-Credential für die Produktion)
Richten Sie die Webhooks auf n8n aus. Fügen Sie in Warmly Ihre URL https://<your-n8n-host>/webhook/visitor-deanon unter Settings → Webhooks hinzu. Verwenden Sie in RB2B die Webhook-Integration (oder einen Zapier-”Catch Hook”, der an dieselbe URL weiterleitet). Für keinen der Anbieter wird ein Credential in n8n gespeichert — sie pushen zu Ihnen.
Stimmen Sie das ICP-Rubric ab. Öffnen Sie ICP Fit Gate und lesen Sie den Scoring-Block. Er vergibt Punkte für Titelfunktion, Seniorität, Unternehmensgrößen-Band, Land und Seitenintention und lässt jeden bei oder über ICP_FIT_THRESHOLD (Default 3) passieren. Passen Sie die Punkte-Gewichte und den Schwellenwert an Ihre Definition von Fit an, bevor Sie aktivieren.
Verifizieren Sie jeden Pfad. Gehen Sie die Verifizierung in _README.md durch: Posten Sie einen klar im-ICP liegenden Payload (sollte passieren und einen Entwurf erzeugen), einen klar außerhalb-des-ICP liegenden Payload (sollte am Gate abfallen) und denselben im-ICP-Payload zweimal (der zweite sollte beim Dedup abfallen). Führen Sie den Dedup-Test gegen den Live-Webhook aus, nicht über den Execute-Workflow-Button — statische Daten persistieren nur bei Produktionsläufen.
What the flow does
Webhook — Visitor Deanon Ingest nimmt POST-Requests an und gibt über Respond 202 Accepted sofort 202 zurück, damit der Webhook-Caller des Anbieters nicht am LLM-Call blockiert. Normalize Visitor Payload ist ein Code-Node, das die Quelle anhand der Payload-Form erkennt — RB2B (identifiziert an seinen Business Email / Captured URL-Feldern), Warmly (identifiziert an seiner Kontakt-plus-Company-Verschachtelung) und einen generischen Fallback — und jede auf einen internen Datensatz mit konsistenten Feldern mappt: firstName, lastName, title, company, domain, email, linkedinUrl, employeeCount, industry, country, pageViewed und referrer. Das Feld pageViewed kommt aus RB2Bs Captured URL und Warmlys Signal-Referrer — es ist das, was den Entwurf warm statt kalt macht.
ICP Fit Gate ist das Node, das diesen Flow von einem simplen Intent-Router unterscheidet. Es bewertet die Person gegen ein Rubric: Titelfunktion gegen eine Allowlist (revops, sales, marketing, growth, founder, product) und eine Denylist (student, intern, seeking, agency recruiter); Seniorität (C-Level, VP, Head, Director scoren höher); Unternehmensgrößen-Band zwischen ICP_MIN_EMPLOYEES und ICP_MAX_EMPLOYEES; Land gegen ICP_COUNTRY_ALLOWLIST; und Seitenintention (ein /pricing-, /demo- oder /product-Aufruf fügt Punkte hinzu). Liegt die Summe unter ICP_FIT_THRESHOLD, gibt das Node ein leeres Array zurück und die Ausführung stoppt still — die Person erreicht nie einen Rep. Der fitScore und die Gründe werden an den Datensatz angehängt, sodass die Slack-Karte eines passierenden Besuchers zeigt, warum er qualifiziert war, und ein fehlkonfiguriertes Rubric auditierbar ist.
Dedup Gate (Static Data) nutzt n8ns Workflow-Static-Data — $getWorkflowStaticData('global') — um einen Schlüssel pro Person pro Woche zu halten (dedup_<email-or-linkedin>_<ISO-week>). Wochenebene ist das richtige Fenster für warmes Outreach: Jemand, der Ihre Site dreimal in fünf Tagen besucht, sollte eine Rep-Ansprache erzeugen, nicht drei. Dieses Objekt ist die einzige korrekte Art, ausführungsübergreifenden State aus einem Code-Node zu persistieren — n8ns öffentliche REST-API hat keine Static-Data-Ressource — und das Node stempelt den Schlüssel vor jedem nachgelagerten Call, sodass zwei gleichzeitige Reveals für dieselbe Person nicht beide passieren können, und beschneidet Schlüssel aus früheren Wochen, damit der Store klein bleibt.
Salesforce — Contact Lookup fragt nach einem Contact ab, der zur E-Mail der Person passt, und gibt die Contact-Id, Account-Id, den Owner (Id, Name, Email, Slack_Handle__c) und zwei Suppression-Signale zurück: ob der Account eine offene Opportunity hat und ob der Kontakt bereits in einer aktiven Sequenz ist (über ein Current_Sequence__c-Feld). Routing & Suppression Logic entscheidet dann. Existiert der Kontakt und ist ein beliebiges Suppression-Signal gesetzt — offene Opportunity, aktive Sequenz oder ein Bestandskunden-Account-Typ — gibt das Node ein leeres Array zurück: Eine warme De-Anon-Ansprache würde eine laufende Motion stören, also wird sie verworfen und geloggt. Andernfalls, wenn der Kontakt existiert, routet der Spike an den Account-Owner und der Flow erstellt einen Task auf dem bestehenden Kontakt. Existiert kein Kontakt — der häufige De-Anon-Fall, da der ganze Sinn ja ist, Personen sichtbar zu machen, die noch nicht in Ihrem CRM sind — routet er an einen Territory-SDR-Pool (AMER/EMEA/ROW nach Land) und der Flow erstellt einen Lead. Das Node setzt createSObject entsprechend auf Task oder Lead.
Claude — Draft Warm First Touch postet an die Anthropic-API mit claude-haiku-4-5, einem 8-Sekunden-Timeout und neverError: true. Der System-Prompt verbietet Füllwörter (“I noticed”, “reach out”, “touch base”, “circle back”) und weist Claude an, den Opener an der konkret angesehenen Seite und der Rolle der Person zu verankern — weil “saw you were on the pricing page” handlungsfähig ist und “I’d love to connect” nicht. Parse Draft (with fallback) behandelt einen Timeout oder fehlerhaftes JSON, indem es einen template-basierten Entwurf erzeugt, getaggt mit draftSource: template-fallback; beide Pfade liefern draftSubject, draftBody und draftTalkingPoint. Slack — Notify Assignee postet eine Block-Kit-Karte an #visitor-deanon mit Name, Titel, Company, LinkedIn-URL der Person, der angesehenen Seite, dem fitScore und den Gründen sowie dem Entwurf mit dem Label “edit before sending”. Salesforce — Create Record POSTet an /sobjects/{{ createSObject }} — einen Lead für neue Personen, andernfalls einen Task, der über WhatId mit dem bestehenden Kontakt verknüpft ist — mit OwnerId, das nur auf eine echte Salesforce-User-Id gesetzt wird (nie auf eine E-Mail, die MALFORMED_ID zurückgibt) und beim Routing an einen Pool weggelassen wird.
Cost reality
Pro identifiziertem Besucher, der das ICP-Gate passiert, empfängt claude-haiku-4-5 rund 500 Input-Tokens und produziert etwa 150 Output-Tokens für den Drei-Felder-Entwurf. Bei Haiku-4.5-Pricing (~0,80 USD/M Input, ~4 USD/M Output) sind das etwa 0,0007 USD pro Entwurf. Das ICP-Gate übernimmt die Kostenbegrenzung: Wenn RB2Bs Pro-Stufe ~1.000 identifizierte Besucher/Monat sichtbar macht und Ihr Rubric 30 % passieren lässt, verfassen Sie ~300 Entwürfe/Monat — unter 0,25 USD/Monat an Claude-Ausgaben. Das Dedup-Fenster bedeutet, dass ein wiederkehrender Besucher einmal pro Woche abgerechnet wird, nicht pro Besuch.
Das De-Anon-Tool ist der eigentliche Posten, nicht die Automatisierung. RB2B liegt bei 159 USD/Monat (~250 identifizierte Besucher) bis 499 USD/Monat (~1.000); Warmlys kostenpflichtige Pläne starten bei 15.000 USD/Jahr und seine volle Autopilot-Suite bei 30.000 USD/Jahr. n8n self-hosted ist kostenlos; n8n Cloud Starter für 20 USD/Monat deckt 5.000 Ausführungen ab und bewältigt bequem ~300 mit Entwürfen versehene Besucher zu je ~9 Nodes. Die Salesforce-API-Nutzung ist eine Query plus ein Create pro passierendem Besucher — ein paar hundert Calls/Monat gegen ein Enterprise-Limit von 15.000+/Tag. Der Slack-Bot und der n8n-Webhook-Endpoint sind kostenlos.
Failure modes
Das ICP-Rubric verwirft still alle. Ein zu strenger Schwellenwert oder eine Titel-Allowlist, die verfehlt, wie Ihre Käufer ihre Titel tatsächlich schreiben (z. B. “RevOps” als Denylist-Teilstring, der versehentlich “Revenue Operations” fängt), bedeutet, dass jeder Besucher am Gate scheitert und der #visitor-deanon-Channel verstummt — was sich wie “kein Traffic” liest, obwohl es eigentlich “Filter fehlkonfiguriert” ist. Absicherung: ICP Fit Gate hängt fitScore und Gründe pro Regel an jeden Datensatz an, und die _README.md-Verifizierung umfasst das Posten eines bekannten im-ICP-Payloads und die Bestätigung, dass er passiert. Beobachten Sie die Pass-Rate in der ersten Woche; liegt sie bei echtem Traffic nahe null, lockern Sie das Rubric.
Dedup-Static-Data persistiert nur bei Produktionsläufen.Dedup Gate (Static Data) liest und schreibt $getWorkflowStaticData('global'), das n8n nur speichert, wenn die Ausführung in der Produktion ausgelöst wird — nie bei einem manuellen Execute-Workflow-Lauf. Dedup zu testen, indem man zweimal auf Execute Workflow klickt, lässt das Gate kaputt aussehen, obwohl es funktioniert. Absicherung: Aktivieren Sie den Workflow und POSTen Sie zweimal an die Live-Webhook-URL; der zweite POST sollte beim Dedup abfallen. Das Node beschneidet Schlüssel der Vorwoche bei jedem Lauf, sodass sich der Store selbst reinigt.
Der Entwurf adressiert die falsche Person. De-Anon auf Personenebene ist probabilistisch — RB2Bs Identifizierung liegt bei ~50–70 % Genauigkeit auf US-ICP-Traffic — sodass ein Entwurf einen Namen grüßen kann, der gar nicht der Besucher war. Absicherung: Der Flow sendet nie. Die Slack-Karte führt mit der LinkedIn-URL, damit der SDR die Identität mit einem Klick verifiziert, bevor er bearbeitet und sendet, und der Entwurf ist sowohl im System-Prompt als auch in der Slack-Nachricht als Ausgangspunkt gekennzeichnet.
Salesforce-Bearer-Token-Rotation legt Lookups lahm. Ein rohes Bearer-Token in SFDC_ACCESS_TOKEN rotiert (alle ~2 Stunden bei Orgs ohne persistente Session-Policy). Wenn es abläuft, gibt Salesforce — Contact Lookup still 401 zurück (wegen neverError: true), sodass jeder Besucher als neu erscheint und als Lead an einen Pool geroutet wird — was die Suppression stillschweigend umgeht. Absicherung: Achten Sie auf eine Serie von Lead-Erstellungen mit null Task-Erstellungen, selbst wenn Sie wissen, dass bestehende Kontakte besuchen; ersetzen Sie für die Produktion das rohe Token durch eine Connected App mit OAuth-2.0-Client-Credentials-Flow. Die _README.md deckt das ab.
vs alternatives
vs Warmly Autopilot. Warmlys eigener Agent kann aus einem Besuch heraus qualifizieren und buchen, und wenn Sie ohnehin für die 30.000-USD/Jahr-Stufe zahlen und Salesforce nicht als Source of Truth für Suppression betreiben, reicht er vielleicht aus. Er ist nicht das richtige Tool, wenn Sie wollen, dass die ICP-Logik und die Suppression-Regeln von Ihrem Ops-Team lesbar und auditierbar sind, wenn Sie RB2B neben oder statt Warmly betreiben oder wenn Sie wollen, dass die Ansprache ein Rep-bearbeiteter Entwurf ist statt eines autonomen Versands. Dieser Flow gibt Ihnen alle drei zu n8n-Kosten und funktioniert über beide Anbieter hinweg.
vs RB2B → Slack → manuelle Triage. RB2Bs nativer Slack-Push ist der Status quo: jede identifizierte Person, kein ICP-Filter, kein CRM-Bewusstsein. Er ist Free-Tier-freundlich und bei niedrigem Volumen in Ordnung, aber bei 1.000 Identifizierungen/Monat wird der Channel zu Rauschen, das Reps ausblenden, und es gibt keine Absicherung dagegen, einen Kontakt anzupingen, der mitten in einem Deal steckt. Dieser Flow filtert zuerst auf ICP und unterdrückt aktive Motions, sodass das, was in Slack landet, lesenswert ist.
vs ein Zapier-Auto-Enroll in Instantly/Smartlead. Der Ein-Klick-Zug ist RB2B/Warmly → Zapier → Cold-Sequencer. Er sendet am schnellsten und ist am riskantesten: kein menschlicher Check bei einer probabilistischen Identität, keine Suppression gegen offene Opportunities, und Cold-Sends an frisch de-anonymisierte Personen sind der schnellste Weg, eine Sending-Domain zu verbrennen. Dieser Flow tauscht diese Geschwindigkeit gegen einen Rep-in-the-Loop-Entwurf und CRM-bewusste Suppression.
vs eine Clay-Tabelle auf einem De-Anon-Feed.Clay kann einen De-Anon-Feed ziehen, ihn anreichern, ein ICP-Rubric mit Formelspalten anwenden und an einen Sequencer pushen — und es ist ein starker Fit für Batch-Prospecting-Läufe. Es ist nicht event-getrieben, sodass es immer einen Batch-Lag zwischen dem Besuch und der Ansprache gibt. Nutzen Sie Clay für die wöchentliche Anreicherungs- und Prospecting-Schicht; nutzen Sie diesen Flow für die Echtzeit-Antwort, solange der Besuch noch warm ist.
# Visitor de-anon to outreach — n8n flow
This bundle contains a complete n8n workflow that turns person-level website de-anonymization signals from **Warmly** and **RB2B** into ICP-filtered, CRM-aware warm outreach. It catches each identified visitor from the vendor's outgoing webhook, scores the person against a configurable ICP rubric (dropping everyone who doesn't fit), deduplicates within a week-level window, checks Salesforce for an existing contact and any active motion, routes the survivor to the account owner or a territory SDR pool, drafts a warm first-touch with Claude anchored to the exact page the person viewed, posts a Slack card to the assignee, and creates a Salesforce Lead (net-new person) or Task (existing contact).
One entry point:
- **Webhook** — `Webhook — Visitor Deanon Ingest` accepts `POST /webhook/visitor-deanon` from Warmly (Settings → Webhooks) and RB2B (Integrations → Webhook / Zapier), or any system that can POST a person-level payload.
## What this flow does
`Normalize Visitor Payload` maps three payload shapes — RB2B (space-cased field names, `Captured URL`), Warmly (nested `contact` / `company` / `signal`), and a generic fallback — into one internal person record. The `pageViewed` field (RB2B `Captured URL` / Warmly signal referrer) is the load-bearing input for the warm draft.
`ICP Fit Gate` is what separates this flow from a plain intent router. It scores each person against a readable rubric — title function (+2), seniority (+1), company-size band (+1), country (+1), high-intent page like `/pricing` or `/demo` (+2) — and hard-drops title-denylist matches (student, intern, agency recruiter, job-seeker) and off-allowlist countries. Anyone below `ICP_FIT_THRESHOLD` (default 3) is dropped and never reaches a rep. The `fitScore` and reasons are attached so a passing visitor's Slack card shows why they qualified, and a misconfigured rubric is auditable from execution history.
`Dedup Gate (Static Data)` uses n8n workflow static data — `$getWorkflowStaticData('global')` — to hold a per-person-per-ISO-week key. Week-level (not day-level) is the right window for warm outreach: someone who visits three times in five days should generate one rep touch. Static data is the only correct way to persist cross-execution state from a Code node — n8n's public REST API has **no** static-data resource — and it only persists for **production** executions (webhook / schedule trigger), not manual runs. The node stamps the key before any external call (race-safe) and prunes prior weeks.
`Salesforce — Contact Lookup` finds an existing contact by exact email and returns the owner plus three suppression signals: open opportunity, active sequence (`Current_Sequence__c`), and customer account type. `Routing & Suppression Logic` suppresses the touch (drops silently) when an existing contact is mid-motion; otherwise it routes an existing clean contact to the account owner (→ Task) or a net-new person to a territory SDR pool (→ Lead).
`Claude — Draft Warm First Touch` generates a three-part draft (subject, body, talking point) anchored to the page viewed. The draft is explicitly a starting point — identity is probabilistic — and the flow never sends. `Slack — Notify Assignee` posts the context and draft to `#visitor-deanon`, leading with the LinkedIn URL for one-click identity verification. `Salesforce — Create Record` writes a Lead or Task.
## Import
1. In n8n, open **Workflows → Import from File** and select `visitor-deanon-to-outreach-n8n.json`.
2. Open the workflow's **Settings** and confirm `Execution Order` is `v1` and `Timezone` matches your business hours (defaults to `America/New_York`). The dedup window rolls over on the ISO-week boundary in UTC; if you need it aligned to a local week, adjust the week derivation in `Dedup Gate (Static Data)`.
3. Set the environment variables in the **Environment variables** section below.
4. Wire the three credentials in the **Credentials** section.
5. Read and tune the **ICP rubric** in `ICP Fit Gate` to your definition of fit.
6. Point the Warmly and RB2B webhooks at your n8n URL (**Webhook setup** below).
7. Activate the workflow only after the **First-run verification** below passes.
## Environment variables
Set these in your n8n instance's environment (n8n Cloud: **Settings → Environment Variables**; self-hosted: your `.env` file or container environment). Every variable has an in-code fallback, so a missing one won't throw — but the ICP defaults are generic, so set them before going live.
| Variable | What it does | Example |
|---|---|---|
| `SFDC_INSTANCE_URL` | Salesforce Setup → Company Information → Salesforce.com Base URL | `https://yourorg.my.salesforce.com` |
| `SFDC_ACCESS_TOKEN` | Salesforce OAuth access token (see note below) | `00D…` |
| `ICP_MIN_EMPLOYEES` | Lower bound of the in-ICP company-size band | `25` |
| `ICP_MAX_EMPLOYEES` | Upper bound of the in-ICP company-size band | `5000` |
| `ICP_FIT_THRESHOLD` | Minimum fit score to pass the gate | `3` |
| `ICP_COUNTRY_ALLOWLIST` | Comma-separated ISO country codes; empty = allow all | `US,CA,GB` |
| `ICP_TITLE_ALLOWLIST` | Comma-separated lowercase title substrings that score +2 | `revops,sales,marketing,growth,founder` |
| `ICP_TITLE_DENYLIST` | Comma-separated lowercase substrings that hard-drop | `student,intern,seeking,recruiter,job` |
| `SDR_POOL_AMER_EMAIL` | SDR pool lead email for AMER territory | `sdr-amer@yourcompany.com` |
| `SDR_POOL_AMER_SLACK` | Slack handle (no @) for AMER SDR pool | `sdr-amer` |
| `SDR_POOL_EMEA_EMAIL` | SDR pool lead email for EMEA territory | `sdr-emea@yourcompany.com` |
| `SDR_POOL_EMEA_SLACK` | Slack handle (no @) for EMEA SDR pool | `sdr-emea` |
| `SDR_POOL_ROW_EMAIL` | SDR pool lead email for ROW territory | `sdr-row@yourcompany.com` |
| `SDR_POOL_ROW_SLACK` | Slack handle (no @) for ROW SDR pool | `sdr-row` |
The `SFDC_ACCESS_TOKEN` rotates. For production, use a Connected App with OAuth 2.0 client-credentials flow and a short-lived token refresh, or the Salesforce OAuth2 credential in n8n instead of the raw Bearer token.
## Credentials
### `PLACEHOLDER_ANTHROPIC_CRED_ID` — Anthropic
Used by `Claude — Draft Warm First Touch`. Generate an API key at `https://console.anthropic.com`. In n8n, add an **HTTP Header Auth** credential with header name `x-api-key` and value set to the key. The node uses `claude-haiku-4-5` to keep latency under ~2 seconds on a typical person payload. Swap to `claude-sonnet-4-6` only if draft quality is consistently off for a segment — roughly 10× the cost.
### `PLACEHOLDER_SLACK_CRED_ID` — Slack
Used by `Slack — Notify Assignee`. Create a Slack app with a bot token (`xoxb-…`) that has `chat:write` scope, and invite the bot to `#visitor-deanon`. In n8n, add an **HTTP Header Auth** credential with header name `Authorization` and value `Bearer xoxb-…`.
### `PLACEHOLDER_SALESFORCE_CRED_ID` — Salesforce
Used by `Salesforce — Contact Lookup` and `Salesforce — Create Record`. For a quick pilot, add an **HTTP Header Auth** credential with header name `Authorization` and value `Bearer <sfdc_token>`. For production, use a Connected App (OAuth 2.0 client credentials) so the token refreshes automatically.
## Salesforce fields used
The flow reads `Current_Sequence__c` on the Contact object as an active-sequence suppression signal, and the standard `Owner.Slack_Handle__c` custom field on User for Slack @-mentions. If your org doesn't have these:
- **`Current_Sequence__c` (Contact, Text)** — set by your sequencer's integration when a contact is enrolled; if you don't populate it, the suppression check simply never fires on that signal (open opportunity and customer type still work). Remove the field from the SOQL in `Salesforce — Contact Lookup` if it doesn't exist, or the query errors.
- **`Slack_Handle__c` (User, Text)** — the owner's Slack handle for @-mentions. If absent, remove it from the SOQL; the flow falls back to no @-mention.
No custom fields are required on Lead or Task — the flow uses only standard fields (`LeadSource`, `Description`, `WhoId`, `WhatId`, etc.).
## Webhook setup
- **Warmly** — **Settings → Webhooks**, add `https://<your-n8n-host>/webhook/visitor-deanon`, save. Configure the orchestrator to fire the webhook on an identified-visitor event.
- **RB2B** — **Integrations → Webhook** (or the **Zapier** integration with a "Catch Hook" → POST to the same URL). RB2B sends person-level fields (LinkedIn URL, First/Last Name, Title, Company Name, Business Email, Website, Industry, Employee Count, Captured URL, Referrer, etc.).
## First-run verification
Run these against the **live** webhook URL (not the Execute Workflow button — static data and production behavior only apply to real webhook executions). Sample payloads are minimal; add fields as needed.
1. **In-ICP passes and drafts.** POST an RB2B-shaped payload for a clearly in-ICP person on a high-intent page:
```bash
curl -X POST https://<your-n8n-host>/webhook/visitor-deanon \
-H 'Content-Type: application/json' \
-d '{"First Name":"Jordan","Last Name":"Lee","Title":"VP Sales","Company Name":"Acme","Website":"acme.com","Business Email":"jordan@acme.com","Employee Count":"400","Industry":"Software","State":"CA","Captured URL":"https://yoursite.com/pricing","LinkedIn URL":"https://linkedin.com/in/jordanlee"}'
```
Expect: a Slack card in `#visitor-deanon` with a fit score ≥ 3 and a draft, and a new Salesforce Lead (no matching contact).
2. **Out-of-ICP drops at the gate.** POST a payload that should fail — a student, or a sub-`ICP_MIN_EMPLOYEES` company:
```bash
curl -X POST https://<your-n8n-host>/webhook/visitor-deanon \
-H 'Content-Type: application/json' \
-d '{"First Name":"Sam","Last Name":"Kim","Title":"Student","Company Name":"University","Website":"uni.edu","Business Email":"sam@uni.edu","Employee Count":"3","State":"NY","Captured URL":"https://yoursite.com/blog/post"}'
```
Expect: no Slack card, no Salesforce record. Check the execution — it should stop at `ICP Fit Gate`.
3. **Dedup drops the repeat.** Re-run the payload from step 1 within the same week.
Expect: no second Slack card. The execution stops at `Dedup Gate (Static Data)`. (This only works against the live webhook — manual runs don't persist static data.)
4. **Existing contact → Task, not Lead.** POST step 1's payload with an email that already exists as a Salesforce Contact whose account has no open opportunity and no active sequence.
Expect: a Task on the existing contact assigned to the account owner (not a Lead), and a Slack card that reads "existing contact → Task."
5. **Suppression holds.** Repeat step 4 with a contact whose account has an open opportunity (or a customer account type).
Expect: no Slack card, no record — the execution stops at `Routing & Suppression Logic`.
## Notes and limits
- **Identity is probabilistic.** RB2B's person-level identification runs roughly 50-70% accurate on US ICP traffic; Warmly resolves ~15-25% of visitors (largely account-level). The Slack card leads with the LinkedIn URL so the SDR verifies before sending. The flow never auto-sends.
- **Compliance is out of scope for this flow.** Restrict the snippet to US traffic in Warmly/RB2B, run identified people through your suppression list, and review CA/VA/CO/CT handling with counsel. The `ICP_COUNTRY_ALLOWLIST` is a routing convenience, not a legal control.
- **Static data self-cleans.** The dedup node prunes prior-week keys on every run, so the store doesn't grow unbounded; no separate maintenance cron is needed.