Visitor identification
Learn which companies visit your website and what they read: Snitcher identifies the organisation behind each visit, two Cargo models keep the visiting companies and their sessions current, and the site loads the tracker only after a visitor accepts it.
Set up the visitor-identification cookbook in this project.
1. If the Cargo CLI is not installed yet, follow every step in https://api.getcargo.io/INSTALL.md
2. From the Cargo project, run: cargo-ai cdk add cookbook/visitor-identification
3. Then follow .claude/skills/visitor-identification/SKILL.md. Stop for my approval before any paid call, and stop at "cargo-ai project plan" before deploying anything.$cargo-ai cdk add cookbook/visitor-identificationSay this to your agent
Show us which companies visit www.fabrikam.example, and only track visitors who accept.
Illustrative output #
Fictional records, to show the shape of what comes back.
model:website_visiting_companies deployed 12 companies after the first day
northwind.example Software first seen 09:14 last seen 16:02
contoso.example Logistics first seen 11:40 last seen 11:52
model:website_visitor_sessions deployed 31 sessions
northwind.example /pricing/ /about/ referrer: linkedin.com
app:website updated consent gate on, tracker after accept only
Rows land on Cargo’s own sync interval. A day with no identified company is an honest zero: not every IP resolves to an organisation.
Done when #
node --import tsx evals/contract.mjspasses: the companies model isfetchOrganisationson the Snitcher connector with an HTTPSurl, the sessions model isfetchSessionsreadingconfig._workspaceUuidfrom it, both are filed invisitor_identification_models- the plan’s first deploy shows the two models and the app update, and the operator approved the spend against the live price
- in a browser on the canonical origin: no request to
snitcher.combefore a choice, after “Reject tracking”, or after withdrawing and reloading; one “Accept tracking” makes a request tocdn.snitcher.comandradar.snitcher.com - the Cargo URL and a draft preview make no request to
snitcher.comand show no banner - after the sync interval the models hold rows, or a zero reported as a zero
- the banner links to the reviewed privacy disclosure
What it costs #
Each company Snitcher identifies is billed once, when it first lands in the companies model;
sessions add nothing. Read the live price from the integration (cargo-ai connection integration get snitcher) and the workspace’s credit balance before the first deploy, and quote both. Spend
follows the site’s traffic and there is no built-in cap, so say that too. Removing the companies
model stops the billing.
Which companies visit the website, and what they read, kept current in two Cargo models. The tracker loads only after a visitor accepts it.
visitor accepts on the site
-> the site's own Snitcher loader (profile ID only)
-> Snitcher identifies the company from the visit
-> website_visiting_companies + website_visitor_sessions (Cargo, on its sync interval)
Why it is built this way #
One deploy, no capture step. Snitcher’s tracker and workspace only exist once the companies
model is created. visitingCompanies.config._trackingScript and ._workspaceUuid are CDK tokens,
so the sessions model and the site’s env read them in the same deploy that creates them.
The site owns its loader. The provider’s snippet is a script; the site takes only its public profile ID from it, rejects any other shape at build time, and loads Snitcher with settings this repository reviews: consent required, form, click, download, error and recording capture off.
Nothing before consent. Snitcher’s own waitForConsent still records pageviews and sessions
before consent, so the gate does not request the tracker at all until the visitor accepts.
Company-level by design. An IP address resolved to an organisation. No identify call, no person, no outreach in this skill.
Placeholders (edit before deploy) #
- Site URL:
infra/models/companies.tsurl, the site’scanonicalUrl. - Privacy disclosure:
site/visitors.jsonprivacyPolicyUrl, once copied into the app.
Files #
| Path | What it is |
|---|---|
infra/connectors/snitcher.ts | Snitcher on Cargo’s credits |
infra/models/companies.ts | fetchOrganisations: the companies, and the tracker |
infra/models/sessions.ts | fetchSessions, on the provisioned workspace |
site/lib/snitcher.ts | Snippet to reviewed settings; anything else fails |
site/lib/visitors.ts | Build-time switch: settings, or no gate at all |
site/components/visitor-consent.tsx | The consent gate and the loader |
references/consent.md | Wiring the site, and checking the gate in a browser |
references/data.md | What the rows mean, querying, stopping |
evals/contract.mjs | Graph and parser contract |
Verify #
node --import tsx visitor-identification/evals/contract.mjs