Who is visiting
A visit to your pricing page in, the company behind it out, checked against your customer sentence and added to your accounts when it fits.
- Kind
- Workflow
- Price
- 1.2¢ per visit
- Your time
- 4 minutes
- Approval
- Runs on its own
- Deepens
- Inbound sales
Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.
curl -X POST "https: //api.sb/ leaseline.app/ visitors/ match? mode= try" \
-H "Authorization: Bearer $SB_TOKEN" \
-H "Content-Type: application/ json" \
-d '{"goal": "Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.", "budget": {"amount": 1, "currency": "USD"}}'
npx startup-builder do Visitor.match --try --data '{"goal": "Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.", "budget": {"amount": 1, "currency": "USD"}}'
{
"name": "do",
"arguments": {
"mode": "try",
"code": "return await $.Visitor.match({ goal: 'Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.', budget: { amount: 1, currency: 'USD' } })"
}
}
import { $ } from 'startup-builder'
const result = await $.try.Visitor.match({ goal: 'Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.', budget: { amount: 1, currency: 'USD' } })
{
"mode": "try",
"stored": false,
"estimate": "About 1.2¢ a visit",
"sample": {
"visit": "/pricing, twice",
"company": "Harbor Point Residential",
"fit": "strong",
"added": "account Audience",
"why now": "visited /pricing twice this week"
}
}
What you get
- 1 visit · A visit to your pricing page in, the company behind it out, checked against your customer sentence and added to your accounts when it fits. · Visitor
organization· The company behind the visit: hostname, name andfit(strong,possibleornone), or nothing when the visit came from a home or mobile network.added· The account Audience it joined, withwhyNow, such as “visited /pricing twice this week”.person· Empty until the visitor signs up;Visitor.identifyjoins them then.
Connect once: Google Analytics. How long: Under 5 seconds.
Trigger
It runs on each new session on a buying page, from a visitor who is not a customer and not a bot.
on.Visit.created((visit, $) => ['/pricing', '/compare', '/demo'].includes(visit.path) && $.Visitor.match({ visitor: visit.visitor }))Steps
Your agent does these steps, one row per step; each step’s check is part of its row and its price.
| Step | Verb | Returns | Price | Approval |
|---|---|---|---|---|
| 1. Find the company behind the visit | Organization.resolve | The company’s hostname, or no match; a miss is free | About 1¢ | Runs on its own |
| 2. Read the company’s profile | Organization.enrich | Headcount, location and industry | About 0.2¢ | Runs on its own |
| 3. Check it against your customer sentence | Collection.query | strong, possible or none, by the declared rule | Free | Runs on its own |
| 4. Add a strong fit to your accounts | Audience.update | The company on the account Audience, with why now | Free | Runs on its own |
Calls: Organization.resolve, then Organization.enrich, then Collection.query, then Audience.update.
About 1.2¢ a visit, each time it runs, capped at 5¢.
Example: give it a goal
Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first.
The plan it shows runs 4 steps, priced before it spends anything; Run it above shows the result it returns.
When something fails
Each failure, and what happens next
| When | Then |
|---|---|
| The visit came from a home, mobile or VPN network | No company resolves, the visit keeps no row, and the miss costs nothing. |
| The company is already a customer | It is skipped before any read: the trigger ignores customers. |
| One visitor comes back the same day | The stored match is returned at $0: it is idempotent per visitor and day. |
Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-visitor-match-1-<step>-<item>.
Change it
| Ask | Compiles to |
|---|---|
| Write to the operations lead at each strong fit within the hour. | Prospect.reach |
| Show my ads to the companies that visited pricing. | Integration.sync |
| Resolve visits to my blog posts too. | Visitor.match |
import { $, workflow } from 'startup-builder'
export default workflow({
name: 'visitor-match',
verb: 'Visitor.match',
input: { visitor: 'string' },
trigger: { event: 'Visit.created' },
maxCost: 0.05,
execute: async (ctx, { visitor, icp = 'icps/icp_4' }) => {
const org = await ctx.step('resolve', () => $.Organization.resolve({ visitor, maxCost: 0.01 }))
if (!org.match) return { visitor }
const profile = await ctx.step('profile', () => $.Organization.enrich({ hostname: org.match.hostname, fields: ['profile'], maxCost: 0.01 }))
const fit = fitOf(profile, icp) // the declared ICP rule
if (fit !== 'strong') return { visitor, organization: { ...org.match, fit } }
return ctx.step('add', () => $.Audience.update({ id: 'audiences/audience_accounts' , add: [org.match], whyNow: 'visited /pricing' }))
},
})Extend it with extends: and base(), or compose your own from these steps.
Works with
Plays that order it: Account visits, Retargeting.
It serves Convert visitors, and runs in Paid. It deepens Inbound sales.
For agents
For agents: the guide, its approvals, retries and lookups
| Fact | Value |
|---|---|
| Guide | Visitor.match |
| Guide approval | limits |
| Goal | Tell me which companies visited my pricing page twice this week and fit my ICP, spend up to $1, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval. |
| Trigger | on.Visit.created((visit, |
| Retry | Three times with backoff, then the next route; the same idempotency key never charges, sends or posts twice |
| Idempotency key | leaseline-visitor-match-1 |
| Lookups | A find: input asks unless exactly one record fits |
| Step |
|---|
| 1. Find the company behind the visit |
| 2. Read the company’s profile |
| 3. Check it against your customer sentence |
| 4. Add a strong fit to your accounts |
The amounts live once, on the hub (approvals).
Who does each step, and how it is checked
| Step | Function | Doer | Checker | Assurance | Inputs |
|---|---|---|---|---|---|
| 1. Find the company behind the visit | code | Code | Code checks each result against its declared type | measured | $0.visitor |
| 2. Read the company’s profile | code | Code | Code checks each result against its declared type | measured | $1.hostname |
| 3. Check it against your customer sentence | code | Code | Code checks each result against its declared type | measured | $2, |
| 4. Add a strong fit to your accounts | code | Code | Code reads the result back from where it landed | measured | $3.strong |
The doer is never the checker, and the weakest assurance on the path is the whole call’s.
Under the hood
Under the hood: the Systems, Nouns and Events it touches
| Kind | What it touches |
|---|---|
| Systems | None. |
| Nouns | Organization, Collection, Audience |
| Events | Collection.queried, Audience.updated |
Reference
Inputs, outputs, its Event and its errors
| Name | Type | Default | Meaning |
|---|---|---|---|
visitor | Visitor | Required | The visit to resolve. |
paths | string[] | ['/ | Only visits to these pages are resolved: a buying page is the trigger, a blog read is not. |
icp | ICP | your saved ICP | The declared rule a company must pass to be added. |
maxCost | number | 0.05 | The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link. |
Emits Visitor.matched. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).