Skip to content

Anonymous usage statistics

TravStats can send a small, anonymous usage report to a public adoption-metrics service so the community can see how many installations exist and how they’re used. This is what actually gets sent, reproduced verbatim so you can diff it against your own instance’s traffic.

  • Opt-in. No ping is ever sent unless an admin explicitly agrees.
  • Off by default. A fresh install’s consent state is unset, which behaves identically to denied — nothing is sent.
  • Instance-wide, admin-controlled. The payload describes the installation as a whole (aggregated across every user), not an individual account, so the decision is made once, by an admin, for the whole instance — not per user.
  • You’re asked twice: once during first-run setup, and once via a one-time consent card in the “What’s new” dialog for existing installs. Either surface links back to this page.

This is the complete JSON body of every ping. Nothing is added, nothing is removed — if you capture your instance’s outbound request to stats.travstats.de/v1/ping, this is what you’ll see, field for field:

{
"install_id": "<random uuid4 hex>",
"version": "2.4.0",
"arch": "amd64 | arm64",
"enabled_domains": ["flight", "cruise"],
"users_bucket": "1 | 2-5 | 6-20 | 20+",
"flights_bucket": "<50 | 50-250 | 250-1k | 1k+",
"cruises_bucket": "0 | 1-5 | 6-20 | 20+",
"distance_km": { "flight": 128400, "cruise": 9200 },
"achievements": { "unlocked_total": 87, "keys": ["globetrotter", "night_owl"] },
"features": {
"llm_parser": true,
"backups": true,
"webdav_sync": false,
"historical_enrichment": false,
"live_tracking": true
},
"flight_api_providers": ["airlabs", "opensky"],
"locale": "de | en",
"reported_at": "<ISO 8601 UTC>"
}
FieldSource
versionThe running app version (any pre-release suffix like -rc.1 is stripped)
archThe server’s CPU architecture — x64amd64, arm64arm64
enabled_domainsThe union of enabled domains (flight, cruise, …) across every user account on the instance
users_bucketA bucketed count of user accounts
flights_bucketA bucketed count of logged flights
cruises_bucketA bucketed count of logged cruises — "0" is its own bucket, so “cruise domain enabled but never used” doesn’t disappear inside a <50-shaped range
distance_km.flightSum of flight route distances, rounded to the nearest 100 km. Flights without a resolved route contribute nothing, so this is a lower bound
distance_km.cruiseSum of cruise leg distances, rounded to the nearest 100 km
achievements.unlocked_totalTotal achievements unlocked across every user
achievements.keysWhich achievement types have been unlocked at least once, deduplicated — never a per-key count, and never tied to who unlocked it
features.llm_parserWhether any LLM parsing backend (Ollama URL, or a global OpenAI/Claude key) is configured
features.backupsWhether the scheduled backup job is enabled
features.webdav_syncWhether off-host WebDAV backup sync is enabled
features.historical_enrichmentWhether any user has historical flight-data enrichment turned on
features.live_trackingWhether any flight on the instance has live tracking data — there is no single instance-wide toggle for this
flight_api_providersWhich flight-data providers have a key configured (by name only — never the key itself)
localeThe most common UI language across users; ties resolve to English
reported_atTimestamp of the ping, UTC

Regardless of the above, TravStats never includes:

  • Your IP address or hostname
  • Filesystem paths
  • Airport, port, ship, or airline names
  • Travel dates
  • Usernames or e-mail addresses
  • API keys (only which providers are configured, never the values)
  • Exact counts — everything is bucketed or rounded, except the two distance sums and the achievement total, which are the only numbers sent as-is (and the distances are themselves rounded to the nearest 100 km)

A purely random uuid4, generated the first time an admin grants consent. It is never derived from an IP address, hostname, MAC address, database id, or any filesystem path — it exists only so a second ping from the same installation updates the same row instead of creating a duplicate. It is a dedup key, not a fingerprint.

You can find your instance’s install_id at Admin → Instance → Anonymous usage statistics. Quote it if you ever need to make an access or erasure request about your installation’s data.

Flip the toggle at Admin → Instance → Anonymous usage statistics back to off. This does two things:

  1. Stops all future pings immediately.
  2. Fires a request asking the server to delete this installation’s stored row — no e-mail required. If the server can’t be reached at that moment, the request is not retried; the row is then removed automatically once it falls outside the 180-day retention window (see below).

Self-hosters who want this guarantee enforced in their own configuration, independent of the admin UI, can set:

TRAVSTATS_STATS_ENDPOINT=""

An empty value disables all sending, unconditionally — regardless of what the consent toggle says.

  • An installation’s stored row is hard-deleted if it hasn’t been seen for 180 days, by a daily cleanup job on the server.
  • The daily active-install count used to draw the public growth chart is retained indefinitely, but it holds only a date and a count — no install_id, no link back to any individual installation.

The service rate-limits both the ping and erasure endpoints per client address to prevent abuse. The address is hashed in memory the moment a request arrives and the hash is discarded once its short window expires — the raw address is never written to disk, logged, or stored anywhere. The reverse-proxy configuration shipped for this service uses an access-log format that omits the client address entirely for this endpoint.

The stats endpoint is served through a Cloudflare Tunnel. Cloudflare terminates that tunnel and therefore sees every client’s IP address and full request content before it reaches the service — this is inherent to how a tunnel works and isn’t something TravStats’ code can avoid. Cloudflare, Inc. is a US company, so this is a transfer of personal data (the client IP) to a third country.