# TransLink patronage analyser

Queensland public transport patronage, precomputed into static files and
explored in the browser. No server, no database, and no multi-gigabyte download:
the whole analytical layer is a few megabytes of dimension tables plus one small
partition per month, fetched only when a view needs it.

TransLink publishes 126 months, February 2016 to July 2026, and the deployed
dataset covers **all of them** — 1.43 billion journeys. The month selector and
`manifest.json` remain the authority on what is actually available.

Two things about that record are worth knowing before reading any chart, and
both are set out under **Coverage and limitations**: the default view is scoped
to South East Queensland rather than the whole network, and the source changed
shape in March and April 2026, so the most recent months are not directly
comparable with what precedes them.

Live at [/translink](https://dantine.dev/translink). A shorter, user-facing
version of what follows — sourced live from the deployed dataset rather than
fixed in prose — is at [`/translink/about/`](about/).

## What the data actually is

The source is TransLink's published **Origin-Destination Trips** extract, one
file per calendar month, from the Queensland Government open data portal. Two
datasets cover it: [2016 to 2021](https://www.data.qld.gov.au/dataset/go-card-transaction-data)
and [2022 onwards](https://www.data.qld.gov.au/dataset/translink-origin-destination-trips-2022-onwards).
This deployment attributes the whole record as
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), credited to the
State of Queensland. The two are separate dataset records published years
apart on the open data portal, so check each one's own licence badge rather
than assuming they are guaranteed to match — the portal sets licensing per
dataset, not per publisher.

Each row is an aggregated count of ticketing transactions for one combination of
operator, route, direction, time band, ticket type, origin stop and destination
stop.

**A recorded trip is one movement on one service between an origin and
destination** — this document calls it a "journey" throughout, in the sense
TransLink's own open data uses the word for this extract, but the site's UI
prefers "trip" for the same concept where "journey" would be ambiguous against
TransLink's broader multi-leg journey-planning terminology. Either way it is
one boarding of one vehicle by one ticket: not a unique passenger and not a
complete door-to-door movement. Someone who catches a bus and then a train
contributes two trips (two journeys, in this document's sense). Nothing in the
source identifies individuals, so no figure on the site is a passenger count,
and none is described as one.

### What the source does and does not permit

| | |
|---|---|
| **Time of day** | Five bands only: four **weekday** bands (midnight–08:29, 08:30–14:59, 15:00–18:59, 19:00–23:59) and one undifferentiated **Weekend**. Every clock band is a weekday band, which the filter chips now say on their face. The first weekday band fuses early morning with the whole AM peak, so an "AM peak" figure is **not derivable**. Saturday cannot be separated from Sunday. The site shows the source's own bands and offers nothing finer. |
| **Day type** | Weekday and weekend *are* separable, so an average-weekday measure is available. Public holidays are not identifiable and are counted as weekdays. |
| **Ticket type** | go card, paper ticket, and contactless bank card (EMV, from August 2020 — 40 journeys that month, 51% of all journeys by July 2026). From April 2026 the source also emits fare-product labels this pipeline does not recognise (`Count`, `Daily`, `Multi-Day`, `Multi-Trip`), which are counted in every total but grouped as "Other / unrecognised" — 8–10% of each recent month. What that bucket *is* has been measured; see **The unrecognised ticket bucket** below. |
| **Origins and destinations** | Only where both ends were recorded. **Paper tickets record no tap-off**, so they contribute a boarding and no destination — 3.1% of journeys across the whole record, but the share is not stationary: 5.4% in February 2016, 0.6% in March 2026, and 9–12% from April 2026 onward. The site quotes the selected month's own figure rather than this average. Boarding totals include them; every origin-destination view excludes them and says so. |
| **Direction** | Not a binary: Inbound/Outbound, the four compass points, Clockwise/Counterclockwise, per-mode placeholders, an empty string and one malformed `Unknown : 40`. The source spells the same direction more than one way — `East` and `Eastbound`, `Up` and `Upward`, `Counterclockwise` and `Counter Clockwise` — and often uses both at once: route 963 ran `East` from November 2022 and `Eastbound` from September 2023, four years of overlap. **These are merged**, so a route's eastbound journeys appear once rather than split across two rows meaning the same thing. The longer spelling is the one shown. Merging moves journeys between direction rows and never changes a total. |
| **Rail and light rail** | Each is a single placeholder "route" in the source — station-to-station movements with no route and no stopping pattern. Rail alone is **402 million journeys, 28% of the whole record**. Ferry is mixed: 22 named routes plus two 2016-19 placeholders (`BCC Ferries`, `BIT`), which are placed by an inferred model (see G:link below). A fourth placeholder, `Busway`, is bus. |

## Metric definitions

- **Monthly total** — journeys recorded in the month, as published.
- **Average calendar day** — monthly total ÷ days in the month, weekends and
  holidays included. Labelled as a calendar-day average because that is what it is.
- **Average weekday** — weekday-band journeys ÷ the number of Mondays to Fridays
  in the month. Public holidays are counted as weekdays, because the source gives
  no way to identify them.
- **Average weekend day** — weekend journeys ÷ Saturdays and Sundays. The two
  cannot be separated.
- **Year-on-year** — always against the *same calendar month* in an earlier
  year, so school holidays and seasonal travel line up instead of masquerading
  as growth. How many years back is the "Same month in" filter, which reaches as
  far as the record allows — ten years from July 2026. The growth rankings use
  the same span and label it, so a three-year change is never presented as an
  annual one. Growth from a base of zero has no percentage and is shown as a
  dash. A route or stop the selected month does not record at all is a
  withdrawal, not a decline: it reads −100%, nothing can rank below −100%, and
  ten of them together crowd out every service that is genuinely losing riders.
  Those are left out of the fastest-declining list and counted in a note under
  it. Route 66 did not lose its passengers; it became the M2.
- **Journeys per scheduled service** — journeys ÷ the trips the route's matched
  pattern ran that month, taken from the timetable in force then rather than
  today's. A trip count is turned into a *rate* first — trips on a typical
  weekday and on a typical weekend day, from the GTFS calendar — and multiplied
  by the month's day counts, because one Sunday-only trip and a trip every
  weekday are not the same service.

  Two honest limits. The historical GTFS snapshots are quarterly samples
  chosen to explain which network a month ran on, so a month between snapshots
  is measured against the nearer one rather than against its own timetable. And
  a route with no GTFS match has no denominator at all: the figure is shown as a
  dash, never as a zero.
- **Journeys per service-hour** — the same numerator over the hours those trips
  spend running, rather than over how many of them there were. A trip is a trip
  whether it runs four stops or forty, so a per-trip figure flatters short
  routes and penalises long ones; per service-hour asks what the operator spends
  to carry them. Running time only: a trip's last arrival less its first
  departure, so layover and deadheading are outside it.

  Neither figure is a crowding measurement. A journey is one boarding and a trip
  is one scheduled vehicle; nothing in this data knows a vehicle's capacity or
  how far along the route its passengers were aboard. A CityCat carrying 150
  journeys a trip and a bus carrying 50 are not comparable, which is why the
  mode filter matters more on that ranking than anywhere else on the site.
- **Scheduled services per day** — trips ÷ how many of *those* days the month
  held, drawn as one line per day type so a weekday timetable is never averaged
  with a Sunday one. This is the **only** measure on the site that separates
  Saturday from Sunday, and it can only do so because it describes the timetable
  rather than the passengers: GTFS names the days a service runs, and the
  patronage source publishes one undifferentiated Weekend band. So there is a
  Sunday service line and there is no Sunday patronage figure anywhere —
  including inside journeys per scheduled service, which divides by the weekend
  entire. The build checks that Saturday plus Sunday reconciles to that weekend
  figure, because the two come from the same calendar and cannot legitimately
  disagree.

## What each filter actually reaches

One filter rail sits beside five views, and not every cube carries every
dimension. The rule the site holds itself to is that a filter is either applied
or disclosed — never shown as applied and quietly ignored, and never applied
while the control denies it.

| | Mode | Operator | Route service | Time band | Ticket type |
|---|---|---|---|---|---|
| Network totals (Overview) | yes | route-series derived | only with an operator selected (route-series derived); otherwise all services | yes | yes |
| Route totals and profiles | by selection | yes | yes | yes | no — summed before storage |
| Stop rankings (month partition) | yes | yes, via the route on each cell | yes, via the route on each cell | yes | no |
| Stop boardings over eleven years | no — four columns per stop-month | no | no | no | no |
| Origin-destination flows | yes | no — the OD cube has no route dimension | no — the OD cube has no route dimension | no — stored per mode and day type only | no |
| Stop traffic by route | yes, via the route's own mode | yes | yes | yes | no |
| Rail service families | no — one recorded rail placeholder | yes, by matching the placeholder | no — rail is a modelled placeholder, not a route | yes | no |

Where a panel cannot honour an active filter it says so under the figures, and
where it cannot honour it the description says "all modes" or "every time band"
rather than echoing a selection it did not apply.

Operator is a canonical, shareable route-key filter (`op=`). Overview headline
totals and trends derive from the selected operator's route series, so they have
no ticket dimension; the ticket split and ticket anomaly panels remain
all-operator and say so. The long historical stop series and OD-based flow
panels also remain all-operator because their stored cubes have no route
dimension. Corridor profiles are shown only when their stored profile contains
no routes removed by the operator filter.

Route service scope (regular / school / all) is a frontend-only classification
of routes, not a column the source publishes — `lib/school-services.mjs` holds
the manually maintained operator/route lookup. It follows exactly the same rule
as operator, because it is derived from the same route dimension: it applies on
the Overview, route and stop views, and any cube with no route dimension —
network totals when no operator is selected, the ticket split and anomaly
panels, the long historical stop series, and OD-based flows — discloses **all
services** rather than honouring it.

There is one deliberate exception, in the other direction: **a panel does not
filter by the dimension it splits by.** The Overview's ticket mix does not take
the ticket filter, because narrowing it to one type would draw that type as all
of itself; the route page's time-of-day matrix takes neither the band nor the
direction filter, and the stop page's takes neither the band nor the mode, for
the same reason — a matrix that honoured them would have one cell. Each says so
under the table.

Two consequences worth stating plainly. A stop's eleven-year boardings line is
all-mode and all-band whatever is selected, while the flow panels below it on
the same page *are* mode-filtered and the ranking that led there *was*
band-filtered — one page, three honest answers, each stated on the panel it
belongs to. And a stop's traffic is not confined to one mode in the source:
South Bank ferry terminal recorded 260 bus and 111 rail alightings in July 2026
against 78,919 ferry ones, every one of them a tap the source filed against a
route of another mode. Those are shown as published, and the mode filter is what
takes them out.

## How route load is calculated

For a route and direction, the profile puts every stop in travel order and shows
boardings, alightings, and how many people were on board **between** each pair of
stops — load belongs to the segment, not the stop, because that is where the
passengers are.

The obvious method is the recurrence `load(i) = load(i-1) + boardings(i) −
alightings(i)`. This site does not use it. Because the source gives actual
origin-destination pairs, load is accumulated directly: a journey from stop *i*
to stop *j* is counted on every segment between them and nowhere else. The
difference matters — the recurrence leaks every journey whose ends fall outside
the route's stop sequence and drifts steadily, often negative, with no way to see
how far wrong it has gone. Pair accumulation cannot go negative, and journeys it
cannot place are excluded and counted rather than smeared along the route.

Loop-shaped routes need two more rules, because a stop can appear twice in one
sequence. On an out-and-back, the outbound and return stops are paired, so a
journey is drawn on the leg it rode; where the source cannot say which leg, the
journey takes a minimal-ride reading and is marked ambiguous. On a true loop, a
journey that crosses the route's start and end is wrapped round the loop rather
than dropped. Where an older timetable split a loop into two half-trips, they
are joined, so the profile covers the whole loop.

A profile can be narrowed to **any set of time bands**. The bands add: a load
line here is how many *journeys* crossed a segment during the month, not how
many people were aboard at one moment, so the morning peak plus the evening is
exactly those two bands and the four weekday bands sum to the weekday. Corridor
profiles take the same band selection as route profiles.

The load profile always keeps every on-board line in **monthly-total units** on
the left axis, including comparison years. The right-hand axis is the same
left-hand scale divided by the scheduled services for the selected month and
direction — not a separate line. It is explicitly labelled as the current
year's service level: comparison-year lines remain monthly totals and should be
read from the left axis rather than silently rescaled to their own timetables.
If the selected month and direction has no complete matched service
denominator, the right axis is omitted.

The load line is always marked **derived**, and every profile states the share of
journeys it could not place. Where that share exceeds half, a warning appears
above the chart rather than below it.

A route page also draws its stops on a map, sized by boardings, with the line
thickening where more people are on board. The line joins consecutive stops in a
straight line: the pipeline reads stop sequences, not road or track geometry, so
it shows the order and spacing of the stops rather than the path the vehicle
takes between them.

### Why some routes have no profile

The stop order comes from GTFS — the current feeds plus a set of archived
quarterly snapshots (see `data/qa/report.md` for the current count) going back
to February 2016. Each month is matched against whichever feed best
explains the stops its journeys actually used, so a route is drawn along the
network that was running at the time rather than today's. A route is matched
only if that overlap reaches 20%; below it, no profile is offered.

That guard is what stops a renumbered route being drawn along a service it never
ran. Routes **66** and **111** were the clearest case — they carried a large
share of Brisbane's patronage and have since become Metro M2 and M1, numbers
that still exist in today's timetable but describe different services. With
historical snapshots available both now match their own era and are drawn
correctly; 88 other routes still fail the overlap test and are reported as
`stops-do-not-match` in the build's QA report.

A route can also lose its profile for a *month* while keeping it either side,
when that month's direction resolution fails. That is what happened in April
2026: 46 routes went dark at once, including route 60, both Metro routes and
the Northshore ferry. The cause was the test that requires one direction to
beat the other by a margin, measured against every journey observed rather than
against the journeys a stop sequence could place. When the source's tap-off rate
collapsed, the denominator grew by a quarter while the numerator did not, and
routes whose orientation had not changed at all fell under the threshold. The
margin is now measured on placeable journeys, and the build fails if more than
five substantial routes lose a profile in one month rather than reporting it as
a coverage share that moved.

Separately, **1,957 routes match no GTFS route at all** and 5 are mode
placeholders rather than routes. Two thirds of all journeys sit on a matched
route — but most of the remaining third is placeholder rail and ferry, which
have no route to match *by construction*. Of the journeys that could in
principle be matched, 94% are.

## Corridors

A corridor is several routes that share a stretch of the network, analysed
together. Combined totals and year-on-year follow from addition. The load profile
does not, and is built carefully:

- The stop **order** comes from one real member route, never from chaining
  several routes' sequences together — which would draw a line no service runs.
- The corridor keeps only the stops that enough of the group's other routes also
  serve.
- A member is included only if its shared stops appear in the same order as the
  corridor's. One whose stops appear reversed is the other direction of travel;
  one whose stops are jumbled weaves across the corridor rather than following
  it. Both are excluded, and each panel lists what was left out and why.
- Journeys are projected by **traversal**: a journey counts on the corridor
  segments its own route order says it crosses. Most passengers ride *through* a
  shared segment rather than starting and ending inside it, so each panel states
  how many journeys actually travelled the corridor.

Expect that last figure to be low: across the curated corridors, well under
half of the journeys their member routes carried are placed on the corridor
itself — the rest began or ended outside the shared stretch. The current
figure, and how many corridors are curated, are build-derived and move as
corridors are added or routes are renumbered; see
[`data/qa/report.md`](data/qa/report.md) rather than a number fixed here. A
corridor profile describes the shared segment, not the routes that pass along it.

A corridor's **membership changes over a decade**, and its geometry changes with
it. Route 66 ran the UQ Lakes trunk until April 2025 and the Metro M2 has run it
since January 2025; the corridor spans both, resolved as one geometry per era,
so the series does not stop at the renumbering. Which era applies to the month
you are looking at is decided from the routes' own observed dates, not from a
hand-written list.

You can also save your own group of routes. Those are stored in your browser
only, never uploaded, and get every combined measure — but no corridor profile,
because the site does not know which stretch of road you had in mind.

## Rail

Rail is **station-to-station movement**, and it is the largest single thing in
this dataset: 402 million journeys, 28% of the whole record, all filed under one
placeholder route called `Rail`. The source records a tap-on station and a
tap-off station and nothing about the path between them.

This is why the QA report's "share of journeys on a matched route" reads well
short of a full match — see the current figure on
[`/translink/about/`](about/) or in [`data/qa/report.md`](data/qa/report.md)
rather than a number fixed in this document, which would drift as the record
grows. The missing share is overwhelmingly rail and ferry placeholders that
have no route to match by construction, not routes the matcher failed on. The
station explorer and the origin-destination views remain the account of what was
**observed**, and no figure in them is inferred.

### The Rail lines view is a model, and says so

There is now a second answer beside that one, and the difference between them
matters more than either. A curated analytical layer describes twelve heavy-rail
service families — Sunshine Coast, Caboolture, Ipswich/Rosewood, Redcliffe,
Springfield, Doomben, Shorncliffe, Cleveland, Airport, Gold Coast, Beenleigh,
Ferny Grove — as stable identities with their own histories, and the ETL
allocates each observed movement across the families that could plausibly have
carried it, weighted by the GTFS timetable in force in that month:

```text
generalisedCost = inVehicleMinutes + 1 × expectedWaitMinutes + 10 × physicalTransferCount
attractiveness  = frequency × exp(-0.08 × generalisedCost)
```

Attractiveness is normalised across the feasible alternatives, so a movement
between Central and Northgate — which Redcliffe, Caboolture and Sunshine Coast
trains all serve — is split between them by how often each runs and how long
each takes, not assigned to one of them.

**This is a model, not a measurement, and the site does not pretend otherwise.**
Every panel that shows it is marked *inferred*, the origin-destination view is
unchanged, and the numbers are bounded:

- **89% of rail journeys reach a family at all.** 8% are unresolved — no
  tap-off, the same station at both ends, a station the curated topology does
  not describe, or a month whose archived GTFS snapshot carries no active
  service. 3% begin and end inside the city core, where no radial line is
  implied and none is guessed.
- **82% are placed on a station.** A family's load profile is drawn from the
  journeys the model both allocated to it *and* could place on its evidenced
  stopping pattern. The gap between that and the 89% above is almost entirely
  journeys inferred to use two families: where the passenger crossed between
  them decides which leg carried which half, and the published partitions do
  not carry it. Those journeys are counted in every total and deliberately
  spread over no station. The shortfall is named on each profile.
- **Family totals do not add up.** One Cleveland–Caboolture journey is *one*
  network journey and counts against *both* families, so the family column is
  never summed and the site never totals it. A T number's total *is* offered,
  because the overlap inside one number is measurable and is subtracted: about
  2–3% of a T's journeys use two of its families.
- **Seven of the 126 months allocate nothing.** Their patronage is correct
  everywhere else; the model simply does not reach them. They are listed in the
  QA report and drawn as gaps rather than as zeroes.
- **The line number is not the line.** T4 is both Shorncliffe and Cleveland.
  Grouping by T number groups rows; it never merges two families into one, and
  no month claims which number a line carried at the time, because that has not
  been verified.

### A line's own page

Picking a family opens the equivalent of a route page — the month's figures with
its year-on-year change, patronage over time, the last twelve months against the
twelve before them, and the same calendar month across years — because the
questions a reader has about a line are the questions they have about a route,
and rail had no page that answered them. Everything on it is the same modelled
allocation as the table it was reached from, badged the same way, and the
non-additivity caveat travels with the trend chart rather than being stated once
at the top: a family total that may not be added to another family's is exactly
what a reader would otherwise take away from a chart read on its own.

The load profile below it draws **one direction at a time**, chosen with the
Inbound / Outbound toggle. The curated sequence runs outer to core, so the two
directions are two different shapes: a morning peak of alightings in the city
against an evening peak of boardings there would cancel into a flat line that
describes no hour of any day. The toggle switches between them and never
averages them. G:link's profile carries the same toggle over the compass
directions its own layer records.

### Journeys per scheduled trip

Rail has no route in the source, so it had no scheduled-trip count either, and
a line with a train every six minutes sat beside one with a train an hour with
nothing to separate them. The figure now comes from the GTFS variants that
evidence each line's curated stopping patterns, counted where they reach the
city end and turned into a monthly total the same way a bus route's is — so the
two are comparable by construction rather than by resemblance.

**The trips column is not additive across lines.** A train that runs through
from one line onto another is counted on both, because a journey using both
lines is counted against both, and a rate has to divide like with like. The QA
report publishes the overlap so it is a figure rather than a surprise.

The per-trip figure moves when you select an average weekday. The measure
itself divides out of the ratio — both halves are scaled the same — but
selecting a weekday also narrows both halves to weekdays, and a weekday train
carries more than a weekend one. That movement is the answer to a different
question, not an inconsistency.

A line whose month no timetable covers shows a dash, never a zero: "no feed
covered this" and "no trains ran" are different claims, and only one of them is
true. The same holds for the service-hour figure, which is withheld outright if
any part of the running time behind it is unknown — a sum over part of a line
divided into all of its journeys is not a less precise rate, it is a wrong one.

The figure reaches the routes index as well as the rail views, on both settings
of the rail toggle, and in all three of its rankings — the busiest routes, the
busiest routes for the service they get, and the full table. Shown **as one
route**, rail's denominator is the network's trips deduped across lines, so a
through-running train counts once — the trams are excluded, because the row is
heavy rail. Shown **as service families**, each line is divided by its own trips,
on the non-additive counting above. Those two denominators are different numbers
on purpose: the first answers "how much service does rail run", the second "how
much does this line run", and only the second is comparable with the bus route
beside it.

Light rail is the simpler case, and gets the trips heavy rail sheds. Its network
is a single curated line, so the line and the family are the same thing and both
settings of the toggle give it the same denominator.

### What a line page shows

A service family gets the same page a bus route does: the line in numbers, its
patronage over time, the last twelve months, every same calendar month, a split
by time of day, scheduled services over time, the load profile, the line on a
map, its busiest stations, and what the model means by the line.

The time-of-day panel splits by direction as the route page's does, but the
directions are not the same kind of thing. The source files one direction value
for rail, so the columns are the model's: each band's journeys are divided
between inbound and outbound — northbound and southbound on the light-rail
line — in the proportions the load profile placed them. The band total beside
them is what the source recorded and does not move. A month whose stopping
pattern could not be evidenced places nothing, and then has no direction columns
at all rather than an even split, which would be a symmetry the data never
showed. Each direction is divided by half the band's trains, assumed even, which
is slightly generous to the quiet direction where a peak extra runs one way only.

The busiest stations are deliberately narrower than the route page's equivalent:
they are the journeys the model *placed* on this line, not the station's own
totals, so a station on two lines appears on both with its journeys divided
between them rather than counted twice.

### Through running, and changing trains

Several Brisbane lines are one train. A service from Shorncliffe becomes a
service to Cleveland at the city end and nobody gets off. Drawn as a plain
sequence that reads as a wall of boardings at the city terminus and an on-board
line starting from zero at the other end, neither of which happened — so where
the model evidences a through service, the partner line gets its own entry at
the end of the sequence it continues past. Outbound it comes first and reads
*Continuing from T4 Shorncliffe*; inbound it comes last and reads *Continuing
to T4 Shorncliffe*. The line named is whichever one the model found, and a line
that runs through to two of them gets an entry for each.

Those journeys are **moved onto the entry, not added to it**. The model places
a cross-family journey by splitting it into two legs at the interchange, which
records an alighting there — an artefact of the split, since on a through
service the passenger stays aboard. So the entry takes them out of the
terminus rather than counting them again: the station's own total is unchanged,
and the on-board line runs through to the entry instead of stepping to zero.

At the curated interchange stations — the city core, the junctions, and the
highlighted stations — the share of a bar that **is** an interchange is drawn
inside it in purple. Inside, never on top: a passenger who changes trains
really does alight one line and board the other, so those journeys are already
in the bar, and stacking them above it would count every one of them twice. The
legend says *of which* for the same reason. A station's total is still every
boarding recorded there.

None of this appears until the data carries it. The published partitions were
written before the interchange was retained, so every panel here draws exactly
as it did before, and the shortfall the profile declares says so in as many
words.

### What "spanning multiple families" is not

About 7% of allocated rail journeys are inferred to use more than one service
family. That is **not** a transfer count, and it is **not** a count of line
changes either. Two families can carry the same number today — T4 is both
Shorncliffe and Cleveland — so a fifth of those journeys span two families
without ever leaving their T number. The view publishes both readings. Several family pairs are joined by through services,
so a passenger can cross from the Beenleigh family to the Gold Coast family
without leaving the train; where the timetable evidences that, the model records
no physical interchange, and it publishes that lower figure separately. The
wording throughout is *journeys spanning multiple rail service families*, and it
is quoted against two denominators — journeys allocated to a family, and all
rail journeys observed — because only an allocated journey can be classified at
all and choosing one denominator silently would be choosing an answer.

**None of this applies to buses.** A bus journey is one boarding of one vehicle
on a route the source names, the source links no two boardings to each other,
and nothing here infers a bus transfer or a bus interchange. The rail model
exists only because rail has no route in the source; a bus route already has one.

### G:link

Light rail is a placeholder too, but the current network is a single line, so
L1's journeys are *placed* on an evidenced stopping pattern rather than
allocated across candidates — the same arithmetic as any bus route's load
profile. The extent shown is the one the applicable GTFS feed evidenced for the
month you are looking at: the original Broadbeach South–Gold Coast University
Hospital line in 2016, and the Helensvale extension from 2018. The route's
identity and its totals do not change across an extension.

The line runs northbound and southbound, and the Direction control on its page
sets which one the load profile and the time-of-day table are drawn for. It is
not the direction filter a bus route carries: the source files every tram
journey under one direction value, so this is the model's reading of which way
each journey was travelling, derived from the order of its origin and
destination. The totals on the page are both directions together and do not move
with it.

**Ferry placeholders (2016-02 to 2019-02).** `BCC Ferries` and `BIT` are placed
the same way, but the result is *inferred*, and the route page says so.
`BCC Ferries` was the whole river network, not just CityCat: only journeys
between stops on the CityCat path (UQ St Lucia to Northshore Hamilton) are drawn
on its profile, and CityHopper and cross-river journeys stay origin-destination
only, so the profile covers part of the route's total. `BIT` is drawn on the
Southern Moreton Bay Islands loop, each journey taking the shorter way round; a
journey equidistant both ways is left unplaced. From March 2019 ferry routes are
named in the source and carry ordinary profiles.

The candidate paths behind every weighted rail allocation — frequency, running
time, expected wait, generalised cost and the resulting share — are on
`/translink/diagnostics`, which is a developer page.

## Stations and platforms

A rail station is several stops in the source, one per platform, so a station
total is their sum. Where GTFS gives a parent station the roll-up is exact and is
the default; a toggle drops back to the single platform. The same toggle sits on
both busiest-stops rankings, because that is where the distinction changes the
answer: by stop, a station's platforms compete as separate rows and none of them
says how busy the station is. Wherever the roll-up is on, a flow, a ranking row
or an origin-destination pair is **named for the station**, including the
stations GTFS gives a single stop — "Central station", not "Central station,
platform 1". Ordinary bus stops have
no parent, so the stop across the road stays a separate stop rather than being
guessed into a group. Every stop belongs to exactly one station, which is what
keeps a roll-up from counting anything twice.

The roll-up applies to the origin-destination view as well, where it is also the
default. At stop level a station's traffic is split across its platforms and a
journey between two of them is drawn as a line from a place to itself; at
station level those are counted as movements *within* the station and reported
as a figure rather than a line. Inside a station you can pick which of its stops
"this stop only" means — a fifteen-stop bus station was otherwise mostly
unreachable — and a station page splits its traffic by the routes it was
recorded against.

At a rail station that last split used to read *Queensland Rail* against most of
the station's traffic, which is what the source records and answers nothing. It
now names the service families the path model infers served the station that
month — *T2 Springfield*, *T4 Cleveland* — and it does so by **apportioning the
recorded figure** across them in the model's proportions rather than by
substituting the model's own counts for it. The distinction matters: the model's
placed journeys at a station are not the taps the source recorded there, so the
station's total is unchanged and still reconciles with the figures above it, and
only the split between the lines is modelled. Boardings and alightings are
apportioned separately, because a city station's inbound and outbound mixes
differ and one set of shares for both would flatten exactly the asymmetry the
two panels exist to show. Where the month's evidenced stopping patterns do not
reach the station — a branch terminus beyond a short working — the single
placeholder row stands, rather than a split the model cannot support.

Only where GTFS supplies the hierarchy, though: **769 of 20,270 stops (3.8%)
belong to a multi-stop station**. The rest stand alone. The QA report's count of
19,799 "facilities" is 298 real groupings plus every standalone stop counted as
its own — it is not 19,799 places.

## Coverage and limitations

- **The default view is South East Queensland, not the whole network.** The
  source expanded statewide in April 2026. Counting the new regional operators
  into a ten-year Brisbane trend would show a step change that is an artefact of
  coverage, so the area filter defaults to SEQ and the headline total is a SEQ
  total. Switch it to *All TransLink* for the network figure. Routes whose region
  cannot be determined (91 of 2,794, about 0.5 million journeys) appear only
  under *All*.
- **The source changed shape in March and April 2026.** See the section below.
  Comparisons spanning it are not like-for-like.
- **Some stops cannot be mapped.** 0.06% of journeys touch a stop with no
  recorded position anywhere — it was retired before any surviving reference.
  Those journeys are counted in every total; they simply cannot be drawn. 1,931
  stop ids appear in the extracts and in no reference at all.
- **Flows are capped.** A month holds around a quarter of a million distinct
  stop-to-stop pairs. Maps and tables show the largest and state what share of
  the month's journeys the drawn lines account for.
- **Origin-destination views exclude journeys with no tap-off**, which is most
  paper tickets.
- **The network changed, and the match follows it only in steps.** Stops opened
  and closed, routes were renumbered and restructured. A set of quarterly GTFS
  snapshots (current count in `data/qa/report.md`) tracks that, so each month is drawn against roughly the right era —
  but between two snapshots a month is matched to whichever explains its stops
  best, which is a nearest-fit, not the timetable of that exact month.

  Which era a month gets is decided **per direction**, not per route, and by
  more than stop coverage alone. Coverage asks how many of a month's observed
  stops a route version *contains*, which quietly favours the longer, older
  version of a route that has since been cut back — its withdrawn stops are
  still in the old feed. Route 345 outbound is the case that showed it: its city
  terminus moved to Queen Street by mid-2025, July 2026 was matched to the April
  2025 timetable whose sequence contains no Queen Street platform at all, and
  59% of its journeys could not be placed. Inbound, which still used a stop that
  feed had, kept the stale era alive for a direction that no longer ran it. Both
  the pooling and the tie-break are fixed, and the build now fails if a route's
  placement collapses month over month while it still carries journeys.
- **Public holidays count as weekdays.** The source does not identify them, so
  an "average weekday" in a month with two public holidays is diluted by them.

## What changed in 2026

Three changes sit close together near the end of the record. None has been
adjusted away. They are stated here as **comparison context** — what a reader
needs to know before reading a year-on-year figure spanning them — not as
explanations for the size of any particular change. The patronage dataset
alone cannot establish causation for a demand shift; where an operational or
external event coincided with one, that coincidence is stated as such.

**March 2026.** Recorded trips rose 51% against March 2025, having run at
+7.6% the month before. This coincided with the Strait of Hormuz fuel crisis
and sharply higher fuel costs — a coincidence in timing, not a demonstrated
cause. Source row counts rose alongside recorded trips, so the increase is
present in the underlying published data rather than being solely an
aggregation effect, and routes first seen that month account for only half a
million trips, which weighs against a simple ingestion or new-operator
artefact.

**April 2026.** Queensland Rail industrial action affected train services,
reducing schedules; some demand shifted to bus over the same period. As at
September 2026 the full rail timetable had not been restored. Separately,
several source-data measures step at once:

| | March 2026 | April 2026 |
|---|---|---|
| Journeys with no tap-off | 0.6% | 9.4% |
| Journeys not placeable on a stop sequence | 6.3% | 20.1% |
| Journeys touching a stop with no position | 1,973 | 48,136 |
| Ticket types this pipeline does not recognise | ~0 | 8.1% |

From April 2026 rail's year-on-year growth falls to 4–9% while bus runs at
38–51%. The industrial action and reduced rail timetable are context for that
mode shift, not a demonstrated explanation of its size. The ticket finding
below remains a separate data-quality issue: the new fare-product labels
primarily affect bus and ferry, so ticket-type shares are not comparable
across the boundary.

The same month, the published dataset also expanded to include regional
Queensland — a **coverage break**, not a change in travel: counting the new
regional operators into a longitudinal South East Queensland trend would show
a step that is an artefact of coverage rather than of patronage. This is why
the area filter defaults to South East Queensland, and why the headline total
is a SEQ total unless *All TransLink* is selected.

The practical consequences: origin-destination flows and load profiles from
April 2026 onward cover materially less of the network than earlier months, and
the ticket-type split is not comparable across the boundary. Totals and
boardings are unaffected — every journey is still counted, whatever its ticket
type or placement.

**August 2026.** Gold Coast Light Rail Stage 3 opened, extending G:link from
Broadbeach South to Burleigh Heads. Stage 3 operated for only part of the
month, so August 2026 is a transition month rather than a full-month read of
the extended line. From August 2026 onward, G:link patronage represents a
larger network with additional stops and new travel opportunities — a
different network from the one earlier months describe, not simply more of
the same line.

### The unrecognised ticket bucket

From April 2026 the source emits fare-product labels this pipeline does not map
to go card, paper or contactless — `Count` overwhelmingly, then `Daily`,
`Other`, `Unknown`, `Multi-Day`, `Multi-Trip` — and they are 8–10% of every
month since. Every one of those journeys is counted in every total on the site,
whatever its label. The question is whether they are journeys that newly
*arrived* in the record or journeys that were merely *relabelled*, because only
the first means the headline totals stepped.

They were relabelled. Three readings say so, and the Overview panel shows all
three:

- **The total did not move.** Within South East Queensland the bucket appears in
  April 2026 with 1,351,463 journeys, the named ticket types fall by 1,615,662,
  and the month's total *falls* by 264,200. Journeys entering the record for the
  first time would have raised it by roughly the size of the bucket.
- **It is not the regional expansion**, which is the obvious suspect since it
  lands in the same month. Only 47,422 of April's 1,430,952 unrecognised
  journeys are outside SEQ — about 3%.
- **It follows operators, not travel.** From April 2026 onward the bucket is
  13.3% of bus journeys and 6.1% of ferry, against 0.1% of rail and 0.1% of
  light rail. A change in how passengers pay would follow passengers.

The practical consequence: totals and boardings are unaffected, and the
ticket-type *split* is not comparable across April 2026, because a share before
it and a share after it are shares of differently labelled populations.

The build's own audit — coverage, unmatched routes, unplaced journeys, month by
month — is published with the data at
[`data/qa/report.md`](data/qa/report.md) and linked from the page footer.

## Provenance

Every built month records the dataset it came from, the resource id and URL, the
publication and update dates, when it was retrieved, and the SHA-256 of the file.
That is in `data/manifest.json` under `provenance`, and the latest available
month is shown in the page footer.

TransLink patronage data © State of Queensland (Department of Transport and Main
Roads), [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Network
topology from the TransLink GTFS feeds, same source and licence.

Developer documentation — running the pipeline, adding a corridor, refreshing the
data — is in [`data/translink/README.md`](../../data/translink/README.md).
