Sextant
← Catalog
Block · sales

Pipeline Coverage

Weighted pipeline stacked against the gap to quota, with a coverage ratio and the probability of hitting plan.

State
Size
Mode

Q2 2026 · Pipeline Coverage

2.9×

$4.1M pipeline · $1.4M gap

Quota has a 44% chance of hitting plan by quarter end.

Q2 2026 · Pipeline Coverage — open pipeline by stage
StageValueWin prob
Prospect$1.6M10%
Qualify$920k22%
Proposal$780k45%
Negotiation$520k65%
Verbal$280k88%

Salesforce · updated hourly

Demo data is illustrative. Replace with your own typed data prop.

How it computes

Probability-weighted pipeline vs the gap to quota, with a Gaussian estimate of P(bookings ≥ gap).

gap = max(0, quota − closedWon);  weighted = Σ value·winProb;  σ = √(Σ value²·p(1−p));  P = 1 − Φ((gap − weighted)/σ)

Assumptions

  • Stage win-probabilities are independent (Bernoulli per opportunity).
  • The normal approximation holds across the set of opportunities.
  • quota − closedWon is the true remaining gap.

Honest about

  • Coverage is reported as ∞ when the gap is already closed, rather than a misleading finite ratio.
  • σ assumes independence — real deal correlations are not modeled, so a concentrated pipeline is riskier than the interval implies.
  • The "healthy" coverage multiple (default 3×) is an industry reference line, not a statistical threshold.

Use it with your data

Data contract

Passed via the data prop — an object: validated at runtime, so a bad shape degrades to the error state rather than crashing.

FieldTypeRequired
quotanumberyes
closedWonnumberyes
stagesarrayyes

Static props

import { SalesPipelineCoverage } from "@/components/blocks/sales-pipeline-coverage/sales-pipeline-coverage";

<SalesPipelineCoverage data={myData} />

Client fetch (SWR)

const { data, isLoading, error } = useSWR("/api/metric", fetcher);
// route isLoading/error through <ChartStates>, then:
<SalesPipelineCoverage data={data} />

Server component (RSC)

const data = await fetch(url, {
  next: { revalidate: 3600 },
}).then((r) => r.json());

<SalesPipelineCoverage data={data} />

Map arbitrary rows

import { mapRows } from "@/lib/sextant/column-map";

const out = mapRows(rows, { /* contractKey: "yourColumn" */ }, dataSchema);
if (out.ok) <SalesPipelineCoverage data={out.data} />;

Make it yours

Every customization below is an optional prop — omit them all and you get the defaults shown above. Recolor, reformat, restyle, or drop the card chrome without forking the component.

Recolor or rename a series (pipeline)

<SalesPipelineCoverage
  series={{ pipeline: { color: "var(--chart-3)", label: "…" } }}
/>

Format numbers (currency / locale)

const eur = new Intl.NumberFormat("de-DE", {
  style: "currency",
  currency: "EUR",
  notation: "compact",
});

<SalesPipelineCoverage valueFormatter={(n) => eur.format(n)} />

Replace or hide the narrative

<SalesPipelineCoverage narrative="Your own one-liner." />

// …or hide it entirely:
<SalesPipelineCoverage narrative={false} />

Restyle any region

<SalesPipelineCoverage
  className="max-w-xl"
  classNames={{ body: "bg-muted/20" }}
/>

Drop the card chrome (headless plot)

import { SalesPipelineCoveragePlot } from "@/components/blocks/sales-pipeline-coverage/sales-pipeline-coverage";

// Just the chart body — bring your own card/layout:
<SalesPipelineCoveragePlot data={data} config={config} />