# How we compute advertised salaries

Canonical URL: https://quarrion.ai/salary/methodology

> Every published figure is a median of the annual pay employers stated in public job advertisements over a rolling 90-day window, recomputed nightly, published only where at least 30 advertisements support it.

This page states the method in full: what a single observation is, which advertisements are excluded and why, what gets a whole figure withdrawn, and where the numbers come from. It is written to be checked rather than taken on trust — every threshold named below is the one the code enforces.

## What these figures are

They are ADVERTISED salaries: the annual pay an employer published in a job advertisement. That is the whole claim, and it is deliberately a narrow one.

- **Not a survey**: Nobody was asked what they earn. No figure here is self-declared by an employee, and none is weighted to a population.
- **Not what anyone was paid**: An advertised range is an opening position. An employer may settle above or below the figure it advertised, and the settlement is not public.
- **Base pay only**: Bonus, tips, overtime, commission, equity and benefits are outside what an advertisement usually quotes, so they are outside these figures.
- **Aggregates only**: No individual listing, employer name or line of advertisement text is published anywhere on this site. A cell is a count and three percentiles.

## How the figures are computed

A cell is one role in one market — "chef de partie in London". Every advertisement matching that cell and carrying an annual salary in the window becomes one observation, and the cell is the 25th percentile, the median and the 75th percentile of that sample.

- **One observation per advertisement**: The midpoint of the advertised range when both bounds are given, or the single bound when only one is. A missing bound is treated as absent, never as zero — averaging in a zero is how a median gets dragged toward nothing.
- **A rolling 90-day window**: Measured on the date the advertisement was posted. A posting date in the future is refused rather than accepted, because a window that ends after today is visibly impossible and discredits every number beside it.
- **Converted before aggregating**: Each cell is priced in its own local market currency, and every observation is converted into that currency before it joins the sample. An advertisement in a currency we cannot convert is dropped, never averaged in as though it were already local.
- **A plausibility band, applied after conversion**: An annual figure below 15,000 or above 500,000 in the cell's currency is not a salary and is dropped. After conversion, because the same raw number can be nonsense in one currency and ordinary in another.
- **A floor of 30 advertisements**: A cell below the floor is not published at all, and a published cell that falls below it is WITHDRAWN rather than frozen at a number we can no longer stand behind. That is why a page you bookmarked can legitimately disappear.
- **Outlier suppression on the spread**: A cell whose 75th percentile exceeds 4 times its 25th is suppressed entirely. A spread that wide is the signature of two different jobs sharing a title, and a median across them describes neither.
- **Recomputed nightly**: The whole table is rebuilt each night from the current window, so a figure is never carried forward. Every cell states when it was last computed.

## What is excluded, and never estimated

An advertisement with no stated annual salary is EXCLUDED. It is not imputed, modelled or predicted from the job title, and no estimated figure is ever mixed into a published median. If a cell has too few advertisements that stated pay, the cell does not publish — the gap is left visible rather than filled in.

- **No stated annual salary**: Excluded. "Competitive" and "DOE" contribute nothing to any figure here.
- **Hourly, daily, weekly and monthly rates**: Excluded rather than annualised. Annualising a day rate requires assuming the working pattern, and the assumption would silently become the answer.
- **Unconvertible currencies**: Excluded and counted, never defaulted to a currency we merely guessed at.
- **Advertisement copy dressed as a job title**: Titles longer than 40 characters, or containing pipes, brackets, slashes or digits, do not form a cell — those are reference codes, pay fragments and marketing lines, not occupations.

The honest consequence, stated rather than buried: a median over advertisements that stated pay is not a median over all advertisements. Where employers who publish a salary differ systematically from those who do not, these figures inherit that difference. Excluding is still the better trade — a stated number can be wrong, but an estimated one cannot even be checked.

## Where the data comes from

Aggregated from public job listings on boards including Adzuna and Reed. Coverage is whatever those boards carry, which is why the published cells span trades and construction, hospitality and retail, education, healthcare, care work, logistics and office roles rather than one industry.

The same vacancy re-posted by three agencies counts as three advertised observations. The corpus already de-duplicates on content at ingest; suppressing more than that would require employer-level identity we do not publish, and guessing at it would remove real adverts as often as duplicates.

## Freshness and provenance

- **Last computed**: Every cell page prints the date its figures were computed. The recompute runs nightly, so this is normally yesterday or today.
- **Data generation**: Each recompute stamps every row it writes with one generation id, printed on every salary surface — this page's siblings, /salary, each cell, each markdown twin and /llms.txt. Two of our surfaces quoting different numbers with different generation ids are two snapshots, not a contradiction; the same generation id with different numbers would be a bug worth reporting.
- **Window dates**: Every cell states the first and last posting date in its own sample, so the window is checkable rather than assumed from this page.

## How this differs from other salary sources

Advertised-salary data is well-established and several organisations publish it. These are the choices this dataset makes, so you can judge whether they suit the question you are asking — not a claim about anyone else.

- **Every sector the boards carry**: Chefs, teaching assistants, care workers, electricians and quantity surveyors are cells here on the same terms as software engineers. Nothing is scoped to one industry.
- **Stated pay only**: Advertisements without a salary are excluded, never estimated, so no published figure is partly a model output.
- **A median, not a mean**: A mean advertised salary moves with a handful of outlying adverts. The quartiles are published alongside it so the spread is visible.
- **The sample is on the figure**: The posting count and the date range sit beside every median, on the index, on the page and in the machine-readable copies — not in a footnote.
- **Readable by machine**: Every page here has a markdown twin, the whole table is available as one document, and the same figures are served over the public API.

Every published figure: https://quarrion.ai/salary (markdown: https://quarrion.ai/salary.md)
