Every readiness dot, meter and band in Engage comes from one function that runs over your own data. It is a fixed arithmetic formula — no model, no training, no inference — and this page publishes it in full, because a score you cannot explain to a colleague is a score nobody trusts.
Say that part out loud before anything else: the numbers on this page are not AI output. The Recompute scores button is styled like the rest of Leed’s AI affordances and it is gated by an AI privilege, but what it runs is a hundred lines of addition over fields you can see on the contact record. If a contact scores 68 you can work out why with a calculator.
What a score is
A score is a stored row, attached either to a contact or to an account, holding up to seven values:
| Value | Range | Set for contacts | Set for accounts |
|---|---|---|---|
| Readiness | 0–100 | Yes | Yes |
| Fit | 0–100 | Yes | Yes |
| Intent | 0–100 | Yes | Yes |
| Journey stage | one of four | Yes | Yes |
| Committee role | one of six, or none | Yes | Never |
| Matched persona | a persona, or none | Yes | Never |
| Persona confidence | 0–100 | Yes | Never |
The word to hold on to is stored. Scores are written by the recompute and read back on every Engage screen; nothing is calculated while you look at it. A contact that has never been through a recompute has no row at all, and every score surface says so honestly — the Signals facet reads Not scored yet., the status strip shows dashes, and the Leed note tells you to run a recompute.
Fit
Fit answers how much does this person look like somebody we sell to? It is profile completeness plus one quality signal, and it starts everyone at 25.
fit = 25 + 25 \cdot corporate + 15 \cdot fullName + 15 \cdot title + 10 \cdot linkedIn + 15 \cdot account + 5 \cdot phone
| Signal | Points | How to satisfy it |
|---|---|---|
| Baseline | 25 | Existing at all |
| Corporate email domain | 25 | The email domain is set and is not one of the ten consumer domains below |
| First and last name | 15 | Both — one alone scores nothing |
| Job title | 15 | Any non-empty title |
| LinkedIn URL | 10 | Any non-empty URL |
| Linked account | 15 | The contact is attached to a business in Accounts |
| Phone number | 5 | Any non-empty phone |
The maximum of those parts is 110, and the result is rounded and clamped to 100 — so a fully-filled corporate contact reads 100 and there is a little headroom above it that you never see. A contact with nothing but a consumer email address scores the bare 25.
Why my consumer-domain contacts score lower
Exactly ten domains are treated as non-corporate:
gmail.com · yahoo.com · hotmail.com · outlook.com · aol.com · icloud.com · proton.me · gmx.com · live.com · msn.com
An address on any of those forfeits the 25-point corporate bonus. Everything else — including a domain Leed has never seen, a university address and a one-person consultancy — counts as corporate. The list is a fixed constant; there is no setting for it and no way to add your own.
There is a second, quieter effect. Fit feeds readiness at three tenths of its value and it feeds persona confidence at a fifth, so the 25 points move more than one number. A workspace selling to individuals rather than to businesses will see its whole population sit lower than a workspace selling to companies, which is a reason to read readiness relative to your own list rather than against an absolute 70.
Intent
Intent answers how much buying signal has this person actually shown? It is a baseline set by how they entered your funnel, plus their email engagement.
| Source | Baseline | Then add |
|---|---|---|
form — filled in one of your forms | 55 | 18 per recorded email click, and 6 per recorded open |
salesforce — arrived over the CRM webhook | 45 | " |
valid_email — identified by opening or clicking an email | 30 | " |
mcp — signed in to your documentation | 20 | " |
upload — came in on a CSV | 10 | " |
manual, or any source not listed | 15 | " |
Clicks and opens are counted across every email that contact has ever been sent, not over a window. The sum is rounded and clamped to 100, so a heavily-engaged contact tops out rather than running away.
The ordering is the interesting part. Somebody who filled in a form starts 45 points ahead of somebody you imported, before either of them has done anything — which is the product’s opinion that a person who came to you is worth more than a person you bought. Whether you agree is a matter for how you read the bands.
Readiness
Readiness is the blend, and it is the number the dots, the meters, the default sort and the Hot and Stalled views all key off.
readiness = 0.5 \cdot intent + 0.3 \cdot fit + 12c + 4o
where c is the contact’s total email clicks and o their total opens. Rounded, clamped to 100.
Clicks appear twice — once inside intent at 18 points each, and again here at 12. That is deliberate, not a bug: a click is the strongest signal Leed can observe without you telling it anything, so it is weighted into both the component and the blend. The practical consequence is that email engagement moves readiness faster than any profile field can. Two clicks are worth more than a complete profile.
Note also that fit contributes only three tenths of itself, and the baseline fit of 25 is worth 7.5 readiness points. A contact you have never emailed and who came in on a CSV sits at around 15 readiness however completely you fill in their record.
Journey stage
The stage is banded from the stronger of readiness and intent — not from readiness alone.
| Stage | Label shown | Reached when max(readiness, intent) is |
|---|---|---|
awareness | Awareness | below 25 |
consideration | Consideration | 25 to 49 |
evaluation | Evaluation | 50 to 74 |
decision | Decision | 75 and above |
Using the maximum rather than readiness is what stops a brand-new form fill from reading as Awareness: that contact has intent 55 and readiness around 24, and the stage that matters is the 55.
Committee role
A contact’s buying-committee role is inferred from their job title, by pattern, and by nothing else. No behavior, no account data, no persona text takes part. Patterns are tested against the lower-cased title in the order below, and the first one that matches wins.
| Role | Label shown | Title patterns that match | Ever inferred automatically |
|---|---|---|---|
champion | Champion | — | No |
economic | Economic Buyer | chief, ceo, cfo, cto, coo, founder, owner, president, partner | Yes |
decision | Decision Maker | vp, vice president, head of, director | Yes |
influencer | Influencer | manager, lead, principal | Yes |
user | End User | engineer, developer, analyst, specialist, coordinator, designer, associate | Yes |
blocker | Blocker | — | No |
Every pattern is a plain substring test, which has two consequences worth planning around.
The first is that “Vice President of Sales” is classified as an Economic Buyer, not a Decision Maker. The economic pattern is tested first and it contains president, so any title containing that word matches there before the decision rule is ever reached. The same applies to partner and owner — “Product Owner” reads as Economic Buyer.
The second is that a contact with no title has no role at all, and a title made of words that appear in none of those lists — “Growth”, “Solutions Architect”, “Consultant” — also yields nothing. No role means no persona match, which is covered next.
Persona match
A persona is matched to a contact through the committee role, and through nothing else.
During a recompute, Leed builds a lookup from role to persona by walking your personas in creation order and keeping the first persona that declares each role. Each contact’s inferred role is then looked up in that map. That is the whole mechanism, and it produces two rules that are invisible in the interface:
- A contact whose title yields no role never matches any persona, however precisely the persona describes them. The persona’s summary, goals, pains and everything else are free text that the matcher never reads.
- A second persona declaring a role that an older persona already declares can never match anybody. It is not an error and nothing warns you; it simply sits at zero matches forever. Personas covers what to do about it.
Confidence is a signal-strength heuristic over the same data, not a probability:
confidence = 50 + 20 + 0.2 \cdot fit
The middle term is 20 whenever a title is present — and a match requires a role, which requires a title, so it is always 20 for a matched contact. Confidence therefore lands between 78 and 90 in practice, and the label the rail shows (High at 85 and above, Likely at 65, Low below that) can only ever read High or Likely. A matched contact never shows Low confidence. High means their fit is 75 or better; Likely means it is not.
The rail’s “Why this match” note reads “… was classified against this persona from title and on-site behavior.” Treat the second half of that sentence as marketing rather than mechanism: on-site behavior plays no part in persona matching.
Account scores
An account’s score is the plain average of its member contacts’ numbers:
- readiness, fit and intent are each averaged across every contact linked to the account and rounded
- the journey stage is then banded from those averages by the same rule as a contact’s
Accounts get no committee role, no persona and no confidence — which is why the account’s Engagement facet shows only Readiness, Fit, Intent and Stage, and why the buying committee is assembled from the contacts rather than from the account. The full account read-out is on Accounts.
An account with no linked contacts gets no score row at all.
The whole pipeline in one picture
flowchart LR
subgraph inputs["Fields on the contact"]
D["Email domain"]
N["First + last name"]
T["Job title"]
L["LinkedIn URL"]
A["Linked account"]
P["Phone"]
S["Source"]
end
subgraph email["Email engagement"]
O["Opens"]
C["Clicks"]
end
D --> FIT["fit<br/>25 + 25 + 15 + 15 + 10 + 15 + 5"]
N --> FIT
T --> FIT
L --> FIT
A --> FIT
P --> FIT
S --> INT["intent<br/>source baseline"]
C -->|"+18 each"| INT
O -->|"+6 each"| INT
INT -->|"× 0.5"| RDY["readiness"]
FIT -->|"× 0.3"| RDY
C -->|"+12 each"| RDY
O -->|"+4 each"| RDY
RDY --> STG["journey stage<br/>banded on max(readiness, intent)"]
INT --> STG
T --> ROLE["committee role<br/>title patterns only"]
ROLE --> PER["matched persona<br/>first persona for that role"]
FIT --> CONF["persona confidence"]
PER --> CONF
RDY --> ACC["account score<br/>average of member contacts"]
FIT --> ACC
INT --> ACC
ACC --> ASTG["account journey stage"]
Two things the picture makes obvious that a list does not: clicks reach readiness by two separate routes, and the only path from a contact to a persona runs through their job title.
Recomputing
Recompute scores sits at the right of the Engage header, on every section, whatever is selected.
What it does, precisely:
- It rescores every contact and every account in the workspace. It is not scoped to whatever you happen to have selected — the selection is irrelevant to it.
- It needs
ai:write(Content Writer and above). Without that privilege the button is not rendered at all, and the rest of Engage works normally. - It runs inline, while you wait. The button reads Recomputing… and is disabled for the duration, and the response reports how many contacts were processed. On a large workspace this can take a while; there is no background job and no progress bar.
Both halves are available to an AI client, under the same permissions: get_engage_scores reads one contact’s score, one account’s, or the whole workspace’s, and recompute_engage_scores triggers the same run the button does. The contacts and accounts tool reference has the argument shapes. Note that the tool description calls the recompute asynchronous; it is not — the request runs the whole pass before it answers.
Where the numbers turn up
| Surface | Which number |
|---|---|
| The dot on every list row, in Accounts and Contacts | Readiness |
| Sort by readiness in the left panel’s Filter & view menu | Readiness |
| The status strip on a contact and on an account | All of them, plus the stage pill and the role pill |
| The Signals facet on a contact | Readiness meter, then Readiness, Fit, Intent, Stage, Computed |
| The Engagement facet on an account | Readiness, Fit, Intent, Stage, linked contacts, Computed |
| The Match facet on a contact | Matched persona, role label, confidence percentage and label |
| The Hot leads and Stalled saved views | Readiness, banded at 70 and 45 |
| The persona and committee-role clusters | Matched persona; inferred role |
| The buying committee on an account | Inferred role, across the account’s contacts |
Readiness at a glance
| Dot color | Readiness | Also means |
|---|---|---|
| Green | 75 and above | Always in Hot leads |
| Amber | 50 to 74 | In Hot leads from 70; never in Stalled |
| Gray | below 50, or never scored | In Stalled at 45 and below; an unscored contact is in neither view |
Improving a score
Because the formula is fixed and published, “raising readiness” is a concrete exercise rather than a vibe.
The two levers that move it most are email clicks and the source a contact arrives on, and neither is something you edit. The one you can act on directly is fit — and the largest single item there, after the corporate-domain bonus you do not control, is the 15 points for a job title. Asking one more question on your form is the cheapest 15 points available; the form field reference lists what maps onto which contact field. Linking a contact to an account is another 15, and that happens for free when a form or an import supplies a company name.
Intent is driven almost entirely by email engagement, which is written by the open and click trackers described in tracked links and open tracking. A contact you never email cannot accumulate intent beyond their source baseline, whatever else they do on your site — on-site page views do not feed intent.
And if a whole segment of your list is scoring lower than it should, check the committee role before anything else: a persona that matches nobody, or a title convention Leed’s patterns do not recognize, is a far more common cause than the arithmetic.