Um fluxo do n8n que captura visitantes do site identificados no nível da pessoa via Warmly e RB2B por meio dos webhooks de saída deles, pontua cada pessoa identificada contra uma rubrica de ICP configurável, descarta todo mundo que não se encaixa, deduplica dentro de uma janela de nível semanal, verifica no Salesforce se há um contato existente e qualquer motion ativo que valha a pena não atropelar, roteia o sobrevivente para o dono da conta ou para um pool de SDR por território, pede para o Claude redigir um primeiro contato warm ancorado na página específica que a pessoa visualizou, e entrega o contexto — rascunho incluído — como uma notificação do Slack mais um Lead ou Task do Salesforce. O bundle em apps/web/public/artifacts/visitor-deanon-to-outreach-n8n/ traz o export completo do n8n mais um _README.md cobrindo import, variáveis de ambiente, configuração de credenciais, a rubrica de ICP e a verificação por branch.
Quando usar isto
Use quando uma ferramenta de deanonimização já estiver resolvendo seu tráfego anônimo em pessoas nomeadas, mas o feed bruto for inviável de trabalhar. O RB2B empurra todo visitante identificado dos EUA para um canal do Slack sem nenhum filtro de ICP; em uma semana os reps param de ler porque a maioria das identificações são candidatos a emprego, estudantes, concorrentes e pessoas três níveis distantes do seu comprador. O próprio Autopilot da Warmly pode agir sobre as visitas, mas é uma caixa-preta paga no tier de US$30,000/ano e redige sem enxergar as oportunidades abertas do seu CRM. O sintoma nos dois casos é o mesmo: visitantes identificados que batem exatamente com o seu ICP recebem o mesmo tratamento que o ruído, então ninguém age rápido nos que importam.
Este fluxo fica entre a ferramenta de deanon e o rep. Ele aplica sua rubrica de ICP — função do cargo, senioridade, faixa de tamanho da empresa, allowlist de país e intenção da página — em um único node Code que o time de ops consegue ler e alterar, de modo que os únicos visitantes que chegam a um rep são os que valem um toque warm. Como a deanon te dá uma pessoa e a página que ela visualizou, o rascunho do Claude pode referenciar “você estava olhando a página de pricing” em vez de dor genérica do setor. Essa especificidade é o objetivo inteiro de agir sobre uma visita ao site em vez de uma lista fria.
É também o padrão certo quando você roda tanto Warmly quanto RB2B, ou planeja trocar um pelo outro. O node Normalize Visitor Payload lida com os dois formatos de webhook e um fallback genérico, então a lógica de roteamento, filtragem e redação lá na frente não se importa com qual fornecedor disparou.
Quando NÃO usar isto
Pule se a sua ferramenta de deanon não estiver configurada para enviar webhooks de saída. Tanto a Warmly (Settings → Webhooks) quanto o RB2B (Integrations → Webhook / Zapier) suportam webhooks em tempo real no nível da pessoa, mas se você não os habilitou não há nada para ingerir, e os fallbacks de polling que funcionam para dados de intenção no nível da conta não existem para reveals no nível da pessoa.
Pule se o seu volume de identificação for baixo e a sua taxa de acerto de ICP já for alta. O tier Standard do RB2B resolve por volta de 250 visitantes identificados/mês; se a maioria deles já está dentro do ICP porque o seu tráfego é bem segmentado, um filtro de ICP e uma camada de supressão via CRM adicionam infraestrutura que você não precisa — o push do Slack que o RB2B já entrega é suficiente.
Não use isto para auto-inscrever visitantes identificados em uma sequência fria. Seria trivial ligar o rascunho direto no Instantly ou Smartlead, e essa é exatamente a jogada agressiva que faz domínios de envio serem flagados. Uma visita ao site não é consentimento para nada. O design de redigir-sem-enviar mantém um humano entre o reveal e o envio, o que importa mais para deanon no nível da pessoa do que para intenção no nível da conta, porque o match é uma identidade probabilística, não um preenchimento de formulário — a própria acurácia do RB2B roda por volta de 50-70% em tráfego de ICP dos EUA, e a resolução no nível da conta da Warmly fica em torno de 15-25% dos visitantes.
Por fim, isto não é um controle de compliance. Ele pode restringir o outreach a uma allowlist de país no gate de ICP, mas restringir o snippet a tráfego dos EUA na Warmly/RB2B, rodar as pessoas identificadas pela sua lista de supressão, e revisar o tratamento de CA/VA/CO/CT com o jurídico acontecem todos fora do n8n.
Setup
Importe o bundle. Solte apps/web/public/artifacts/visitor-deanon-to-outreach-n8n/visitor-deanon-to-outreach-n8n.json no n8n via Workflows → Import from File. Um ponto de entrada: um webhook em /webhook/visitor-deanon para onde tanto a Warmly quanto o RB2B fazem post.
Defina as variáveis de ambiente. O fluxo usa variáveis de ambiente para os thresholds de ICP (ICP_MIN_EMPLOYEES, ICP_MAX_EMPLOYEES, ICP_COUNTRY_ALLOWLIST, ICP_TITLE_ALLOWLIST, ICP_TITLE_DENYLIST), a instância e o token do Salesforce, e os três emails de pool de SDR e handles do Slack. A lista completa e onde encontrar cada valor está no _README.md. Toda variável tem um fallback no código para que o fluxo nunca dê erro por uma faltante — mas os defaults são deliberadamente genéricos, então defina-os antes de ir para produção.
Ligue as credenciais. Três credenciais são necessárias:
PLACEHOLDER_ANTHROPIC_CRED_ID — HTTP Header Auth com x-api-key definido para a sua chave da Anthropic
PLACEHOLDER_SLACK_CRED_ID — HTTP Header Auth com Authorization: Bearer xoxb-…
PLACEHOLDER_SALESFORCE_CRED_ID — HTTP Header Auth com Authorization: Bearer <sfdc_token> (ou uma credencial OAuth de Connected App para produção)
Aponte os webhooks para o n8n. Na Warmly, adicione a sua URL https://<your-n8n-host>/webhook/visitor-deanon em Settings → Webhooks. No RB2B, use a integração Webhook (ou um “Catch Hook” do Zapier encaminhando para a mesma URL). Nenhuma credencial fica armazenada no n8n para qualquer fornecedor — eles fazem push para você.
Ajuste a rubrica de ICP. Abra o ICP Fit Gate e leia o bloco de pontuação. Ele concede pontos por função do cargo, senioridade, faixa de tamanho da empresa, país e intenção da página, e aprova qualquer um em ou acima de ICP_FIT_THRESHOLD (default 3). Ajuste os pesos dos pontos e o threshold para a sua definição de fit antes de ativar.
Verifique cada caminho. Percorra a verificação no _README.md: faça post de um payload claramente dentro do ICP (deve passar e redigir), um payload claramente fora do ICP (deve cair no gate), e o mesmo payload dentro do ICP duas vezes (o segundo deve cair na dedup). Rode o teste de dedup contra o webhook ativo, não pelo botão Execute Workflow — a static data só persiste em execuções de produção.
O que o fluxo faz
Webhook — Visitor Deanon Ingest aceita requisições POST e retorna imediatamente 202 via Respond 202 Accepted para que o chamador do webhook do fornecedor não fique bloqueado na chamada do LLM. Normalize Visitor Payload é um node Code que detecta a fonte pelo formato do payload — RB2B (identificado pelos campos Business Email / Captured URL), Warmly (identificado pelo aninhamento de contato-mais-empresa), e um fallback genérico — e mapeia cada um para um registro interno com campos consistentes: firstName, lastName, title, company, domain, email, linkedinUrl, employeeCount, industry, country, pageViewed e referrer. O campo pageViewed vem do Captured URL do RB2B e do referrer do sinal da Warmly — é o que faz o rascunho ser warm em vez de frio.
ICP Fit Gate é o node que distingue este fluxo de um roteador de intenção simples. Ele pontua a pessoa contra uma rubrica: função do cargo contra uma allowlist (revops, sales, marketing, growth, founder, product) e uma denylist (student, intern, seeking, agency recruiter); senioridade (C-level, VP, Head, Director pontuam mais alto); faixa de tamanho da empresa entre ICP_MIN_EMPLOYEES e ICP_MAX_EMPLOYEES; país contra ICP_COUNTRY_ALLOWLIST; e intenção da página (uma visualização de /pricing, /demo ou /product adiciona pontos). Se o total ficar abaixo de ICP_FIT_THRESHOLD, o node retorna um array vazio e a execução para silenciosamente — a pessoa nunca chega a um rep. O fitScore e as razões são anexados ao registro para que o card do Slack de um visitante aprovado mostre por que ele qualificou, e para que uma rubrica mal configurada seja auditável.
Dedup Gate (Static Data) usa a static data de workflow do n8n — $getWorkflowStaticData('global') — para segurar uma chave por-pessoa-por-semana (dedup_<email-or-linkedin>_<ISO-week>). O nível semanal é a janela certa para outreach warm: alguém que visita seu site três vezes em cinco dias deveria gerar um toque de rep, não três. Esse objeto é a única forma correta de persistir estado entre execuções a partir de um node Code — a API REST pública do n8n não tem um recurso de static-data — e o node estampa a chave antes de qualquer chamada downstream para que dois reveals concorrentes da mesma pessoa não possam ambos passar, e poda chaves de semanas anteriores para que o store fique pequeno.
Salesforce — Contact Lookup consulta um Contact que bate com o email da pessoa, retornando o Contact Id, o Account Id, o Owner (Id, Name, Email, Slack_Handle__c) e dois sinais de supressão: se a conta tem uma Opportunity aberta e se o contato já está em uma sequência ativa (via um campo Current_Sequence__c). Routing & Suppression Logic então decide. Se o contato existe e qualquer sinal de supressão está setado — oportunidade aberta, sequência ativa, ou um tipo de conta de cliente existente — o node retorna um array vazio: um toque warm de deanon atropelaria um motion ativo, então é descartado e logado. Caso contrário, se o contato existe, o pico roteia para o dono da conta e o fluxo criará uma Task no contato existente. Se nenhum contato existe — o caso comum de deanon, já que o objetivo inteiro é trazer à tona pessoas que ainda não estão no seu CRM — ele roteia para um pool de SDR por território (AMER/EMEA/ROW por país) e o fluxo criará um Lead. O node define createSObject como Task ou Lead conforme o caso.
Claude — Draft Warm First Touch faz post para a API da Anthropic com claude-haiku-4-5, um timeout de 8 segundos e neverError: true. O system prompt bane enrolação (“I noticed”, “reach out”, “touch base”, “circle back”) e instrui o Claude a ancorar a abertura na página específica visualizada e no papel da pessoa — porque “vi que você estava na página de pricing” é acionável e “adoraria me conectar” não é. Parse Draft (with fallback) lida com um timeout ou JSON malformado produzindo um rascunho baseado em template marcado como draftSource: template-fallback; ambos os caminhos geram draftSubject, draftBody e draftTalkingPoint. Slack — Notify Assignee faz post de um card Block Kit para #visitor-deanon com o nome da pessoa, cargo, empresa, LinkedIn URL, a página que ela visualizou, o fitScore e as razões, e o rascunho rotulado “edit before sending”. Salesforce — Create Record faz POST para /sobjects/{{ createSObject }} — um Lead para pessoas net-new, uma Task ligada ao contato existente via WhatId caso contrário — com OwnerId definido apenas para um Salesforce User Id real (nunca um email, que retorna MALFORMED_ID) e omitido quando roteando para um pool.
Realidade de custo
Por visitante identificado que passa pelo gate de ICP, o claude-haiku-4-5 recebe por volta de 500 tokens de input e produz cerca de 150 tokens de output para o rascunho de três campos. No pricing do Haiku 4.5 (~$0.80/M input, ~$4/M output) isso dá cerca de $0.0007 por rascunho. O gate de ICP faz a contenção de custo: se o tier Pro do RB2B trouxer à tona ~1,000 visitantes identificados/mês e a sua rubrica aprovar 30%, você redige ~300 vezes/mês — menos de $0.25/mês em gasto com Claude. A janela de dedup significa que um visitante recorrente é cobrado uma vez por semana, não por visita.
A ferramenta de deanon é o item de linha de verdade, não a automação. O RB2B roda de $159/mês (~250 visitantes identificados) a $499/mês (~1,000); os planos pagos da Warmly começam em $15,000/ano e a suíte completa de Autopilot é $30,000/ano. O n8n self-hosted é grátis; o n8n Cloud Starter a $20/mês cobre 5,000 execuções, lidando confortavelmente com ~300 visitantes redigidos a ~9 nodes cada. O uso da API do Salesforce é uma query mais um create por visitante aprovado — algumas centenas de chamadas/mês contra um limite Enterprise de 15,000+/dia. O bot do Slack e o endpoint de webhook do n8n são grátis.
Modos de falha
A rubrica de ICP descarta todo mundo silenciosamente. Um threshold estrito demais ou uma allowlist de cargo que erra como seus compradores de fato escrevem os títulos deles (ex.: “RevOps” como substring de denylist pegando acidentalmente “Revenue Operations”) significa que todo visitante falha no gate e o canal #visitor-deanon fica quieto — o que parece “sem tráfego” quando na verdade é “filtro mal configurado”. Guarda: o ICP Fit Gate anexa fitScore e razões por-regra a todo registro, e a verificação do _README.md inclui fazer post de um payload conhecido dentro do ICP e confirmar que ele passa. Observe a taxa de aprovação na primeira semana; se estiver perto de zero em tráfego real, afrouxe a rubrica.
A static data de dedup só persiste em execuções de produção.Dedup Gate (Static Data) lê e escreve $getWorkflowStaticData('global'), que o n8n salva apenas quando a execução é disparada em produção — nunca em uma execução manual de Execute Workflow. Testar a dedup clicando Execute Workflow duas vezes faz o gate parecer quebrado quando está funcionando. Guarda: ative o workflow e faça POST para a URL do webhook ativo duas vezes; o segundo POST deve cair na dedup. O node poda chaves da semana anterior em toda execução, então o store se autolimpa.
O rascunho se dirige à pessoa errada. Deanon no nível da pessoa é probabilístico — a identificação do RB2B roda ~50-70% de acurácia em tráfego de ICP dos EUA — então um rascunho pode cumprimentar um nome que não é de fato quem visitou. Guarda: o fluxo nunca envia. O card do Slack começa com a LinkedIn URL para que o SDR verifique a identidade em um clique antes de editar e enviar, e o rascunho é rotulado como um ponto de partida tanto no system prompt quanto na mensagem do Slack.
A rotação do Bearer token do Salesforce trava os lookups. Um Bearer token bruto em SFDC_ACCESS_TOKEN rotaciona (a cada ~2 horas em orgs sem uma política de sessão persistente). Quando ele expira, Salesforce — Contact Lookup retorna 401 silenciosamente (por causa do neverError: true), então todo visitante parece net-new e é roteado para um pool como Lead — burlando a supressão silenciosamente. Guarda: fique de olho em uma sequência de criações de Lead com zero criações de Task mesmo quando você sabe que contatos existentes estão visitando; para produção, substitua o token bruto por um Connected App usando o fluxo OAuth 2.0 client-credentials. O _README.md cobre isso.
vs alternativas
vs Warmly Autopilot. O próprio agente da Warmly consegue qualificar e agendar a partir de uma visita, e se você já está pagando pelo tier de $30,000/ano e não roda o Salesforce como fonte da verdade para supressão, pode ser suficiente. Não é a ferramenta certa se você quer que a lógica de ICP e as regras de supressão sejam legíveis e auditáveis pelo seu time de ops, se você roda o RB2B junto ou no lugar da Warmly, ou se você quer que o toque seja um rascunho editado por rep em vez de um envio autônomo. Este fluxo te dá os três ao custo do n8n e funciona nos dois fornecedores.
vs RB2B → Slack → triagem manual. O push nativo do RB2B para o Slack é o status quo: toda pessoa identificada, sem filtro de ICP, sem consciência de CRM. É amigável para o tier grátis e ok em baixo volume, mas a 1,000 identificações/mês o canal vira ruído que os reps ignoram, e não há guarda contra pingar um contato que está no meio de um deal. Este fluxo filtra para o ICP primeiro e suprime motions ativos, então o que cai no Slack vale a pena ler.
vs um auto-enroll do Zapier no Instantly/Smartlead. A jogada de um clique é RB2B/Warmly → Zapier → sequenciador frio. Envia mais rápido e é o de maior risco: nenhuma checagem humana sobre uma identidade probabilística, nenhuma supressão contra oportunidades abertas, e envios frios para pessoas recém-deanonimizadas são a forma mais rápida de queimar um domínio de envio. Este fluxo troca essa velocidade por um rascunho com rep no loop e supressão consciente de CRM.
vs uma tabela do Clay em um feed de deanon. O Clay consegue puxar um feed de deanon, enriquecê-lo, aplicar uma rubrica de ICP com colunas de fórmula, e empurrar para um sequenciador — e é um forte encaixe para rodadas de prospecção em batch. Não é event-driven, então sempre há lag de batch entre a visita e o toque. Use o Clay para a camada semanal de enriquecimento-e-prospecção; use este fluxo para a resposta em tempo real, com-a-visita-ainda-warm.
# 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.