Methodology
The method is public, including the unflattering parts.
A figure you cannot audit is worth nothing. This page states how the index is measured, what every field means, where coverage is thin, and what has been got wrong so far.
How it is measured
01
Read directly from each marketplace
11 marketplaces are read at their own public listing surfaces. No panel data, no reseller feed, no scraped aggregator of aggregators. Provenance is one hop, which is what makes a disagreement between two sources investigable instead of inherited.
02
Measure the denominator first
Before ingesting anything, each source is asked for its own unfiltered national result count, the number it would show a visitor. That figure is the denominator: coverage is what we hold divided by what the marketplace says exists, rather than a percentage of an unknown.
03
Normalise at the write boundary
Make, model, variant and body are reconciled onto one vocabulary as rows are written, not at query time. A field that means different things in different rows is a field that cannot be grouped, and fixing it later means re-deriving every figure ever published from it.
04
Re-observe, and keep what changed
Listings are re-read on a schedule and the record keeps the difference: a price change, a re-listing, a disappearance. This is the part that cannot be reconstructed afterwards, and it is the reason the index runs continuously rather than on demand.
05
Validate before it lands
Rows pass a schema gate on the way in. A malformed batch is rejected rather than partially written, because a partially written batch is indistinguishable from a real drop in listings a month later.
06
Stamp everything with an as-at
Every published figure carries the date it was measured. The counts on this site are stamped 19 August 2026 and are derived at build time from the source registry. There is no hand-typed number anywhere on this domain.
Field dictionary
The core of the canonical row. Nullable fields are marked, and they are null rather than imputed. A zero odometer and an unknown odometer are different facts, and the record keeps them different.
| Field | Type | What it means |
|---|---|---|
| source | enum | Which marketplace the listing was read from. Never inferred. A row always knows its origin. |
| source_id | string | The marketplace's own identifier for the listing. What makes re-observation possible rather than guesswork. |
| make · model · variant | string | Normalised across sources. Marketplaces disagree about all three, and reconciling them is most of the work. |
| body | enum | One controlled vocabulary at the write boundary, so a wagon is a wagon regardless of which site called it a touring. |
| year | integer | Build or compliance year as advertised. Where a source publishes both and they disagree, the advertised one is kept and the disagreement is not hidden. |
| price | integer | null | The asking price as advertised, in AUD. Not a sale price. Where a listing shows no price, the field is null rather than zero. |
| odometer | integer | null | Kilometres as advertised. Absent on a meaningful share of auction and dealer stock, and absent rather than imputed. |
| location | string | null | The seller's advertised location: state, region, postcode where given. Where a car is listed, not necessarily where it is. |
| first_seen · last_seen | timestamp | The observation window. Days advertised, price changes and disappearance are all derived from these two. |
Coverage and gaps
Coverage is measured, not asserted
Each source's advertised total is measured against the marketplace itself, so the shortfall between that and what the index holds is a known quantity rather than a hope. A thin source is reported as thin instead of being averaged into a headline.
One source is not read at all
A marketplace is excluded either because reaching it would mean operating authenticated accounts against a platform that forbids it, or because its listing surface cannot be enumerated in full, in which case it is disabled rather than partially ingested. Each is named on the coverage page with which of the two applies.
Duplicates are not collapsed
One vehicle advertised on two marketplaces is two listings in the record. Cross-source de-duplication is a separate problem with its own error rate, and hiding it inside a headline count would make the headline unfalsifiable.
Resolution is the crawl interval
Time-based fields are derived from observation, so their resolution is how often a source is re-read, not the hour. A listing that appeared and vanished between two reads was never observed and is not in the record.
Change record
What has changed in the index, dated, including the mistakes. This section is not curated: an error that moved a published figure belongs here precisely because it is the kind of thing that usually does not get printed.
22 July 2026
Autotrader was wrongly written off for six months
A source was recorded as having no reachable pathway and left out of the index. It had one the whole time: an ordinary unauthenticated request returns 76,780 listings. The obstruction turned out to be headers we were sending ourselves. It is in the index now, and the six months are in this list because a coverage figure that quietly grows is a figure nobody can check.
22 July 2026
A state total was recorded as a national one
A national total for one source was recorded as 18,753. That was a single state's figure read as though it were the country. The true national total is 78,790, a four-fold error in a number that had already been published. Every advertised figure is now read from an unfiltered national search and stamped with the date it was taken.
23 July 2026
Fourteen days of ingestion were lost to a silent no-op
Ingestion silently wrote nothing for fourteen days. A schema change had been applied with a statement that does nothing when the table already exists, so the writer had columns the table never received. Nothing errored; the rows simply stopped. Coverage figures from that window are not in the record, rather than being carried forward as though they were fresh.
23 July 2026
Auction inventory was found to swing 19% within a day
One auction house measured 823 lots and 667 lots on the same day, a 19% swing with no listing activity to explain it. Auction inventory is now treated as volatile by default: a single reading is published as a reading, never as a trend, and the as-at date travels with every figure.
Source registry last revised 19 August 2026 (2026-08-19).
Questions about the method
If something here does not stand up to the way you would use it, that is worth an email before it is worth a licence.