Statistics
Since v2.3 the statistics are multi-domain. TravStats turns your travel log — flights and cruises — into numbers in two places:
- Dashboard widgets — at-a-glance summary above the map
- Statistics page (
/stats) — the deep dive, organised into a domain tab bar: an All cross-domain overview plus one tab per enabled domain (Flights, Cruises, …)
All numbers are computed server-side, rate-limited and scoped per-user. Because cruises now count too, totals such as countries visited or active travel days can be higher than in the flight-only v1.x — they aggregate every enabled domain, not just flights.
Which flights count
Section titled “Which flights count”- Time-insensitive stats (airport count, country count, continent
count, total distance, route counts, seat-class breakdown, milestone
year, achievements) include
flownplushistorical. Since v1.5.0, historical entries — old logbook flights you remembered as a date plus a route, without a precise departure time — contribute to your map and totals. Pre-v1.5 they were excluded from most rankings, so the same instance can show higher airport/country counts after the upgrade. - Time-sensitive stats (time-of-day buckets, layovers, durations,
fastest-route km/h, midnight crossings) stay
flown-only. Historical entries carry placeholder timestamps (DATE_ONLYsemantics) that would skew them. plannedandcancelledflights are counted only where it makes sense (totals, status pie).
Dashboard summary
Section titled “Dashboard summary”The bar above the map shows:
- Total flights — count of all flights regardless of status
- Total distance — great-circle sum across flown + historical legs
- Total flight time — sum of arrival − departure (timezone-aware, see time semantics for the contract)
- Countries visited — distinct ISO country codes touched
- Airlines flown — distinct (normalised) airline operators
- Cost (this year) — if you’ve entered prices anywhere
Each tile links to the relevant section on the Statistics page.
Statistics page
Section titled “Statistics page”Click Stats in the nav (or any dashboard tile). The page opens on a domain tab bar — an All overview tab plus one tab per enabled domain. The tab you pick decides what the rest of the page shows.
All tab (cross-domain overview)
Section titled “All tab (cross-domain overview)”A pure cross-domain summary — no per-domain deep-dives — built from every enabled domain at once:
- Range control — a year dropdown that scopes the whole tab to a single year (or All years for lifetime), plus a “compare with…” toggle that adds year-over-year deltas. The most recent year is auto-selected on first load.
- KPI strip — four headline tiles: Total experiences (all flights + cruises + …, with a per-domain breakdown underneath), Countries visited, Active travel days, and Achievements unlocked (with total points). Each carries a delta badge vs. the comparison year when compare is on.
- Activity per year — a stacked bar chart, one colored segment per domain (flights and cruises stacked together), one bar per year. Domain toggle chips above it add or remove series; the selected and compare years get a highlighted outline.
- Activity heatmap — a 12-month × 31-day calendar for the selected year. Each day cell is shaded by how active it was and colored by the dominant domain that day; hover shows the per-domain breakdown.
- Per-domain cards — a grid with one card per enabled domain, each showing that domain’s headline figures (distance and hours for flights; ports, sea days and cruise lines for cruises), top items, achievement badges, and a Details → link into the matching domain tab.
Flights tab
Section titled “Flights tab”The full flight deep-dive. It leads with the scorecard, then the classic per-metric sections below (Distance, Flight breakdown, Fun, Business, Unique, Airports, Seats).
Scorecard — a time-range segmented control (Rolling 12 months / Year / All time) drives three hero KPI tiles — Flights, Distance, Flight time — each with a sparkline, a trend delta vs. the previous comparable window, and a one-line takeaway. Below the tiles a single range-driven time-series chart plots the same window (bucketed by month, or by year for All time). This replaced the old separate “flights by year” / “distance by year” charts.
Two buttons sit at the top of this tab: Generate flight certificate and PDF year report (see Year report PDF).
Overview cards
Section titled “Overview cards”Four all-time tiles — total flights, total flight time, average flight duration, distinct airlines — under an “all-time” scope label, clearly separated from the year-scoped cards.
Pick a year from the dropdown to scope the summary cards to that year; toggle “compare with…” to display delta values vs. another year.
Charts section
Section titled “Charts section”- Flights by month — bar chart, 12 months
- Day-of-week — busiest weekday for departures
Distance section
Section titled “Distance section”- Total km
- Average distance per flight
- Longest single flight (with route + date link)
- Shortest single flight
- Distance distribution histogram
Flight breakdown
Section titled “Flight breakdown”- Status pie (flown / planned / cancelled / historical)
- Category pie (business / leisure / family / commute / unassigned)
- Aircraft type bar chart (if you’ve tagged aircraft)
Fun section
Section titled “Fun section”The lighthearted metrics from funStats:
- Timezone hopper — distinct IANA timezones visited
- Early bird / Afternoon / Night owl — flights by departure hour bucket
- Weekend warrior — count + percentage of flights on Sat/Sun
- Loyalty score — % of flights with your most-flown airline
- Short-haul king — count of flights under 500 km
- Long-haul pilot — count of flights ≥ 5,000 km
- Fastest day — busiest single day on record
- CO2 footprint in kg, and as elephants (1 elephant ≈ 4,000 kg)
- Milestone year — the year with most flights
- Route master — your most-flown route + count
Business section
Section titled “Business section”Spend metrics, computed from businessStats:
- Cost per km / per flight hour — only across flights with a recorded price; bookings count once even if they produced multiple legs
- Total cost in your currency
- Seat class distribution — % economy / premium / business / first
- Most common category
- Airport diversity — distinct airports visited
- Average flight duration — hours
- Busiest month
Unique section
Section titled “Unique section”The “interesting trivia” metrics from uniqueStats:
- Time travellers — flights where local arrival hour < local departure hour
- Equator crossings — North↔South hemisphere transitions
- Arctic flights — any leg crossing 66.5°N
- Ocean crossings — flights > 5,000 km (heuristic, no actual coastline check)
- Highest airport — by altitude in metres
- Northernmost / southernmost point
- Longest travel chain — consecutive same-airport hand-offs within 24 h
- Fastest route — highest average ground speed (capped at 1,200 km/h to ignore bad data)
- Most countries in a single day
Airports section
Section titled “Airports section”Top 20 airports by visit count, with arrows for most departed, most arrived, and first/last visit dates.
Seats section
Section titled “Seats section”- Window / aisle / middle distribution
- Row range histogram (front, middle, rear thirds)
- Seat consistency score (% of times you got the same letter)
Cruises tab
Section titled “Cruises tab”The cruise-domain deep-dive, served from GET /stats/cruise:
- Hero KPI grid — lifetime cruise metrics (number of cruises, unique ports, sea days, ships, cruise lines, total nautical distance, port calls, cruise days)
- Region distribution and a sea-day vs. port-day mix
- Depth + loyalty row (max deck, cruise-line loyalty streak)
- Discovery tag clouds — cruise lines, regions, countries visited
- Achievement-style flag pills — canal transit, polar / cold-water, dateline crossing, birthday or New Year at sea, balcony/suite cabin
Year heatmap (Flights tab)
Section titled “Year heatmap (Flights tab)”The Flights tab carries its own GitHub-style yearly calendar grid: each cell is a day, shaded by the number of flights that day. Hover for a tooltip with airlines + IATA codes; click a date to scroll to that day’s flights in the table. The year picker at the top lets you flip between any year you have flights in.
(This is distinct from the cross-domain Activity heatmap on the All tab, which counts every domain per day.)
Year report PDF
Section titled “Year report PDF”The Flights tab has two export buttons. Generate flight certificate opens a shareable certificate card (total flights, distance, flight time, top airline, favourite route, years active). PDF year report downloads a one-page PDF summarising the selected year. Both are useful as a screenshot-able year-in-review or to print as a memento.
Where the numbers come from
Section titled “Where the numbers come from”All endpoints sit under /api/v1/stats:
| Endpoint | Returns |
|---|---|
GET /summary | The headline numbers — total flights/distance/time/cost, status pie, airline pie |
GET /timeseries | Bucketed series (month/year) + current/previous window totals that back the Flights scorecard |
GET /routes | Per-route counts for the top-N table |
GET /fun | The Fun section metrics (funStats) |
GET /business | The Business section metrics (businessStats) |
GET /unique | The Unique section metrics (uniqueStats) |
GET /seats | Seat-class + position distributions |
GET /airlines | Per-airline aggregations (count, distance, hours) |
GET /aircraft | Per-registration aircraft (hull) ranking |
GET /countries | Per-country counts of arrivals/departures |
GET /cruise | Lifetime cruise stats behind the Cruises tab |
Most flight endpoints accept fromDate, toDate, and a year parameter;
/summary also takes an optional compareYear. /timeseries instead
takes domain (flight/cruise), granularity (month/year) and
window (rolling12m/year/all). Authentication is via cookie (UI) or
PAT with read scope (API).
The full request/response shapes are in
REST API, and the OpenAPI spec at
/api-docs for live exploration.
Limitations
Section titled “Limitations”- Distance uses great-circle, not actual flight path. No jet-stream rerouting, no waypoint-based correction. Real flown distance is typically 1–3 % higher
- Timezone-aware calculations need the airport’s IANA timezone in the cached airport database. Coverage is good (>95 % of commercial IATA airports) but private/general-aviation strips may fall back to “skip rather than guess”
- CO2 figures are rough. 0.25 kg/km short-haul, 0.20 kg/km long-haul, single-cabin assumption. Don’t use for offset certification — use a dedicated calculator like myclimate.org
- No multi-user aggregates. Every stat is scoped to your own flights. There’s no instance-wide “all users’ totals” dashboard; multi-user privacy is the design intent