Alert sales when an ideal-fit company browses your site
Resolves anonymous PostHog visitors to companies with People Data Labs, judges fit and buying stage with Jev, and alerts sales in Slack.
Outcome
A table of the companies behind your anonymous visitors, with the pages each viewed, its fit level, buying stage and Jev's confidence.
A Slack post for each company that fits and is evaluating or ready to talk, with its HubSpot owner.
How it works
- 1
Find engaged visitors
PostHogSelect
$pageviewevents from the lastlookback_daysby persons with noemail, grouped by the event's$ip, with the distinct$pathnamevalues and the view count. Keep the IP addresses with at leastmin_pagespages, with their pages. - 2
Resolve the companies
People Data LabsLook up each IP address, up to
max_lookups, requesting the IP's metadata. Skip VPN, proxy, mobile and hosting addresses and matches belowmin_match. Keep each company's name, website, size and industry, with the pages its visitors viewed. - 3
Judge fit and stage
TypeSafe AISend each company's facts and pages as the state, with a score
fitwhose levels describe the match withideal_customer: no fit (matches none of it), weak (matches some), good (matches most) and ideal (matches all); and a choicestageof researching (blog and docs), evaluating (pricing, comparisons, case studies or security), ready_to_talk (contact or demo pages), existing_customer (the app, login or billing) and job_seeker (careers). Keep each answer with its confidence. - 4
Check the unsure ones with the user
Your agentShow the user the companies whose fit or stage confidence is below
min_confidence, and keep what the user decides. Keep the companies with a fit ofmin_fitor better that are evaluating or ready to talk. - 5
Find the owner
HubSpotSearch companies by each website's domain. Keep each company's record ID and
hubspot_owner_id, and look up each owner's name, a read-only call. Note the ones with no record. - 6
Alert
SlackPost each kept company to
alerts_channelwith its size, industry, fit level, stage, the pages viewed and its owner's name.
You'll be asked for
The window to read visits from
e.g. 1
How many pages one IP address must view to count
e.g. 3
The most IP addresses to resolve in one run, since each match is charged
e.g. 100
The lowest People Data Labs match confidence to keep
e.g. high
The companies you sell to, in a sentence or two
e.g. B2B software companies with 50 to 1,000 employees
The lowest fit level worth an alert
e.g. good
How sure Jev must be before its answer is used without you
e.g. 0.8
The Slack channel to post in
e.g. #sales-signals
The file your agent runs
visitor-company-fit.md
Alert sales when an ideal-fit company browses your site
Resolves anonymous PostHog visitors to companies with People Data Labs, judges fit and buying stage with Jev, and alerts sales in Slack.
Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.
Outcome
- A table of the companies behind your anonymous visitors, with the pages each viewed, its fit level, buying stage and Jev's confidence.
- A Slack post for each company that fits and is evaluating or ready to talk, with its HubSpot owner.
Inputs
Ask the user for these before you start.
lookback_days: the window to read visits from, e.g. 1min_pages: how many pages one IP address must view to count, e.g. 3max_lookups: the most IP addresses to resolve in one run, since each match is charged, e.g. 100min_match: the lowest People Data Labs match confidence to keep, e.g. highideal_customer: the companies you sell to, in a sentence or two, e.g. B2B software companies with 50 to 1,000 employeesmin_fit: the lowest fit level worth an alert, e.g. goodmin_confidence: how sure Jev must be before its answer is used without you, e.g. 0.8alerts_channel: the Slack channel to post in, e.g. #sales-signals
Set up
Run a SQL query (PostHog, tool:posthog/run-sql-query)
Use the first option your agent supports.
Note: Needs a personal API key with the query:read scope. Returns up to 100 rows by default and up to 50,000 with an explicit LIMIT; it is for ad-hoc analysis, not bulk export.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "posthog": { "url": "https://mcp.posthog.com/mcp" } } }
Call the MCP tool execute-sql.
CLI (official)
Install the command, then confirm it runs.
npm install -g @posthog/cli@latest
posthog-cli --version
Run posthog-cli api call execute-sql.
Set $POSTHOG_CLI_API_KEY in your environment first (get a key: https://app.posthog.com/settings/user-api-keys?preset=mcp_server).
Identify the company behind an IP address (People Data Labs, tool:people-data-labs/identify-ip-company)
Use the API.
- Base URL: https://api.peopledatalabs.com
- Endpoint:
GET /v5/ip/enrich - Auth: send the header
X-Api-Key: $PDL_API_KEY - Get a key: https://dashboard.peopledatalabs.com/api-keys
Note: Charged per match.
Answer typed questions (TypeSafe AI, tool:typesafe/answer-typed-questions)
Use the API.
- Base URL: https://api.typesafe.ai
- Endpoint:
POST /v1/systemone - Auth: send the header
Authorization: Bearer $TYPESAFE_API_KEY - Get a key: https://console.typesafe.ai
Note: Put every question about one record in one request. GET /v1/models lists the models and is the cheapest check of a key; a request over the rate limit gets a 429 with a Retry-After header.
Note: Send state, model (jev-latest) and named questions, each with type, instructions and criteria: a choice maps labels to descriptions, a score lists its levels in order, a noul's is optional. Read a score by its most likely level; send unsure answers to a person.
Search CRM records (HubSpot, tool:hubspot/search-crm-records)
Use the first option your agent supports.
Note: The MCP tool takes up to five groups of six filters and returns up to 200 records per page.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "hubspot": { "url": "https://mcp.hubspot.com" } } }
Call the MCP tool search_crm_objects.
API (official)
- Base URL: https://api.hubapi.com
- Endpoint:
POST /crm/objects/2026-09/{objectType}/search - Auth: send the header
Authorization: Bearer $HUBSPOT_API_KEY
Note: Use a service key or an app's static access token with the CRM scopes the calls need; paths carry a dated version such as 2026-09.
Post a message (Slack, tool:slack/post-message)
Use the first option your agent supports.
Note: Needs the chat:write scope. Over MCP it posts as the signed-in user; the API and CLI post as the app's bot.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "slack": { "url": "https://mcp.slack.com/mcp" } } }
Call the MCP tool slack_send_message.
CLI (official)
Install the command, then confirm it runs.
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash
slack --version
Run slack api chat.postMessage.
Set $SLACK_BOT_TOKEN in your environment first (get a key: https://api.slack.com/apps).
Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.
Steps
- Find engaged visitors with Run a SQL query (PostHog). Select
$pageviewevents from the lastlookback_daysby persons with noemail, grouped by the event's$ip, with the distinct$pathnamevalues and the view count. Keep the IP addresses with at leastmin_pagespages, with their pages. - Resolve the companies with Identify the company behind an IP address (People Data Labs). Look up each IP address, up to
max_lookups, requesting the IP's metadata. Skip VPN, proxy, mobile and hosting addresses and matches belowmin_match. Keep each company's name, website, size and industry, with the pages its visitors viewed. - Judge fit and stage with Answer typed questions (TypeSafe AI). Send each company's facts and pages as the state, with a score
fitwhose levels describe the match withideal_customer: no fit (matches none of it), weak (matches some), good (matches most) and ideal (matches all); and a choicestageof researching (blog and docs), evaluating (pricing, comparisons, case studies or security), ready_to_talk (contact or demo pages), existing_customer (the app, login or billing) and job_seeker (careers). Keep each answer with its confidence. - Check the unsure ones with the user yourself. Show the user the companies whose fit or stage confidence is below
min_confidence, and keep what the user decides. Keep the companies with a fit ofmin_fitor better that are evaluating or ready to talk. - Find the owner with Search CRM records (HubSpot). Search companies by each website's domain. Keep each company's record ID and
hubspot_owner_id, and look up each owner's name, a read-only call. Note the ones with no record. - Alert with Post a message (Slack). Post each kept company to
alerts_channelwith its size, industry, fit level, stage, the pages viewed and its owner's name.
Notes
Visitor IP addresses are personal data in many places, so run this only if your privacy notice covers sharing them with an enrichment vendor. PostHog keeps the $ip property only when the project does not discard client IP data; check the project settings first. The stage comes from which pages were viewed, which is why the pages go into the state alongside the company.
It finds companies, not people: reach the right person through the account owner, never by guessing who visited. Run it daily with lookback_days set to 1.
Rules
- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
