Skip to content

Statistics

Since v2.3 the statistics are multi-domain. TravStats turns your travel log — flights and cruises — into numbers in two places:

  1. Dashboard widgets — at-a-glance summary above the map
  2. 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.

  • Time-insensitive stats (airport count, country count, continent count, total distance, route counts, seat-class breakdown, milestone year, achievements) include flown plus historical. 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_ONLY semantics) that would skew them.
  • planned and cancelled flights are counted only where it makes sense (totals, status pie).

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.

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.

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.

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).

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.

  • Flights by month — bar chart, 12 months
  • Day-of-week — busiest weekday for departures
  • Total km
  • Average distance per flight
  • Longest single flight (with route + date link)
  • Shortest single flight
  • Distance distribution histogram
  • Status pie (flown / planned / cancelled / historical)
  • Category pie (business / leisure / family / commute / unassigned)
  • Aircraft type bar chart (if you’ve tagged aircraft)

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

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

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

Top 20 airports by visit count, with arrows for most departed, most arrived, and first/last visit dates.

  • Window / aisle / middle distribution
  • Row range histogram (front, middle, rear thirds)
  • Seat consistency score (% of times you got the same letter)

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

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.)

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.

All endpoints sit under /api/v1/stats:

EndpointReturns
GET /summaryThe headline numbers — total flights/distance/time/cost, status pie, airline pie
GET /timeseriesBucketed series (month/year) + current/previous window totals that back the Flights scorecard
GET /routesPer-route counts for the top-N table
GET /funThe Fun section metrics (funStats)
GET /businessThe Business section metrics (businessStats)
GET /uniqueThe Unique section metrics (uniqueStats)
GET /seatsSeat-class + position distributions
GET /airlinesPer-airline aggregations (count, distance, hours)
GET /aircraftPer-registration aircraft (hull) ranking
GET /countriesPer-country counts of arrivals/departures
GET /cruiseLifetime 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.

  • 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