B2B Enrichment (formerly Lead Intelligence)
Audience: Sales · Management · Support · Engineering · QA · Where in app: results shown on Live Sessions, Recorded Sessions, Leads, Person Detail · Plan availability: package-driven for every account (features.lead_intelligence_allowed + features.lead_intelligence daily cap)
"Lead Intelligence" as a separate feature flag no longer exists.
companies.lead_intelligence/lead_intelligence_allowed, the admin toggle and cap,/happier-leads/quota, and the whole HappierLeads integration (pixel, service, config,HappierLeadSessionModel, inbound webhook, provisioning route, ms-comm mirror fields) were deleted on 2026-09-09 (d8a283a1b) — they only ever gated the HappierLeads pixel, which left the widget on 2026-07-01. The engineering detail now lives on Identity Graph; this page keeps the product-level summary for the people who used to come here.
What it does
- Resolves a visitor's IP/network to a company (name, domain, industry, size) via Snitcher, then a person via Apollo (domain → people match).
- Feeds the resolved company/person onto the session, the Leads view, the
industry_matchlead-scoring signal, and the identity graph. - Caches results to conserve quota; enrichment guesses never mint
verifiedidentity and never overwrite a self-provided name.
Providers
| Provider | Status |
|---|---|
| Snitcher (reverse IP → company) | Active, company-level, not GDPR-gated (legitimate interest) |
| Apollo (domain → person) | Active, person-level, GDPR-gated |
| RB2B | Webhook path only |
| Clearbit | Cache-read only; live call disabled |
| HappierLeads | Removed — only readers of the historic happier_leads_data session blob remain |
Plan & limits
Identification runs when snitcher_enabled && (snitcher_allowed ?? 20) > 0. Both come from the package at every subscription sync (SubscriptionHelper: trial, Stripe subscribe, update, package change, platform create) — snitcher_enabled = !!features.lead_intelligence_allowed, snitcher_allowed = features.lead_intelligence ?? 20 — so a super-admin override is reset by the next sync. A cap of 0 now blocks (it used to mean unlimited). The daily cap is counted in the company's local timezone (00:00–06:00 spends only yesterday's leftover); bots never spend quota; Apollo has no separate quota and only runs after Snitcher resolves a domain.
Off by default for partner accounts (invite redemption clears the switches; buying a package restores them) and for archived companies/agencies.
GDPR
With companies.gdpr_protection_enabled (default true), visitors located in the EEA, UK, or Switzerland — and visitors whose country can't be determined — are never identified at person level: no Apollo match, and the widget never computes the device fingerprint. Snitcher's company-level resolution still runs. Super-admins can turn it off per company. See Identity Graph › GDPR.
Behaviors & edge cases
- Company ≠ person. Reverse-IP identifies the network. A visitor from Acme's office is "Acme Corp", not a named person, until a first-party signal (form, chat, call, booking, CRM link) or a verified device match says otherwise.
- Apollo error responses are never cached (error-cache poisoning fix);
POST /admin/identity/maintenance/cleanup-apollo-recordspurges poisoned rows so domains retry. - Returning identified visitors don't burn quota — internal resolution (widget id, cookie, device signature) runs before enrichment.
- The enrichment-guess CRM push job (
LeadContactSyncJob) stays disabled globally.
Related
- Identity Graph — the engineering view.
- Leads overview · Lead scoring (
industry_match). - Consent gating — what the Identification category gates.