Outcome-trained ICP graph a field guide

Winners, losers,
and lookalikes.

Most tools score accounts against a description of your ideal customer. This one scores them against your outcomes — the deals you actually won and lost — and turns a few dozen labels into a living map of a market.

Grain  companies → buying groups → people Ground truth  won / lost deals Output  keystones · halo · exclusions
live layout · 2-D projection UMAP + HDBSCAN
won keystone lost keystone halo · lookalikes same-company edge account, unlabeled
00

The labeled loop is the whole point

why train on outcomes instead of a description

Every account-based platform will sell you a score. Almost all of them compute it the same way: you write down who your ideal customer is — industry, size, a few technographics — and the tool ranks the world by resemblance to that story. The story is a hypothesis, and it is usually wrong at the edges in exactly the places that matter.

We start from the other end. The only ground truth in go-to-market is which deals closed-won and which closed-lost. That signal is small, noisy, and precious — and most systems either throw it away or bury it inside weights they will not show you. We keep it, and we build everything on top of it.

The vocabulary of the map is simple. Keystones are communities of accounts with a distinctive win/loss signature — green where you win, red where you lose. The halo is the soft ring of lookalikes around a winning keystone. Buying groups are the people inside an account who actually decide. The rest of this page is how those three things get built, in order.

Fig.00 — the pipelineraw → embed → cluster → label → score → activate
01 · entities
Resolve
companies, buying groups, people
02 · embed
Vectorize
canonical text → 1024-d
03 · graph
Cluster
UMAP + HDBSCAN, soft
04 · label
Keystones
win/loss stats + FDR
05 · score
Lookalikes
calibrated + explainable
06 · act
Activate
audiences → outreach → labels
01

Accounts close deals, not people

the entity model & the grain of everything downstream

B2B revenue arrives at the account level, so the account is the unit of outcome — a deal attaches to a company. Inside that company is a buying group: the role-tagged set of people who evaluate, champion, and sign. Below them sit individuals, the unit of contact and identification, whose behavior rolls up to the account.

This ordering is load-bearing. Clustering, polarity, and lookalike scoring all operate primarily on company vectors. People are a secondary lens — once an account lights up, the buying group tells you whom to reach and in what role. A one-person business is just the degenerate case: a buying group of one.

Company

Unit of outcome. One row per resolved domain. Deals, win/loss labels, and firmographics live here. This is what gets clustered.

Buying group

Unit of decision. The people at an account, tagged by buying role, assembled by domain match under trust caps (see §07).

Individual

Unit of contact. Identified visitors and known contacts. Behavior (page views, in-market topics) rolls up to the account.

02

An account, written down as a vector

canonical text → text embeddings → pgvector

Before anything can be clustered it has to become a point in a high-dimensional space. Each entity is first serialized into a canonical text description assembled in a fixed field order — industry, then size band, revenue band, geography, description, and finally a sentence describing the roster. The order is locked deliberately: shuffling those fields measurably degrades downstream retrieval quality, so the template is versioned and frozen.

That text is embedded with a modern text-embedding model into a 1024-dimensional vector, stored in Postgres via pgvector behind an HNSW index for fast nearest-neighbor search. Every embedding is keyed by a hash of its source text plus the model and template version — so an unchanged account is never paid for twice, and a re-model only re-embeds what actually moved.

Design decision · no averaging

A company embedding is its own artifact, built from the company's own canonical text — never the mean of its members' vectors. Averaging people washes out exactly the firmographic signal that distinguishes accounts, so the company grain is embedded directly.

03

From a cloud of points to a map

dimensionality reduction, soft clustering, and where the halo comes from

A thousand-dimensional cloud isn't a map yet. We reduce it with UMAP twice: once into a ~15-dimensional clustering space that preserves neighborhood structure, and once into the 2-D layout you actually see. Both projections are computed server-side with a fixed random seed and cached — the browser never runs a physics simulation on tens of thousands of nodes; it renders a precomputed layout.

Then HDBSCAN finds the communities. Crucially it produces soft membership: every account gets a probability of belonging to each cluster rather than a hard assignment. That soft membership is where the halo falls out for free — an account sitting on the fringe of a winning community, with partial membership, is by definition a lookalike.

Two kinds of edge

Nodes are entities; edges come in two flavors, each capped so the render stays legible:

same-company · relational

A fact, not a similarity. People sharing a company are linked. Small accounts get a full clique; large ones collapse to a hub-and-spoke from the highest-confidence member so edge counts don't explode.

same-community · visual

k-nearest-neighbors in the 2-D layout stitch each cluster together. Edge weight is inverse layout distance — near neighbors draw bold, far ones fade.

Rendering honesty

The map can't draw every node, so it samples the highest-confidence members per community under a fixed budget — and the edge builder is handed the exact same sample, sorted the exact same way. Lines only ever connect nodes you can actually see. Sampling order and edge placement are one coupled decision, on purpose.

04

Which clusters are keystones?

the part that's mostly about refusing to lie with small samples

A cluster earns keystone status when its win/loss mix is different enough from your baseline that we would bet real money on the difference. The hard part isn't detecting a signal — it's not hallucinating one out of four data points. So a cluster passes through a three-layer statistical gate before it's allowed to claim anything.

Fig.04 — the keystone gateshrink · test · correct
a.Shrinkage

Empirical-Bayes, toward your baseline

A 4-deal cluster at "100% win rate" is not 100%. Each cluster's rate is pulled toward your overall win rate with a Beta(·) prior worth ~10 pseudo-deals, and we report a 95% credible interval — a range, never a bare point estimate.

b.Significance

Fisher's exact test

Is this cluster's split genuinely unlike the rest of the population, or just variance? A two-sided exact test yields a p-value. Below a floor of n = 4 deals, the verdict is simply no verdict.

c.Correction

Benjamini-Hochberg FDR

Test many clusters and some will look "significant" by luck. We control the false-discovery rate across all clusters at once (q ≈ 0.15), so the green ones survived multiple-comparison correction, not chance.

Survivors are ranked by WRAcc — weighted relative accuracy, which rewards a cluster for being both large (coverage) and distinctive (lift) rather than a tiny pocket of purity. Then each is tiered by how much we trust it:

HighFDR-significant · n≥10 · tight interval
MediumFDR-significant · smaller n
Noneindistinguishable from baseline
0% baseline 100% n=4 · 4W/0L shrunk ≈71% · wide CI raw 100% n=52 · 40W/12L shrunk ≈75% · tight CI ✓ keystone

Same 77% raw win rate, opposite verdicts. Four deals shrink hard and carry a credible interval too wide to act on; fifty-two barely move and earn a keystone. The map is built to under-claim — a cluster that's only 58% wins from a shared funnel stays neutral grey rather than being painted green for a demo.

05

Scoring the lookalikes

a deterministic, calibrated, explainable model — and its refusals

There are two ways to look like a winner. Geometrically — sitting near a winning keystone in embedding space, which is the halo. And by a trained scorer that reads an account's features and returns a fit score. The geometry is free; the scorer is where the discipline lives. It is built, deliberately, to be reproducible and to know when it should keep quiet.

a · the gate

≥20 wins and ≥20 losses before it trains at all. Under that threshold it returns nothing and says why — no fit scores invented from ten examples.

b · no leakage

PCA on every account, labeled or not, with a fixed seed. Because the reduction is unsupervised, no label can leak into the feature space it produces.

c · the bake-off

Logistic vs. LightGBM, chosen by stratified 5-fold cross-validation. At low sample counts logistic regression usually wins, and we let it — simpler and steadier.

d · calibration

Platt scaling on out-of-fold predictions. We then report percentiles, not raw probabilities — under positive-unlabeled data, ranks are trustworthy and absolute probabilities are not.

The leakage guard, concretely

Only signals an unknown prospect could also have are allowed to feed the model — page views, site visits, in-market topics, hiring activity. Never "they replied to our email" or "they reached stage 3 in the CRM," because you only observe those for people already in your funnel. Train on those and the model just learns to recognize your existing pipeline.

And the output is not a single black-box number. The scorer emits its top feature contributions, the loss exclusions — the traits that predict losing, so you can stop spending on them — and a reproducibility line. Negative lookalikes are a first-class deliverable, which is exactly the thing intent vendors won't give you: the losers, labeled, and the weights, shown.

06

One graph per ideal profile

stratification, so a winner in one motion can't poison another's baseline

A company can sell into more than one ideal customer profile — a self-serve motion and an enterprise motion, say — and blending them lies about both. A 70% win rate that's really 90% in one segment and 40% in another describes neither.

So the ICP is promoted from an implicit singleton to a first-class entity, and every downstream artifact is keyed by it: communities, memberships, edges, fit scores, audiences, layouts, snapshots. Keystone baselines and lookalike training run per ICP. A winner discovered in one profile never touches the baseline of another, and the same account can carry different fit scores under different profiles — because it genuinely is a different bet in each.

Parity by construction

When a client has exactly one profile, the stratified pipeline is byte-identical to the un-stratified one — the machinery is dormant until a second ICP exists. Correctness first; the multiplicity is there when you need it, invisible when you don't.

07

Buying groups, and closing the loop

attribution trust, the heat surface, and turning a map into motion

People join an account's buying group by email-domain match — a deliberately simple, binary rule — but simplicity needs guardrails. Each match is capped by a per-size-band roster ceiling: a company in the "11–25 employees" band that resolves 400 matched people is a data error, not a buying group, and gets dropped to an "unattributed" residual. Shared and freemail domains are blocklisted so a thousand strangers at one webmail host don't fuse into a fake account.

Outcomes are then de-duplicated to the latest closed deal per company, and an invariant is enforced: a company is never simultaneously a win and a loss. Clean labels in, honest keystones out.

The heat surface

Over the 2-D layout the map paints a smoothed win/loss lift field — a kernel-density estimate normalized so one deal reads as roughly one unit, masked wherever evidence is too thin to mean anything. You can see, at a glance, the regions where wins concentrate and where they evaporate.

Then the map does work. A keystone or its halo becomes an audience — pushed to email sequences, synced to your CRM, or mirrored into ad platforms as a custom audience. The outreach produces replies, meetings, and eventually new closed deals. Those come back as fresh labels, the model re-trains, and the keystones sharpen. That is the loop — and it is the only moat that compounds. Warehouse row counts don't; a tightening outcome model does.

08

The whole thing, in constants

the tuning surface, on one screen
Tbl.01 — tuning constantsrepresentative defaults
ParameterValueWhere it bites
Embedding dimension1024text-embedding model, HNSW in pgvector
PCA components8full-SVD, fixed seed, fit on all accounts
Keystone floor · nmin4below this, no win/loss verdict
Empirical-Bayes prior strength≈10pseudo-deals of pull toward baseline
FDR level · q0.15Benjamini-Hochberg across all clusters
Watch-tier lift0.10early-signal threshold vs. baseline
Scorer training gate20W / 20Lminimum labels before it trains
Cross-validation5-foldstratified; picks logistic vs. LightGBM
Same-company clique max6above this, hub-and-spoke not clique
Layout k-NN3same-community stitching edges
Company similarity · k / floor6 / 0.55cosine neighbors between accounts
Edge budget5k + 5krelational + visual, per client·ICP
Heat grid96² · σ2.5KDE lift surface, masked ≥0.35