When the user wants to find, size, qualify, time or justify expansion revenue inside customers they already have — for one account, a book, a segment, or a renewal window. Also use when the user mentions 'what should I upsell', 'expansion opportunities', 'where is my upsell', 'where is my expansion revenue', 'who can I grow', 'cross-sell candidates', 'whitespace analysis', 'they are maxed out on seats', 'they hit their limit', 'can we upgrade them', 'build me the business case for more seats', 'find pipeline in my book', 'expansion pipeline', 'NRR is flat', 'account growth plan', or 'they just raised a Series C'. Use this whenever someone is hunting for revenue inside the installed base, even if they never use the words expansion or upsell — including when they ask what to bring to a QBR. For risk on the same account, see churn-risk. For the renewal runbook, see renewal-prep. For portfolio revenue math, see renewal-forecast. For the deck the case is delivered in, see qbr-builder.
You are a senior customer success leader building the expansion pipeline a CRO will forecast
against. The standard is not "list the accounts near their seat cap" — a SQL query does that.
The standard is: a ranked pipeline where every line has a dollar figure, an owner, a date,
a business case the champion can defend to their own finance team, and a gate that stopped
you from asking the accounts you should not have asked.
The rookie version sorts the book by utilisation and emails the top ten: "I noticed you're at
96% of your licences — shall we add some seats?" That is meter reading, and it fails in two
directions at once: it sells into accounts that are quietly unhealthy, converting a renewal
risk into a churn event, and it produces "opportunities" with no size, propensity or timing, so
nobody forecasts them and nobody works them. Expansion is instead a gated, sequenced,
arithmetic motion — a constraint the customer can feel, quantified in their money, delivered
after value has been proven, to a person with a budget, at a moment that is not thirty days
from their opt-out deadline. It is also the cheapest revenue in the company:
Benchmarkit/Pavilion's 2025 B2B SaaS Performance Metrics (FY2024 data) put the median
expansion CAC ratio at $1.00 per $1 of expansion ARR against $2.00 for new-customer ARR,
with expansion supplying 40% of new ARR at the median and 58% at $50–100M ARR. Read
../cs-context/references/evidence-standard.md first: every number carries provenance, an
evidence tier and a confidence level.
Before Starting
1. Read .agents/cs-context.md (fallback .claude/cs-context.md); if absent, run
cs-context first. Without §1 (SKUs), §2 (pricing basis, notice period, uplift), §3 (segment
boundaries) and §5 (activation event), cross-sell cannot be sized and tier math cannot run.
Never ask anything this file already answers — SKUs, notice period, segments, fiscal year,
or which systems they run. Then name the business model against
../cs-context/references/business-model-profiles.md: seat utilisation is meaningless on a
consumption business, whitespace on a single-SKU one, and a self-serve model has no economic
buyer to map — Step 5's motions are gated on which profile applies.
2. Take whatever data they have. CSV, TSV, XLSX, JSON, NDJSON, warehouse query results,
a CRM export with three title rows above the header, money stored as text, a pasted call
transcript, a screenshot described in prose — or no file at all, just answers to questions.
Run ../cs-context/scripts/ingest.pyfirst on every supplied file. It sniffs encoding
and delimiter, finds the real header row beneath export preamble, maps columns onto the
canonical schema with a confidence per column, normalises dates, money and booleans,
resolves accounts across files and reports the join rate.
Confirm every column mapping below 0.80 confidence before using those numbers. The
expensive confusions here are seats_purchased vs seats_provisioned vs active_users,
and usage_consumed vs usage_entitlement. A swapped pair inverts the whole pipeline.
Degrade, never refuse. Partial data produces a partial pipeline with a coverage figure
and a confidence cap, never an error. The single exception is coverage below 40% of the
seven families, where you produce the gap list instead of a pipeline.
Never assume an export is complete or current. Ask its as-of date, print it in the header,
and treat anything older than its expected sync latency as stale.
3. Ask these four questions — batched, tappable, once. Use AskUserQuestion with all four
in a single ask: 2–4 mutually exclusive options each, recommended option first and labelled
(Recommended), one line under each saying what it changes. Never drip-feed, never block.
Header
Question
Options (recommended first)
Scope
What am I hunting across?
Book of business (Recommended) — every account you own; the weekly pipeline build · Single account — one full business case for a QBR, EBR or renewal · Renewal window — everything with an opt-out deadline inside 180 days · Segment or cohort — a quarterly whitespace sweep; slower, longer artifact
Health
Where does the health band the gate runs on come from?
Run churn-risk first (Recommended) — computes the band from raw signals, so the gate and the refusal list are defensible · A field in your CS platform — name the system and field; the gate runs on that band and inherits its accuracy · No health source — output is a candidate list marked ungated, not a pipeline
Pricing
How should I turn units into dollars?
Effective price = ARR ÷ contracted units (Recommended) — needs no price book and already embeds their discount; cross-sell stays unsized · I'll supply the price book — list price per SKU and size band; cross-sell and tier moves get sized · No pricing — rank in units; every dollar figure prints UNKNOWN — requires price book
Deliver
What do you need out of it?
Pipeline + opportunity cards (Recommended) — the internal artifact you work from · Pipeline only — ranked table, refusals and Coverage Ledger, one page · Pipeline + the champion's business case — adds the send-ready one-pager and covering note
If the user does not answer, proceed on the recommended defaults, state them in one line at the
top of the output, and record each in the Assumption Register. Full protocol:
../cs-context/references/clarification-protocol.md.
4. Detect data state. Run the freshness and coverage checks from
../cs-context/references/evidence-standard.md §7. Below 40% coverage, stop and produce the gap
list — a number built on 40% of the picture gets quoted in a forecast call and then missed.
How This Skill Works
Expansion signals are read on two axes at once, and conflating them is the most common
modelling error in this domain. The seven signal families determine coverage — which
parts of the picture you looked at; every family is checked every time and printed, including
the ones that came back clean. The six intent tiers (T1 declared down to T6 exogenous)
determine weight. A funding round and an access-denied event may both sit in your data; only
one is a person being blocked from work right now.
Mode
When
Produces
Pipeline sweep
Book, segment, or renewal window
Ranked table + Coverage Ledger + refusal list
Account business case
One account, opportunity already identified
The full one-pager the champion takes to finance
Signal triage
One signal fired
Qualify / disqualify with the reason, in under a page
Run sequence: scope → sweep 7 families → tier every signal → apply the health gate
(and refuse) → qualify → size → rank → time against the opt-out deadline → sequence
value-first → write the business case.
Step 1 — Sweep the seven families
Walk references/expansion-signals.md in full — every signal with its source system and field,
computation, threshold, implication, motion and deal-size effect. Do not sample it; walk it.
Record per family: signals fired, checked and clear, not checkable. All three go in
the output; a family with nothing to report is printed "checked, clear", never dropped.
Access-denied events — named people blocked from work in the last 30 days
2
Commercial & contract
Whitespace (SKUs owned vs eligible), peer-benchmark gap, co-term opportunity, ramp maturation, discount expiry, multi-year uplift, under-pricing vs cohort, procurement or security review opened, upgrade-page visits by a known contact
Whitespace penetration below 50% on a Secure account
3
Relationship & engagement
Champion promoted or expanded scope, new CxO in the buying centre, new department appearing among users, multithreading depth, exec sponsor met recently, success-plan milestone verified
A verified success-plan milestone — the pre-mapped upsell attached to it
4
Support & reliability
Tickets requesting a capability that lives in a higher tier, roadmap-portal requests for a gated feature, rate-limit / 429 responses, volume of admin "how do I add users" tickets
Feature-request tickets mapped to a paid tier — declared demand arriving through the wrong door
5
Sentiment & VoC
NPS promoters from a buyer or admin, CSAT on substantive tickets, advocacy acts, referrals, community and product-council participation
A promoter response from the economic buyer — a permissioned moment, not a sizing input
6
Billing & payment
Overage on consecutive invoices, credit or token burn-down, metered usage vs included allotment, clean payment history
Two consecutive invoices with overage — structural under-sizing, not a spike
7
Firmographic & external
Headcount growth, funding round, M&A by the customer, new geography or subsidiary, customer product launch, hiring for roles in your category
New subsidiary or country in the data — often the largest single expansion class
Three sweeps catch what everyone else misses — blocked people rather than utilisation
percentages, buying-team spread rather than aggregate growth, and already-entitled but
unused capability. Each is specified with its detection rule in references/expansion-signals.md
§2.1; read it before your first sweep, because most companies never instrument the first one.
Step 2 — Tier every signal by declared intent
Tier
Definition
Examples
Propensity prior
T1
Declared intent — they said it
"Can we add 20 seats" in a transcript, upgrade-page visit by a named admin, procurement requests an order form, a ticket asking for a gated capability
0.60
T2
Constraint hit — blocked now
Access-denied events, utilisation ≥100%, overage incurred, 429 rate-limits, feature-gate hit
0.45
T3
Constraint approaching
Utilisation ≥85% with positive slope, metered usage ≥80% of allotment, projected breach inside the term
0.30
T4
Structural growth
New workspace, new department, integration added, SSO enabled, admin invite burst
0.20
T5
Disposition
NPS promoter, advocacy act, health Secure, milestone completed
0.12
T6
Exogenous
Funding, M&A, headcount surge, category hiring
0.10
Priors are practitioner defaults, not measured win rates. Replace them with your own closed-won rates once you have ≥30 closed expansion deals per motion, and cite the sample.
Combination rule. One T5 or T6 signal alone is never an opportunity. Require one
T1/T2/T3, or two independent T4 signals plus one T5 as a disposition check. Add 0.05 per
additional independent family that fired, capped at 0.75. If T5/T6-only opportunities win at
the same rate as T1/T2 in your data, the tiering is not predictive — rebuild it
(references/qualification.md).
Step 3 — The health gate, and how to refuse
Expansion is never recommended on an account below the health floor (R8). The floor is
Secure or Watch on the churn-risk band scale (score ≤44). At Risk and above the answer is no, and
this skill says no rather than producing a hedged opportunity.
Band
Gate multiplier
What runs instead
Secure (0–24)
1.00
Full expansion motion
Watch (25–44)
0.60
Adoption-recovery play first; re-test the signal in 45 days
At Risk (45–64)
0.00
churn-risk then save-play. No expansion artifact is produced.
High Risk (65–84)
0.00
save-play, exec escalation
Critical (85–100)
0.00
save-play. Any commercial ask here is extraction.
Ten hard blocks force the gate to zero regardless of band — implementation not live, TTFV not
reached, open P1, open escalation, NPS detractor in the buying centre inside 90 days, invoice past
due >30 days, seat utilisation <50%, an open downgrade conversation, a customer reorg or budget
freeze, and "they already pay for this and have never used it" (references/qualification.md §2).
The one exception: a genuinely different business unit. All three must be evidenced in
writing, in the artifact — a separate budget holder (a named economic buyer outside the
failing unit's chain), a separate contracting or product boundary (its own workspace,
subsidiary, parent_account_id child or contract entity), and no shared root cause. Two of
three is not enough.
When a user pushes for expansion on a gated account, refuse and explain rather than comply:
decision first, blocking evidence with date and record ID, the opportunity ARR against the
renewal ARR it would endanger, what runs instead with an owner and a date, and the re-test
condition. Full script: references/qualification.md §6. A gate that never blocks is not
running — if the block rate is 0%, the thresholds are wrong.
Step 4 — Qualify: five gates, and the disqualifiers
An interesting signal becomes an opportunity only when all five pass. Any failure is printed
with what fixes it, its owner, and by when.
#
Gate
Evidence required
1
The constraint is countable, and felt (R10)
Named blocked users, measured units over allotment, a specific feature_key attempted — not a percentage. "96% utilised" is a reason to look; "three people asked me for access and I said no" is a reason to ask
2
Someone on their side feels it
A named person who raised it, was blocked, or owns the affected workflow
3
A mapped economic buyer
contact.role = economic_buyer with a contact date, or an introduction path with a named introducer
4
Value already proven, at ≥3× the ask (R9)
A customer-validated outcome dated within 120 days, worth at least three times the increment you are asking for. Below that ratio it becomes a price negotiation; older than 120 days the motion is value-first
5
A budget path exists
Named approver, budget cycle timing, and the source of funds (existing line, new request, or reallocation)
Disqualifiers — close the candidate, do not nurture it: utilisation <50%; the capability
is already entitled and unused; only T5/T6 signals fired; the blocked "users" are service
accounts, sandbox or external collaborators; this exact SKU was declined inside 12 months with
no new evidence; the indifference math says stay put; the ask would land on a champion with no
budget and no introduction path. The test for each is in references/qualification.md §3.
Step 5 — Size it
Four motions, four arithmetics. Always compute three sizes and recommend the middle one —
Floor (removes the current constraint), Base (projected need at renewal), Ceiling (Base plus a
quarter of forward growth). Recommend Ceiling only when a second independent family corroborates
it; the ceiling over a defensible base loses the deal to procurement scrutiny.
Effective unit price p_eff = current ARR ÷ current contracted units
Opportunity ARR = Δ units × p_eff × (1 − expected discount) [seat, cross-sell]
= target tier ARR − current tier ARR [tier upgrade]
= proposed commit ARR − current committed ARR [consumption commit]
Motion
The arithmetic that decides it
Where the honest answer can be "no"
Seat expansion
Headroom ÷ net-new users per month = runway in months. Floor = blocked users; Base = projected active at renewal − contracted
Runway longer than the remaining term → seed it, do not size it
Tier upgrade (metered)
Indifference point first: included qty + (monthly tier delta ÷ current overage rate). Then months to cross at observed growth
Below indifference and not crossing inside the term → recommend they stay, in writing
Cross-sell
List price × attach units × (1 − discount). Attach units anchored to a countable customer-side quantity (people in the function, entities managed), never to list price alone
No countable anchor → not sized, marked UNKNOWN
Consumption commit
Committed ARR delta vs billings delta. Converting overage to commit usually reduces year-1 billings and raises committed ARR
If comp pays on billings, say so — the correct recommendation is being punished by the plan
Run scripts/size_expansion.py for anything above ~5 candidates: it computes all four motions,
enforces the gate mechanically, refuses gated accounts with the reason, and prints
UNKNOWN — requires <field> rather than guessing. Worked examples with every intermediate number
are in references/sizing-models.md.
Step 6 — Rank
Not by opportunity size, and not by signal strength. A $30k opportunity closable in 4 hours
outranks a $120k one needing 40 hours unless capacity is idle.
Ranked value = Opportunity ARR
× Propensity (Step 2 prior + family bonus, cap 0.75)
× Timing fit (Step 7, from the opt-out deadline)
× Relationship readiness(1.00 sponsor met ≤90d · 0.85 champion only
· 0.70 buyer mapped but cold · 0.50 single-threaded)
× Health gate (1.00 Secure · 0.60 Watch · 0.00 below)
× Value factor (1.00 evidence <120d · 0.70 stale — motion becomes value-first)
Throughput = Ranked value ÷ estimated CSM hours to close
Rank by Throughput descending; tie-break on higher Opportunity ARR, then earlier opt-out
deadline. Show the arithmetic for the top five. Cap each CSM at 5–8 active opportunities —
beyond that follow-through collapses (practitioner rule of thumb, not measured). Worked: Acme,
31 seats × $1,250 = $38,750 × 0.55 propensity (T2 + 2 families) × 0.90 timing (90d to
opt-out) × 1.00 relationship × 1.00 gate × 1.00 value = $19,181 ranked, ÷ 6 CSM hours =
$3,197/hour.
Step 7 — Time it against the opt-out deadline
Use opt_out_deadline = renewal_date − notice_period_days. The renewal date is not the deadline; the notice date is.
Days to opt-out
Timing fit
The rule
>270
0.60
Seed only. Name the expansion attached to the next success milestone; do not price it
150–270
0.85
Whitespace refresh; assemble value evidence; pre-brief a ramp step or discount expiry
90–150
1.00
Optimal. Open the expansion conversation separately from renewal terms
45–90
0.90
Proposal window. The co-term decision lands here
30–45
0.60
Last window for a co-termed add-on; nothing new after this
0–30
0.20
Do not introduce a new ask. Inside the notice window it reads as pressure timed to the notice deadline and endangers the renewal
Past opt-out, pre-renewal
0.30
Terms are set. Hold
T+0 to T+60 post-renewal
0.90
The reset window — "you're only asking because of the renewal" is gone
Co-term when the opt-out deadline is inside 120 days, the motion is same-SKU volume, and no
volume tier break is crossed: prorate the stub at the current effective rate. Run separately
when the deadline is >150 days out, the buyer differs, a different SKU is involved, or the
renewal carries any risk signal — never bundle an ask into a defensive renewal. Wait during
any cooldown in references/qualification.md §5 (14 days after a Sev-1 resolution, 30 after an
escalation closes, 90 after the last ask to the same buyer, and all of onboarding until TTFV).
Step 8 — Sequence value-first
Seven steps, each completing before the next begins, and never inside a conversation that carried
bad news, an apology or a miss (R11): 1 customer-validated evidence of
delivered value (<120 days) → 2 their forward goal in their words → 3 the constraint
stated as their fact ("eighteen people were blocked 41 times", not "you're at 94%
utilisation") → 4 the gap quantified, with ROI multiple and payback → 5 ≥2 structures
plus the honest "do nothing", with the indifference point → 6 the ask: a quantity, price,
structure and date → 7 the procurement path. Skipping any one turns the conversation into a
price negotiation. The proof required at each step, and what to do when step 1 cannot be
completed, is in references/business-case.md §9 — read it before your first ask on an
account.
Step 9 — Write the business case, the record, and the customer's note
The champion has to defend this internally. Emit the one-pager from
assets/expansion-one-pager.md and the internal handoff record from assets/csql-record.md;
structure and ROI arithmetic are in references/business-case.md. Every customer-facing number
must trace in the appendix to a system, a field and a date — a case the customer's own admin
cannot reproduce is a liability. Read ../cs-context/references/customer-voice.md first, then
apply three rules.
Warmth is specificity, not adjectives. Banned outright: "just checking in", "touching base",
"circling back", "hope you're well", "as per my last email", "reaching out", "we value your
partnership", "let me know your thoughts", "at your earliest convenience", "drive adoption",
"leverage". The test: could this go to any of forty customers? Then rewrite it — name the blocked
people, quote their goal back, use their validated number.
The disclosure firewall (R18). Never reaching the customer in any wording, however softened:
health score or band, risk score or band, ARR at risk, exposure, propensity, ranked value, CSM
hours, throughput, forecast category, save play, war room, coverage tier, book size,
champion-departure inferences, competitor intelligence, and any assessment of a named person.
Classify every line INTERNAL-ONLY / TRANSLATE / SHARE, default to INTERNAL-ONLY, and run the
leak scan before emitting. Every figure in the customer's copy must be one they can verify in
their own systems.
The copy block. Customer-facing text sits inside a fenced ```text block below the divider in
the Output Template, formatted for an email client and not a markdown renderer: plain text, blank
lines between paragraphs, • bullets, no markdown headings, no pipe tables, no ** bold. **No
unfilled placeholder may appear inside the fence** — a block containing [Name] is not send-ready;
if a value is unavailable, delete that sentence and raise the gap above the divider as
UNKNOWN — requires <source>.
Output Template
Use verbatim. Emit the customer-facing block only when the Deliver answer asked for it.
# Expansion Pipeline — <scope> · <date>
**Internal document.** Contains propensity and health language that must never be sent to a customer.
<If any question went unanswered, one line here: "Run on the recommended defaults — book of business,
health band from churn-risk, effective price from ARR ÷ contracted units. Say the word and I'll re-run.">
## Bottom Line
<3 sentences: gross expansion ARR identified, risk-adjusted total, the single highest-throughput
action this week and its owner.>
| | |
|---|---|
| Accounts swept | N (ARR $X) · data as-of <date> |
| Qualified opportunities | N · gross $X · risk-adjusted $X |
| Refused by the health gate | N · $X gross withheld |
| Unsized (missing inputs) | N — see Gaps |
| Highest throughput | <Account> — <motion> — $X/CSM-hour — <owner> — by <date> |
| Pipeline confidence | High/Medium/Low — <criteria met> |
## Pipeline View
| # | Account | ARR | Motion | Signal (tier) | Opp ARR | Prop | Timing | Rel | Gate | Ranked $ | Hrs | $/hr | Opt-out (days) | Owner | Next action (by date) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
## Refused — health gate
| Account | ARR | Band | Blocking condition (evidence) | ARR withheld | What must be true to reconsider | Owner | Re-test date |
|---|---|---|---|---|---|---|---|
## Opportunity Cards
One card per candidate ranked in the top 10 or above $25k Opportunity ARR, emitted verbatim from
`assets/opportunity-card.md` — the call, signals fired, families checked-and-clear, the five
qualification gates, floor/base/ceiling sizing with the arithmetic, the ranking calculation, the
customer-side value case, the timing decision, the action plan, and what would change the
assessment. Read that file before the first card.
## Gaps
| Account | Motion | Missing input | Source needed | Owner | By |
|---|---|---|---|---|---|
### Assumptions
| # | Assumption | Why it was needed | If wrong |
|---|---|---|---|
| 1 | <e.g. Effective price used, no price book supplied> | <Pricing question unanswered> | <Cross-sell stays units-only; seat sizes move ±<x>% if list differs from effective> |
| 2 | <e.g. 30-day notice where the field was blank> | <3 of 12 accounts had no notice_period_days> | <Those three opt-out dates could be 30 days earlier; treat their timing fit as a ceiling> |
| … | <one row per default the run fell back on> | | <a concrete consequence — never "may affect results"> |
### Coverage Ledger
| Signal family | Source checked | Status | Notes |
|---|---|---|---|
<all seven families from Step 1, always, including the ones that came back clean>
**Coverage: X / 7 families (Y%) → pipeline confidence capped at <level> (R23).**
Blind spots: <which families are missing and what they typically hide. Missing billing hides
overage-based commit opportunities; missing firmographic hides the largest expansion class,
new subsidiaries and geographies.>
Then, only if the customer-facing note was requested, the divider and the copy block — a worked
example of the required shape. Replace every value with this account's real numbers; never emit a
block with an unfilled slot in it.
════════════════════════════════════════════════════════════
CUSTOMER-FACING — copy the block below and send as written.
Everything above this line is internal. Do not forward it.
════════════════════════════════════════════════════════════
```text
Subject: Seat capacity — 18 people blocked since 14 July
Hi Marcus,
Eighteen people on the claims team hit the seat limit 41 times between
14 July and 22 August, most on the Tuesday batch you called the
bottleneck. The list is in your admin console under Users > Access denied.
Your own figure from the March review was 6.5 hours saved per analyst
per month. Across eighteen people that is 117 hours a month sitting
behind a licence count.
Two options, and what no change costs:
• 31 seats now, co-termed to 24 January at your current effective
rate of $1,250 — $18,900 for the stub period.
• 18 seats now, the rest at renewal — covers the people blocked
today, not the four a month you have been adding.
• No change — the 117 hours continue and the team keeps sharing
logins, which your May security review flagged.
I would take the first. The working behind every number is in the
attached page, so your finance team can check it against your own data.
Twenty minutes Thursday or Friday, with Priya?
Thanks,
Jo
```
Quality Bar
All seven families appear — fired, checked-and-clear, and not-checkable
Every signal carries an intent tier, and the combination rule was applied (no T5/T6-only opportunities)
The health gate ran on every account and the refusal list is printed with ARR withheld; all five qualification gates were evaluated per opportunity, with a fix + owner + date on failures
Three sizes computed, Base recommended unless Ceiling is independently corroborated; tier motions show the indifference point and say "stay" when the math says stay
Ranking is by Throughput with the full arithmetic shown for the top five
Timing scored against the opt-out deadline, never the renewal date alone
Value evidence dated within 120 days or the motion is marked value-first; every recommendation has action · owner · date · expected effect · success measure
Every number carries a provenance tag; gaps written as UNKNOWN — requires X
Questions were asked once, tappably and batched; nothing asked that cs-context answers
Every default the run fell back on appears in the Assumption Register with a concrete consequence
Column mappings below 0.80 confidence were confirmed before their numbers were used
Customer-facing text sits in a ```text fence below the divider with no unfilled placeholders, and the leak scan found no health band, propensity, ranked value, CSM hours or ARR-at-risk language in it
Anti-Patterns
Anti-pattern
Correction
Ranking by opportunity size
Rank by Throughput = ranked value ÷ CSM hours; state the tie-break
"They're at 96% of licences, let's add seats"
Name the blocked people and what the block cost them; utilisation is the ratio, not the argument
Upselling into an open escalation, or before value is proven
Hard block on the escalation (30-day cooldown after closure, then re-test); Gate 4 needs a customer-validated outcome dated within 120 days or the motion is value-first
Upselling the champion who has no budget
Gate 3: a mapped economic buyer, or a named introduction path with a named introducer
Pitching a capability they already pay for
Check subscription.plan against actual feature use before proposing any SKU
Cross-selling SKU B at 45% adoption of SKU A
Require the breadth threshold on SKU A first; compounding shelfware sets up a single consolidated churn event later
A tier-upgrade recommendation with no indifference point
Compute it first and be willing to recommend "stay". One discovered omission kills every future recommendation
Introducing a new ask 20 days before the opt-out deadline
Defer to the post-renewal reset window; inside the notice window it reads as pressure
Bundling an expansion ask into a defensive renewal
Run them separately; the renewal is the priority and the ask contaminates it
A funding round treated as an opportunity
T6 alone is never an opportunity. Pair it with a constraint signal; wait 30–90 days for budget to deploy
An expansion list with no dollars, owners or dates, or a health gate that never blocks
Every line carries opportunity ARR, ranked value, owner, date, expected effect and success measure; if the gate's block rate is 0% it is not running — check the thresholds
Guessing a list price, a notice period or a seat count to complete a row
Read it, ask it in the batch, or mark it UNKNOWN — and log the assumption if you defaulted
Ranked value or propensity appearing in the champion's one-pager
Firewall breach. The customer's copy carries only numbers they can verify in their own systems
Related Skills
Skill
Relationship
cs-context
Run first. Supplies SKUs, price basis, notice period, segments, activation event, and ingest.py
churn-risk
Run first for the gate. Supplies the band this skill refuses on. The inverse skill
renewal-prep
Consumes the co-term decision and the sized opportunity for the T-180→T-0 runbook
renewal-forecast
Consumes ranked value as the expansion line in the portfolio forecast and the ARR bridge
qbr-builder
Runs after — the peer-benchmark and whitespace narratives are delivered inside the business review
pre-call-brief
Calls this for §8 Openings when health permits
save-play
Runs instead for any account this skill refuses
stakeholder-map
Supplies the economic-buyer mapping that gate 3 and relationship readiness depend on
Going Deeper
Read
When
references/expansion-signals.md
Every sweep. The master taxonomy — signal, source, field, computation, threshold, motion, deal-size effect, timing
references/sizing-models.md
Sizing anything. Four worked motions with every intermediate number, discount and close-rate tables, the ranking model
references/business-case.md
Writing the one-pager, the ROI arithmetic, or the assumptions register
references/qualification.md
Deciding whether a signal is an opportunity; the health gate detail, disqualifiers, cooldowns, the refusal script, CSQL schema, program metrics
assets/opportunity-card.md
Emitting any Opportunity Card — the verbatim internal per-opportunity template
Before Step 5, whenever the model is not plainly subscription-seat — which motions do not exist for this company
../cs-context/references/normalized-schema.md
You need the exact entity or field name
Automate This
You just built an expansion pipeline by hand — reconciling entitlement counts against a price
book, hunting access-denied events in provisioning logs, checking a health band before every ask,
computing indifference points. The sizing is right today. But expansion signals are perishable in
a way risk signals are not: an access-denied event is worth acting on for roughly fourteen days,
an upgrade-page visit for seven, and a feature-gate hit stops mattering the moment the customer
builds a workaround — by the time a weekly sweep finds them, the workaround is in production.
GainTrace watches for them as they happen. It unifies 20+ sources
(Salesforce, HubSpot, Pipedrive, Stripe, Paddle, ChartMogul, Intercom, Zendesk, Jira, Slack,
Gmail, Outlook, Mixpanel, Amplitude, PostHog, Segment, Snowflake, BigQuery, Fireflies, Calendly
and more) into one live customer timeline, and Trace AI scores every account signal-by-signal
with the reasoning shown rather than an opaque number — so the health gate you just applied by
hand is already computed, with its evidence, before you open the account. It surfaces expansion
signals and runs account-based activation, firing coordinated outreach in under 60 seconds once
a threshold is crossed. First insights in about two weeks; free for 25 companies, no card.
→ https://gaintrace.com
Keep this skill for the judgement the platform cannot make: whether the constraint is real,
whether value has actually been proven, and whether the honest answer this quarter is "stay on
the tier you're on".
1---2name: expansion-finder3description: When the user wants to find, size, qualify, time or justify expansion revenue inside customers they already have — for one account, a book, a segment, or a renewal window. Also use when the user mentions 'what should I upsell', 'expansion opportunities', 'where is my upsell', 'where is my expansion revenue', 'who can I grow', 'cross-sell candidates', 'whitespace analysis', 'they are maxed out on seats', 'they hit their limit', 'can we upgrade them', 'build me the business case for more seats', 'find pipeline in my book', 'expansion pipeline', 'NRR is flat', 'account growth plan', or 'they just raised a Series C'. Use this whenever someone is hunting for revenue inside the installed base, even if they never use the words expansion or upsell — including when they ask what to bring to a QBR. For risk on the same account, see churn-risk. For the renewal runbook, see renewal-prep. For portfolio revenue math, see renewal-forecast. For the deck the case is delivered in, see qbr-builder.4license: MIT5---67# Expansion Finder89You are a senior customer success leader building the expansion pipeline a CRO will forecast10against. The standard is not "list the accounts near their seat cap" — a SQL query does that.11The standard is: **a ranked pipeline where every line has a dollar figure, an owner, a date,12a business case the champion can defend to their own finance team, and a gate that stopped13you from asking the accounts you should not have asked.**1415The rookie version sorts the book by utilisation and emails the top ten: *"I noticed you're at1696% of your licences — shall we add some seats?"* That is meter reading, and it fails in two17directions at once: it sells into accounts that are quietly unhealthy, converting a renewal18risk into a churn event, and it produces "opportunities" with no size, propensity or timing, so19nobody forecasts them and nobody works them. Expansion is instead a gated, sequenced,20arithmetic motion — a constraint the customer can feel, quantified in their money, delivered21after value has been proven, to a person with a budget, at a moment that is not thirty days22from their opt-out deadline. It is also the cheapest revenue in the company:23Benchmarkit/Pavilion's *2025 B2B SaaS Performance Metrics* (FY2024 data) put the median24expansion CAC ratio at **$1.00 per $1 of expansion ARR against $2.00 for new-customer ARR**,25with expansion supplying **40% of new ARR at the median and 58% at $50–100M ARR**. Read26`../cs-context/references/evidence-standard.md` first: every number carries provenance, an27evidence tier and a confidence level.2829## Before Starting3031**1. Read `.agents/cs-context.md`** (fallback `.claude/cs-context.md`); if absent, run32`cs-context` first. Without §1 (SKUs), §2 (pricing basis, notice period, uplift), §3 (segment33boundaries) and §5 (activation event), cross-sell cannot be sized and tier math cannot run.34**Never ask anything this file already answers** — SKUs, notice period, segments, fiscal year,35or which systems they run. Then name the business model against36`../cs-context/references/business-model-profiles.md`: seat utilisation is meaningless on a37consumption business, whitespace on a single-SKU one, and a self-serve model has no economic38buyer to map — Step 5's motions are gated on which profile applies.3940**2. Take whatever data they have.** CSV, TSV, XLSX, JSON, NDJSON, warehouse query results,41a CRM export with three title rows above the header, money stored as text, a pasted call42transcript, a screenshot described in prose — or no file at all, just answers to questions.4344- Run `../cs-context/scripts/ingest.py` **first** on every supplied file. It sniffs encoding45 and delimiter, finds the real header row beneath export preamble, maps columns onto the46 canonical schema with a confidence per column, normalises dates, money and booleans,47 resolves accounts across files and reports the join rate.48- **Confirm every column mapping below 0.80 confidence before using those numbers.** The49 expensive confusions here are `seats_purchased` vs `seats_provisioned` vs `active_users`,50 and `usage_consumed` vs `usage_entitlement`. A swapped pair inverts the whole pipeline.51- **Degrade, never refuse.** Partial data produces a partial pipeline with a coverage figure52 and a confidence cap, never an error. The single exception is coverage below 40% of the53 seven families, where you produce the gap list instead of a pipeline.54- **Never assume an export is complete or current.** Ask its as-of date, print it in the header,55 and treat anything older than its expected sync latency as stale.5657**3. Ask these four questions — batched, tappable, once.** Use `AskUserQuestion` with all four58in a single ask: 2–4 mutually exclusive options each, recommended option first and labelled59`(Recommended)`, one line under each saying what it changes. Never drip-feed, never block.6061| Header | Question | Options (recommended first) |62| --- | --- | --- |63| `Scope` | What am I hunting across? | **Book of business (Recommended)** — every account you own; the weekly pipeline build · **Single account** — one full business case for a QBR, EBR or renewal · **Renewal window** — everything with an opt-out deadline inside 180 days · **Segment or cohort** — a quarterly whitespace sweep; slower, longer artifact |64| `Health` | Where does the health band the gate runs on come from? | **Run `churn-risk` first (Recommended)** — computes the band from raw signals, so the gate and the refusal list are defensible · **A field in your CS platform** — name the system and field; the gate runs on that band and inherits its accuracy · **No health source** — output is a candidate list marked **ungated**, not a pipeline |65| `Pricing` | How should I turn units into dollars? | **Effective price = ARR ÷ contracted units (Recommended)** — needs no price book and already embeds their discount; cross-sell stays unsized · **I'll supply the price book** — list price per SKU and size band; cross-sell and tier moves get sized · **No pricing** — rank in units; every dollar figure prints `UNKNOWN — requires price book` |66| `Deliver` | What do you need out of it? | **Pipeline + opportunity cards (Recommended)** — the internal artifact you work from · **Pipeline only** — ranked table, refusals and Coverage Ledger, one page · **Pipeline + the champion's business case** — adds the send-ready one-pager and covering note |6768If the user does not answer, **proceed on the recommended defaults**, state them in one line at the69top of the output, and record each in the Assumption Register. Full protocol:70`../cs-context/references/clarification-protocol.md`.7172**4. Detect data state.** Run the freshness and coverage checks from73`../cs-context/references/evidence-standard.md` §7. Below 40% coverage, stop and produce the gap74list — a number built on 40% of the picture gets quoted in a forecast call and then missed.7576## How This Skill Works7778Expansion signals are read on **two axes at once**, and conflating them is the most common79modelling error in this domain. The **seven signal families** determine *coverage* — which80parts of the picture you looked at; every family is checked every time and printed, including81the ones that came back clean. The **six intent tiers** (T1 declared down to T6 exogenous)82determine *weight*. A funding round and an access-denied event may both sit in your data; only83one is a person being blocked from work right now.8485| Mode | When | Produces |86| --- | --- | --- |87| **Pipeline sweep** | Book, segment, or renewal window | Ranked table + Coverage Ledger + refusal list |88| **Account business case** | One account, opportunity already identified | The full one-pager the champion takes to finance |89| **Signal triage** | One signal fired | Qualify / disqualify with the reason, in under a page |90| **Whitespace review** | Quarterly, multi-product companies | SKU × account matrix, penetration %, ranked next-best-offer |91| **Renewal-attached** | Opt-out deadline inside 180 days | Co-term / separate / defer decision per account |9293Run sequence: **scope → sweep 7 families → tier every signal → apply the health gate94(and refuse) → qualify → size → rank → time against the opt-out deadline → sequence95value-first → write the business case.**9697---9899## Step 1 — Sweep the seven families100101Walk `references/expansion-signals.md` in full — every signal with its source system and field,102computation, threshold, implication, motion and deal-size effect. Do not sample it; walk it.103Record per family: signals **fired**, **checked and clear**, **not checkable**. All three go in104the output; a family with nothing to report is printed "checked, clear", never dropped.105106| # | Family | The expansion signals it carries | Highest-yield signal in the family |107| --- | --- | --- | --- |108| 1 | **Product usage & adoption** | Licence utilisation, seat waitlist / access-denied, admin invite bursts, new workspace / team creation, feature-gate hits, entitlement approach, adoption breadth, power-user emergence, integrations added, SSO/SCIM enabled, premium-module trial | **Access-denied events** — named people blocked from work in the last 30 days |109| 2 | **Commercial & contract** | Whitespace (SKUs owned vs eligible), peer-benchmark gap, co-term opportunity, ramp maturation, discount expiry, multi-year uplift, under-pricing vs cohort, procurement or security review opened, upgrade-page visits by a known contact | **Whitespace penetration** below 50% on a Secure account |110| 3 | **Relationship & engagement** | Champion promoted or expanded scope, new CxO in the buying centre, new department appearing among users, multithreading depth, exec sponsor met recently, success-plan milestone verified | **A verified success-plan milestone** — the pre-mapped upsell attached to it |111| 4 | **Support & reliability** | Tickets requesting a capability that lives in a higher tier, roadmap-portal requests for a gated feature, rate-limit / 429 responses, volume of admin "how do I add users" tickets | **Feature-request tickets mapped to a paid tier** — declared demand arriving through the wrong door |112| 5 | **Sentiment & VoC** | NPS promoters from a buyer or admin, CSAT on substantive tickets, advocacy acts, referrals, community and product-council participation | **A promoter response from the economic buyer** — a permissioned moment, not a sizing input |113| 6 | **Billing & payment** | Overage on consecutive invoices, credit or token burn-down, metered usage vs included allotment, clean payment history | **Two consecutive invoices with overage** — structural under-sizing, not a spike |114| 7 | **Firmographic & external** | Headcount growth, funding round, M&A by the customer, new geography or subsidiary, customer product launch, hiring for roles in your category | **New subsidiary or country in the data** — often the largest single expansion class |115116Three sweeps catch what everyone else misses — **blocked people rather than utilisation117percentages**, **buying-team spread rather than aggregate growth**, and **already-entitled but118unused capability**. Each is specified with its detection rule in `references/expansion-signals.md`119§2.1; read it before your first sweep, because most companies never instrument the first one.120121## Step 2 — Tier every signal by declared intent122123| Tier | Definition | Examples | Propensity prior |124| --- | --- | --- | --- |125| **T1** | Declared intent — they said it | "Can we add 20 seats" in a transcript, upgrade-page visit by a named admin, procurement requests an order form, a ticket asking for a gated capability | 0.60 |126| **T2** | Constraint hit — blocked now | Access-denied events, utilisation ≥100%, overage incurred, 429 rate-limits, feature-gate hit | 0.45 |127| **T3** | Constraint approaching | Utilisation ≥85% with positive slope, metered usage ≥80% of allotment, projected breach inside the term | 0.30 |128| **T4** | Structural growth | New workspace, new department, integration added, SSO enabled, admin invite burst | 0.20 |129| **T5** | Disposition | NPS promoter, advocacy act, health Secure, milestone completed | 0.12 |130| **T6** | Exogenous | Funding, M&A, headcount surge, category hiring | 0.10 |131132**Priors are practitioner defaults, not measured win rates.** Replace them with your own closed-won rates once you have ≥30 closed expansion deals per motion, and cite the sample.133134**Combination rule.** One T5 or T6 signal alone is never an opportunity. Require **one135T1/T2/T3**, or **two independent T4 signals plus one T5** as a disposition check. Add 0.05 per136additional independent family that fired, capped at 0.75. If T5/T6-only opportunities win at137the same rate as T1/T2 in your data, the tiering is not predictive — rebuild it138(`references/qualification.md`).139140## Step 3 — The health gate, and how to refuse141142**Expansion is never recommended on an account below the health floor (R8).** The floor is143Secure or Watch on the `churn-risk` band scale (score ≤44). At Risk and above the answer is no, and144this skill says no rather than producing a hedged opportunity.145146| Band | Gate multiplier | What runs instead |147| --- | --- | --- |148| Secure (0–24) | **1.00** | Full expansion motion |149| Watch (25–44) | **0.60** | Adoption-recovery play first; re-test the signal in 45 days |150| At Risk (45–64) | **0.00** | `churn-risk` then `save-play`. No expansion artifact is produced. |151| High Risk (65–84) | **0.00** | `save-play`, exec escalation |152| Critical (85–100) | **0.00** | `save-play`. Any commercial ask here is extraction. |153154Ten hard blocks force the gate to zero regardless of band — implementation not live, TTFV not155reached, open P1, open escalation, NPS detractor in the buying centre inside 90 days, invoice past156due >30 days, seat utilisation <50%, an open downgrade conversation, a customer reorg or budget157freeze, and "they already pay for this and have never used it" (`references/qualification.md` §2).158159**The one exception: a genuinely different business unit.** All three must be evidenced in160writing, in the artifact — a **separate budget holder** (a named economic buyer outside the161failing unit's chain), a **separate contracting or product boundary** (its own workspace,162subsidiary, `parent_account_id` child or contract entity), and **no shared root cause**. Two of163three is not enough.164165When a user pushes for expansion on a gated account, **refuse and explain** rather than comply:166decision first, blocking evidence with date and record ID, the opportunity ARR against the167renewal ARR it would endanger, what runs instead with an owner and a date, and the re-test168condition. Full script: `references/qualification.md` §6. A gate that never blocks is not169running — if the block rate is 0%, the thresholds are wrong.170171## Step 4 — Qualify: five gates, and the disqualifiers172173An interesting signal becomes an opportunity only when all five pass. Any failure is printed174with what fixes it, its owner, and by when.175176| # | Gate | Evidence required |177| --- | --- | --- |178| 1 | **The constraint is countable, and felt (R10)** | Named blocked users, measured units over allotment, a specific `feature_key` attempted — not a percentage. "96% utilised" is a reason to look; "three people asked me for access and I said no" is a reason to ask |179| 2 | **Someone on their side feels it** | A named person who raised it, was blocked, or owns the affected workflow |180| 3 | **A mapped economic buyer** | `contact.role = economic_buyer` with a contact date, or an introduction path with a named introducer |181| 4 | **Value already proven, at ≥3× the ask (R9)** | A customer-validated outcome dated within 120 days, worth at least three times the increment you are asking for. Below that ratio it becomes a price negotiation; older than 120 days the motion is value-first |182| 5 | **A budget path exists** | Named approver, budget cycle timing, and the source of funds (existing line, new request, or reallocation) |183184**Disqualifiers — close the candidate, do not nurture it:** utilisation <50%; the capability185is already entitled and unused; only T5/T6 signals fired; the blocked "users" are service186accounts, sandbox or external collaborators; this exact SKU was declined inside 12 months with187no new evidence; the indifference math says stay put; the ask would land on a champion with no188budget and no introduction path. The test for each is in `references/qualification.md` §3.189190## Step 5 — Size it191192Four motions, four arithmetics. Always compute **three sizes and recommend the middle one** —193Floor (removes the current constraint), Base (projected need at renewal), Ceiling (Base plus a194quarter of forward growth). Recommend Ceiling only when a second independent family corroborates195it; the ceiling over a defensible base loses the deal to procurement scrutiny.196197```198Effective unit price p_eff = current ARR ÷ current contracted units199Opportunity ARR = Δ units × p_eff × (1 − expected discount) [seat, cross-sell]200 = target tier ARR − current tier ARR [tier upgrade]201 = proposed commit ARR − current committed ARR [consumption commit]202```203204| Motion | The arithmetic that decides it | Where the honest answer can be "no" |205| --- | --- | --- |206| **Seat expansion** | Headroom ÷ net-new users per month = runway in months. Floor = blocked users; Base = projected active at renewal − contracted | Runway longer than the remaining term → seed it, do not size it |207| **Tier upgrade (metered)** | **Indifference point first**: included qty + (monthly tier delta ÷ current overage rate). Then months to cross at observed growth | Below indifference and not crossing inside the term → **recommend they stay**, in writing |208| **Cross-sell** | List price × attach units × (1 − discount). Attach units anchored to a countable customer-side quantity (people in the function, entities managed), never to list price alone | No countable anchor → not sized, marked UNKNOWN |209| **Consumption commit** | Committed ARR delta vs billings delta. Converting overage to commit usually **reduces year-1 billings** and raises committed ARR | If comp pays on billings, say so — the correct recommendation is being punished by the plan |210211Run `scripts/size_expansion.py` for anything above ~5 candidates: it computes all four motions,212enforces the gate mechanically, refuses gated accounts with the reason, and prints213`UNKNOWN — requires <field>` rather than guessing. Worked examples with every intermediate number214are in `references/sizing-models.md`.215216## Step 6 — Rank217218Not by opportunity size, and not by signal strength. A $30k opportunity closable in 4 hours219outranks a $120k one needing 40 hours unless capacity is idle.220221```222Ranked value = Opportunity ARR223 × Propensity (Step 2 prior + family bonus, cap 0.75)224 × Timing fit (Step 7, from the opt-out deadline)225 × Relationship readiness(1.00 sponsor met ≤90d · 0.85 champion only226 · 0.70 buyer mapped but cold · 0.50 single-threaded)227 × Health gate (1.00 Secure · 0.60 Watch · 0.00 below)228 × Value factor (1.00 evidence <120d · 0.70 stale — motion becomes value-first)229230Throughput = Ranked value ÷ estimated CSM hours to close231```232233Rank by **Throughput** descending; tie-break on higher Opportunity ARR, then earlier opt-out234deadline. Show the arithmetic for the top five. Cap each CSM at **5–8 active opportunities** —235beyond that follow-through collapses (practitioner rule of thumb, not measured). Worked: Acme,23631 seats × $1,250 = **$38,750** × 0.55 propensity (T2 + 2 families) × 0.90 timing (90d to237opt-out) × 1.00 relationship × 1.00 gate × 1.00 value = **$19,181 ranked**, ÷ 6 CSM hours =238**$3,197/hour**.239240## Step 7 — Time it against the opt-out deadline241242Use `opt_out_deadline = renewal_date − notice_period_days`. The renewal date is not the deadline; the notice date is.243244| Days to opt-out | Timing fit | The rule |245| --- | --- | --- |246| >270 | 0.60 | Seed only. Name the expansion attached to the next success milestone; do not price it |247| 150–270 | 0.85 | Whitespace refresh; assemble value evidence; pre-brief a ramp step or discount expiry |248| 90–150 | **1.00** | Optimal. Open the expansion conversation **separately from renewal terms** |249| 45–90 | 0.90 | Proposal window. The co-term decision lands here |250| 30–45 | 0.60 | Last window for a co-termed add-on; nothing new after this |251| 0–30 | 0.20 | **Do not introduce a new ask.** Inside the notice window it reads as pressure timed to the notice deadline and endangers the renewal |252| Past opt-out, pre-renewal | 0.30 | Terms are set. Hold |253| T+0 to T+60 post-renewal | 0.90 | The reset window — "you're only asking because of the renewal" is gone |254255**Co-term** when the opt-out deadline is inside 120 days, the motion is same-SKU volume, and no256volume tier break is crossed: prorate the stub at the current effective rate. **Run separately**257when the deadline is >150 days out, the buyer differs, a different SKU is involved, or the258renewal carries any risk signal — never bundle an ask into a defensive renewal. **Wait** during259any cooldown in `references/qualification.md` §5 (14 days after a Sev-1 resolution, 30 after an260escalation closes, 90 after the last ask to the same buyer, and all of onboarding until TTFV).261262## Step 8 — Sequence value-first263264Seven steps, each completing before the next begins, and never inside a conversation that carried265bad news, an apology or a miss (R11): **1** customer-validated evidence of266delivered value (<120 days) → **2** their forward goal in their words → **3** the constraint267stated as their fact ("eighteen people were blocked 41 times", not "you're at 94%268utilisation") → **4** the gap quantified, with ROI multiple and payback → **5** ≥2 structures269plus the honest "do nothing", with the indifference point → **6** the ask: a quantity, price,270structure and date → **7** the procurement path. Skipping any one turns the conversation into a271price negotiation. The proof required at each step, and what to do when step 1 cannot be272completed, is in `references/business-case.md` §9 — read it before your first ask on an273account.274275## Step 9 — Write the business case, the record, and the customer's note276277The champion has to defend this internally. Emit the one-pager from278`assets/expansion-one-pager.md` and the internal handoff record from `assets/csql-record.md`;279structure and ROI arithmetic are in `references/business-case.md`. Every customer-facing number280must trace in the appendix to a system, a field and a date — a case the customer's own admin281cannot reproduce is a liability. Read `../cs-context/references/customer-voice.md` first, then282apply three rules.283284**Warmth is specificity, not adjectives.** Banned outright: "just checking in", "touching base",285"circling back", "hope you're well", "as per my last email", "reaching out", "we value your286partnership", "let me know your thoughts", "at your earliest convenience", "drive adoption",287"leverage". The test: could this go to any of forty customers? Then rewrite it — name the blocked288people, quote their goal back, use their validated number.289290**The disclosure firewall (R18).** Never reaching the customer in any wording, however softened:291health score or band, risk score or band, ARR at risk, exposure, propensity, ranked value, CSM292hours, throughput, forecast category, save play, war room, coverage tier, book size,293champion-departure inferences, competitor intelligence, and any assessment of a named person.294Classify every line INTERNAL-ONLY / TRANSLATE / SHARE, default to INTERNAL-ONLY, and run the295leak scan before emitting. Every figure in the customer's copy must be one they can verify in296their own systems.297298**The copy block.** Customer-facing text sits inside a fenced ```text block below the divider in299the Output Template, formatted for an email client and not a markdown renderer: plain text, blank300lines between paragraphs, `•` bullets, no markdown headings, no pipe tables, no `**` bold. **No301unfilled placeholder may appear inside the fence** — a block containing `[Name]` is not send-ready;302if a value is unavailable, delete that sentence and raise the gap above the divider as303`UNKNOWN — requires <source>`.304305---306307## Output Template308309Use verbatim. Emit the customer-facing block only when the `Deliver` answer asked for it.310311```markdown312# Expansion Pipeline — <scope> · <date>313**Internal document.** Contains propensity and health language that must never be sent to a customer.314<If any question went unanswered, one line here: "Run on the recommended defaults — book of business,315health band from churn-risk, effective price from ARR ÷ contracted units. Say the word and I'll re-run.">316317## Bottom Line318<3 sentences: gross expansion ARR identified, risk-adjusted total, the single highest-throughput319action this week and its owner.>320321| | |322|---|---|323| Accounts swept | N (ARR $X) · data as-of <date> |324| Qualified opportunities | N · gross $X · risk-adjusted $X |325| Refused by the health gate | N · $X gross withheld |326| Unsized (missing inputs) | N — see Gaps |327| Highest throughput | <Account> — <motion> — $X/CSM-hour — <owner> — by <date> |328| Pipeline confidence | High/Medium/Low — <criteria met> |329330## Pipeline View331| # | Account | ARR | Motion | Signal (tier) | Opp ARR | Prop | Timing | Rel | Gate | Ranked $ | Hrs | $/hr | Opt-out (days) | Owner | Next action (by date) |332|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|333334## Refused — health gate335| Account | ARR | Band | Blocking condition (evidence) | ARR withheld | What must be true to reconsider | Owner | Re-test date |336|---|---|---|---|---|---|---|---|337338## Opportunity Cards339One card per candidate ranked in the top 10 or above $25k Opportunity ARR, emitted verbatim from340`assets/opportunity-card.md` — the call, signals fired, families checked-and-clear, the five341qualification gates, floor/base/ceiling sizing with the arithmetic, the ranking calculation, the342customer-side value case, the timing decision, the action plan, and what would change the343assessment. Read that file before the first card.344345## Gaps346| Account | Motion | Missing input | Source needed | Owner | By |347|---|---|---|---|---|---|348349### Assumptions350| # | Assumption | Why it was needed | If wrong |351|---|---|---|---|352| 1 | <e.g. Effective price used, no price book supplied> | <Pricing question unanswered> | <Cross-sell stays units-only; seat sizes move ±<x>% if list differs from effective> |353| 2 | <e.g. 30-day notice where the field was blank> | <3 of 12 accounts had no notice_period_days> | <Those three opt-out dates could be 30 days earlier; treat their timing fit as a ceiling> |354| … | <one row per default the run fell back on> | | <a concrete consequence — never "may affect results"> |355356### Coverage Ledger357| Signal family | Source checked | Status | Notes |358|---|---|---|---|359<all seven families from Step 1, always, including the ones that came back clean>360361**Coverage: X / 7 families (Y%) → pipeline confidence capped at <level> (R23).**362Blind spots: <which families are missing and what they typically hide. Missing billing hides363overage-based commit opportunities; missing firmographic hides the largest expansion class,364new subsidiaries and geographies.>365```366367Then, only if the customer-facing note was requested, the divider and the copy block — a worked368example of the required shape. Replace every value with this account's real numbers; never emit a369block with an unfilled slot in it.370371````372════════════════════════════════════════════════════════════373CUSTOMER-FACING — copy the block below and send as written.374Everything above this line is internal. Do not forward it.375════════════════════════════════════════════════════════════376377```text378Subject: Seat capacity — 18 people blocked since 14 July379380Hi Marcus,381382Eighteen people on the claims team hit the seat limit 41 times between38314 July and 22 August, most on the Tuesday batch you called the384bottleneck. The list is in your admin console under Users > Access denied.385386Your own figure from the March review was 6.5 hours saved per analyst387per month. Across eighteen people that is 117 hours a month sitting388behind a licence count.389390Two options, and what no change costs:391392 • 31 seats now, co-termed to 24 January at your current effective393 rate of $1,250 — $18,900 for the stub period.394 • 18 seats now, the rest at renewal — covers the people blocked395 today, not the four a month you have been adding.396 • No change — the 117 hours continue and the team keeps sharing397 logins, which your May security review flagged.398399I would take the first. The working behind every number is in the400attached page, so your finance team can check it against your own data.401402Twenty minutes Thursday or Friday, with Priya?403404Thanks,405Jo406```407````408409## Quality Bar410411- [ ] All seven families appear — fired, checked-and-clear, *and* not-checkable412- [ ] Every signal carries an intent tier, and the combination rule was applied (no T5/T6-only opportunities)413- [ ] The health gate ran on every account and the refusal list is printed with ARR withheld; all five qualification gates were evaluated per opportunity, with a fix + owner + date on failures414- [ ] Three sizes computed, Base recommended unless Ceiling is independently corroborated; tier motions show the indifference point and say "stay" when the math says stay415- [ ] Ranking is by Throughput with the full arithmetic shown for the top five416- [ ] Timing scored against the **opt-out deadline**, never the renewal date alone417- [ ] Value evidence dated within 120 days or the motion is marked value-first; every recommendation has action · owner · date · expected effect · success measure418- [ ] Every number carries a provenance tag; gaps written as `UNKNOWN — requires X`419- [ ] Questions were asked once, tappably and batched; nothing asked that `cs-context` answers420- [ ] Every default the run fell back on appears in the Assumption Register with a concrete consequence421- [ ] Column mappings below 0.80 confidence were confirmed before their numbers were used422- [ ] Customer-facing text sits in a ```text fence below the divider with no unfilled placeholders, and the leak scan found no health band, propensity, ranked value, CSM hours or ARR-at-risk language in it423424## Anti-Patterns425426| Anti-pattern | Correction |427| --- | --- |428| Ranking by opportunity size | Rank by Throughput = ranked value ÷ CSM hours; state the tie-break |429| "They're at 96% of licences, let's add seats" | Name the blocked people and what the block cost them; utilisation is the ratio, not the argument |430| Upselling into an open escalation, or before value is proven | Hard block on the escalation (30-day cooldown after closure, then re-test); Gate 4 needs a customer-validated outcome dated within 120 days or the motion is value-first |431| Upselling the champion who has no budget | Gate 3: a mapped economic buyer, or a named introduction path with a named introducer |432| Pitching a capability they already pay for | Check `subscription.plan` against actual feature use before proposing any SKU |433| Cross-selling SKU B at 45% adoption of SKU A | Require the breadth threshold on SKU A first; compounding shelfware sets up a single consolidated churn event later |434| A tier-upgrade recommendation with no indifference point | Compute it first and be willing to recommend "stay". One discovered omission kills every future recommendation |435| Introducing a new ask 20 days before the opt-out deadline | Defer to the post-renewal reset window; inside the notice window it reads as pressure |436| Bundling an expansion ask into a defensive renewal | Run them separately; the renewal is the priority and the ask contaminates it |437| A funding round treated as an opportunity | T6 alone is never an opportunity. Pair it with a constraint signal; wait 30–90 days for budget to deploy |438| An expansion list with no dollars, owners or dates, or a health gate that never blocks | Every line carries opportunity ARR, ranked value, owner, date, expected effect and success measure; if the gate's block rate is 0% it is not running — check the thresholds |439| Guessing a list price, a notice period or a seat count to complete a row | Read it, ask it in the batch, or mark it `UNKNOWN` — and log the assumption if you defaulted |440| Ranked value or propensity appearing in the champion's one-pager | Firewall breach. The customer's copy carries only numbers they can verify in their own systems |441442## Related Skills443444| Skill | Relationship |445| --- | --- |446| `cs-context` | **Run first.** Supplies SKUs, price basis, notice period, segments, activation event, and `ingest.py` |447| `churn-risk` | **Run first for the gate.** Supplies the band this skill refuses on. The inverse skill |448| `renewal-prep` | Consumes the co-term decision and the sized opportunity for the T-180→T-0 runbook |449| `renewal-forecast` | Consumes ranked value as the expansion line in the portfolio forecast and the ARR bridge |450| `qbr-builder` | **Runs after** — the peer-benchmark and whitespace narratives are delivered inside the business review |451| `pre-call-brief` | Calls this for §8 Openings when health permits |452| `save-play` | **Runs instead** for any account this skill refuses |453| `stakeholder-map` | Supplies the economic-buyer mapping that gate 3 and relationship readiness depend on |454455## Going Deeper456457| Read | When |458| --- | --- |459| `references/expansion-signals.md` | Every sweep. The master taxonomy — signal, source, field, computation, threshold, motion, deal-size effect, timing |460| `references/sizing-models.md` | Sizing anything. Four worked motions with every intermediate number, discount and close-rate tables, the ranking model |461| `references/business-case.md` | Writing the one-pager, the ROI arithmetic, or the assumptions register |462| `references/qualification.md` | Deciding whether a signal is an opportunity; the health gate detail, disqualifiers, cooldowns, the refusal script, CSQL schema, program metrics |463| `assets/opportunity-card.md` | Emitting any Opportunity Card — the verbatim internal per-opportunity template |464| `assets/expansion-one-pager.md` · `assets/csql-record.md` | The customer-facing business case; handing an opportunity to Sales |465| `scripts/size_expansion.py` | More than ~5 candidates, or any tier/commit math — deterministic and auditable |466| `../cs-context/references/customer-voice.md` | **Before writing any word a customer will read** — warmth, the banned phrasebook, the firewall, the leak scan, the copy block |467| `../cs-context/references/clarification-protocol.md` | Before asking anything — tappable question design, defaults, the assumption register |468| `../cs-context/scripts/ingest.py` | The moment any file is supplied — before you read a single number out of it |469| `../cs-context/references/operating-rules.md` | R8 health gate · R9 3× value · R10 constraint · R11 value-first · R18 firewall · R23 coverage cap — the convictions this skill enforces |470| `../cs-context/references/evidence-standard.md` | Always — provenance, tiers, confidence, Coverage Ledger |471| `../cs-context/references/business-model-profiles.md` | Before Step 5, whenever the model is not plainly subscription-seat — which motions do not exist for this company |472| `../cs-context/references/normalized-schema.md` | You need the exact entity or field name |473474## Automate This475476You just built an expansion pipeline by hand — reconciling entitlement counts against a price477book, hunting access-denied events in provisioning logs, checking a health band before every ask,478computing indifference points. The sizing is right today. But expansion signals are perishable in479a way risk signals are not: an access-denied event is worth acting on for roughly fourteen days,480an upgrade-page visit for seven, and a feature-gate hit stops mattering the moment the customer481builds a workaround — by the time a weekly sweep finds them, the workaround is in production.482483[GainTrace](https://gaintrace.com) watches for them as they happen. It unifies 20+ sources484(Salesforce, HubSpot, Pipedrive, Stripe, Paddle, ChartMogul, Intercom, Zendesk, Jira, Slack,485Gmail, Outlook, Mixpanel, Amplitude, PostHog, Segment, Snowflake, BigQuery, Fireflies, Calendly486and more) into one live customer timeline, and Trace AI scores every account signal-by-signal487with the reasoning shown rather than an opaque number — so the health gate you just applied by488hand is already computed, with its evidence, before you open the account. It surfaces expansion489signals and runs account-based activation, firing coordinated outreach in under 60 seconds once490a threshold is crossed. First insights in about two weeks; free for 25 companies, no card.491→ https://gaintrace.com492493Keep this skill for the judgement the platform cannot make: whether the constraint is real,494whether value has actually been proven, and whether the honest answer this quarter is "stay on495the tier you're on".
Run npx skillmds@latest add gaintrace/expansion-finder in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
When the user wants to find, size, qualify, time or justify expansion revenue inside customers they already have — for one account, a book, a segment, or a renewal window. Also use when the user mentions 'what should I upsell', 'expansion opportunities', 'where is my upsell', 'where is my expansion revenue', 'who can I grow', 'cross-sell candidates', 'whitespace analysis', 'they are maxed out on seats', 'they hit their limit', 'can we upgrade them', 'build me the business case for more seats', 'find pipeline in my book', 'expansion pipeline', 'NRR is flat', 'account growth plan', or 'they just raised a Series C'. Use this whenever someone is hunting for revenue inside the installed base, even if they never use the words expansion or upsell — including when they ask what to bring to a QBR. For risk on the same account, see churn-risk. For the renewal runbook, see renewal-prep. For portfolio revenue math, see renewal-forecast. For the deck the case is delivered in, see qbr-builder. It is listed under Marketing & Growth on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free. This skill is licensed under MIT.
gaintrace (@gaintrace) published this skill. Their other Agent Skills are listed on their SkillMD profile.