Method version v1.0
How the sales estimate is calculated
IndieList publishes a reproducible heuristic built from public Steam review counts. It is not official sales data, and its fixed range is not a statistically validated confidence interval. Every game page exposes the inputs, final multiplier and each adjustment used.
1. Scope and evidence status
The model estimates paid Steam units from the relationship between public review count and an adjustable reviews-to-units multiplier, often called a Boxleiter number.
Version v1.0 is hand-calibrated. Repository tests prove deterministic output and TypeScript/Python parity; they do not prove accuracy against a ground-truth sales dataset. We therefore publish no “X% accurate” or “Y% within ±Z” claim.
Free-to-play titles do not receive paid-copy units or revenue estimates. Results for bundles, deep discounts, Early Access, review-key distribution and old titles can differ materially from reality.
2. Units formula
NB = clamp(50 + year + price + rating + team + genre, 15, 150)
median units = review count × NB
display range = median × [0.6, 1.4]
Adjustments are fixed points added to the base NB; they are not multiplied together. The lower and upper values are a fixed heuristic display range around the median.
3. Exact additive adjustments
Release year
| Rule | NB points |
|---|---|
| release_year < 2018 | +30 |
| 2018 <= release_year <= 2021 | +15 |
| 2022 <= release_year <= 2024 | 0 |
| release_year >= 2025 | -10 |
No release-year adjustment is added when the year is unknown.
Initial USD list price
| Rule | NB points |
|---|---|
| price_usd < 5 | -20 |
| 5 <= price_usd < 10 | -5 |
| 10 <= price_usd < 20 | 0 |
| 20 <= price_usd < 30 | +5 |
| price_usd >= 30 | +15 |
When list price is missing, version v1.0 substitutes $15.00.
Positive review percentage
| Rule | NB points |
|---|---|
| positive_pct < 70 | -10 |
| 70 <= positive_pct < 85 | 0 |
| positive_pct >= 85 | +10 |
The game-service boundary currently substitutes 80 when this field is absent; that fallback is a limitation, not observed evidence.
Studio size tier
| Tier | NB points |
|---|---|
| solo | -10 |
| small | 0 |
| medium | +10 |
| large | +15 |
| tripleI | +20 |
No team-size adjustment is added when the tier is unknown.
Primary-genre keyword rule
| First matching keyword group | NB points |
|---|---|
| casual or hyper | -15 |
| rpg or adventure | +10 |
Rules run in the order shown. No match means zero genre points.
4. Net-revenue heuristic
net per unit = list price × 0.85 × (1 − 0.04) × (1 − 0.3)
net per unit = list price × 0.5712
estimated net revenue = estimated units × net per unit
- 0.85 is the model's combined regional-price/discount factor.
- 4% is the model's refund assumption.
- 30% is the model's store-cut assumption.
This simplified result does not reconstruct price changes over time, bundles, taxes, key sales, tiered store terms, publisher splits, subscription deals or non-Steam revenue.
5. Validation status
What is tested
Deterministic fixtures, boundary behaviour and TypeScript/Python output parity for version v1.0.
What is not yet proven
Accuracy, calibration or interval coverage against a versioned ground-truth dataset of official unit sales.
A future calibrated model must publish its source policy, dataset version, sample exclusions, train/test split, error distribution and coverage before it can make an accuracy claim. That change would require a new formula version.
6. Reproducibility and corrections
The deployed specification is available at /methodology/sales-v1.json. The canonical runtime implementation is src/lib/sales-estimate.ts; the collector mirror is python_collector/src/indielist_collector/sales/algorithm.py.
If you have a public, official sales figure that materially contradicts an estimate, send the source with [sales-estimate] in the message. Corrections should improve a versioned validation dataset before they alter the formula.