The short version: local-first, explicit sharing.
Last updated: 25 June 2026
Your riding data starts in your phone's local storage. Recordings stay local unless you export them. Imported tracks stay local unless you enable device sync, which uploads those GPX files to OffTrail's protected sync relay so your paired device can download them. The app also shares anonymous usage statistics and crash reports (via Google Firebase) so we can fix problems and improve it — not your tracks, your routes, or where you ride. Other data leaves the device only when you use a feature that needs the network: live location during a Group ride session (over our own servers), event participation, basemap tile requests, and — when you use Track to or a track's off-road / on-road split is worked out — coordinates sent to a routing service. Each of these is described below.
What we collect on a server we operate
There is no rider profile and no leaderboard. What our own infrastructure does handle:
- Map tiles are served from our own tile service (with a public fallback for areas we haven't built yet). We keep aggregate request statistics — coarse 1° map cells and edge country — to know where the app is being used. No IP addresses are stored and requests are not tied to a device or person.
- Short-lived tokens for Group ride and tile access are minted by small Cloudflare Workers after a device-integrity check (Play Integrity / App Attest). The token request carries no personal data and no location.
- Device sync, when enabled, stores imported Home-track GPX files and small display metadata on OffTrail's sync relay so your paired device can mirror them. The relay is protected by the same device-integrity token, opaque group/device ids, TLS and rate limits. Recordings, Track-to routes and settings are not synced.
What stays on your phone
- Imported tracks (.gpx files) — up to five tracks at a time, kept under your iOS app's
Documents/Tracksfolder. Each track has a stable per-slot colour on the map. If you enable device sync, those imported tracks are also uploaded to OffTrail's sync relay for your paired device. - Recorded rides (.gpx + sidecar JSON) — kept under
Documents/Recordings. The History screen lists the last 30 days; older files are pruned automatically. - Offline map tiles — kept in MapLibre's local cache (auto-cached as you browse, plus any country regions you explicitly download from the Maps screen).
- Preferences — units (metric / imperial), app language override, rider display name, the "have you been prompted to leave a review" flag. Stored in
UserDefaultsvia@AppStorage; never transmitted.
You can back any of this up the way you'd back up any iOS app's local files (Files app, iCloud Drive backup, Finder sync). OffTrail does not provide account-based recovery.
Location
OffTrail asks for "When in Use" location permission so the user dot can render on the map and the rider can be tracked along an imported route. With your permission we keep listening to location updates while the app is in the foreground — that's how recording survives screen-lock and pocket use. Recording is suspended when the app moves to the background, to save battery. iOS shows its standard system blue bar while location is being used.
Your location is used in real time to render the map and write entries into your own ride recording. It is not transmitted anywhere — except during a Group ride session (sent to our own servers), or when you build a Track to route, where your position and destination are sent to a routing service. Both are described below.
Group ride (opt-in)
When you start or join a Group ride from Settings → Group ride, OffTrail shares your live position with the riders in your session over a realtime connection to OffTrail's own servers (a Cloudflare Durable Object — a small, single-session server instance). There is no third-party messaging provider, no OffTrail account, and no long-term storage — and it works the same between Android and iPhone riders. Specifically:
- You join by typing the host's short 6-character session code — no QR code, no camera, no Apple ID or iCloud sign-in.
- While the session is live, your rider name (the display name you set in Settings) and your live coordinates are sent over a WebSocket to that session's server instance, which relays the riders' names and positions back to draw their dots on your map. Updates are throttled (roughly every 30 seconds, and when you've moved a meaningful distance).
- This data is not stored long-term. The session instance keeps only the current roster (each rider's latest position) for the live session, so a dropped signal doesn't make you vanish; when you leave — or the session ends or expires — it is discarded. Everything stays on OffTrail's Cloudflare infrastructure (EU); no third party processes it.
- To open the realtime connection, a small Cloudflare Worker hands out a short-lived, single-session token. The Worker only ever receives the join request — the session code, the name you chose, the platform, and a device-integrity check — and does not receive or store your location.
- To curb abuse of that endpoint, the app attaches a platform device-integrity attestation (Google Play Integrity on Android, Apple App Attest on iOS). These confirm the request comes from a genuine app install; they carry no personal data and are not used to identify or track you.
- Nothing happens until you explicitly enter the Group ride flow. Riding solo never publishes your location anywhere.
Network requests we make
The app loads basemap tiles online when you're connected, so the map keeps looking fresh in places you haven't pre-cached. Tile requests go to:
- Our own tile service (tiles.offtrailapp.com, on Cloudflare) for the Base and Off-road styles — OpenStreetMap-based maps we build and host ourselves, with OpenFreeMap as a public fallback for areas we haven't covered yet. See "What we collect on a server we operate" above for the aggregate statistics this produces.
- Esri World Imagery for the optional Satellite style. Satellite tiles are pulled live every render — there is no offline cache for satellite. The Esri terms require us to display the attribution string "Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community" whenever satellite is on screen, which OffTrail does in the bottom-right caption above the MapLibre attribution.
- Open-Meteo for the live weather chip on the Ride screen (current temperature + condition icon, e.g. sun 24°C / rain 10°C). Before any request leaves the device, your GPS coordinates are coarsened to two decimal places (≈1.1 km at the equator, less at higher latitudes) so the upstream sees an approximate location, not your exact dot. Open-Meteo is free, requires no API key, and is only queried while you have a network connection — the chip simply doesn't render offline.
These requests are subject to the respective providers' privacy policies. OffTrail does not intercept, log, or proxy any of them. If you are fully offline, the app falls back to what you have cached (or, for satellite, surfaces a "Satellite needs network" banner; for weather, the chip just hides).
Routing & place names (Track to, off-road split)
Two features send coordinates off the device, because the work can't be done offline on the phone:
- Our routing service (routing.offtrailapp.com) — routing. When you use Track to (or the round-trip planner), your current position and the destination are sent to our routing service to build an off-road route. The same service works out the off-road / on-road split shown on a track's preview: the track's coordinates are sent so each stretch can be matched to a road or trail. These are your exact coordinates — routing needs the precision, so they are not coarsened the way the weather request is. The service runs on Cloudflare and currently forwards the route computation to BRouter, a free public routing engine; requests to our service carry the same short-lived device-integrity token as the tiles (no identity, no personal data). OffTrail computes a track's split automatically when you import it (and when you open a preview that doesn't have it yet), if you're online; the result is then cached on your phone, so it isn't re-sent each time. Track to falls back to a straight line and sends nothing when you're offline.
- Apple — place names. To label a generated route "{start} → {destination}", the two endpoint coordinates are sent to Apple's reverse-geocoding service to look up the nearest place names. Apple is the data controller for that lookup; their privacy policy applies.
What our routing service keeps. Coordinates are never logged, and no IP address is stored. We keep aggregate statistics in the same spirit as the tiles: request counters (route type, success/failure, coarse 1° map cell of the route's midpoint, edge country) and — for generated routes only — an anonymised "popular corridors" heatmap: a sparse sample of the computed route's geometry, rounded to a ~1 km grid, with the first and last 500 m of every route discarded so neither your start point nor your destination is ever retained. Surface-split (map-match) requests carry your own recorded track, so they are excluded from the heatmap entirely. Nothing links any of this to a device or person.
External links from inside the app
The About screen has two opt-in outbound links: Share OffTrail (system share sheet seeded with the App Store URL + a short pitch) and Follow on Instagram (deep link to @offtrailgpx, falls back to Safari if Instagram isn't installed). Both open in their respective destinations and are subject to those services' policies. OffTrail does not collect anything before, during, or after the tap.
Review prompt
After three saved recordings on the same install, OffTrail asks iOS to surface its native App Store review sheet (SKStoreReviewController). The sheet runs entirely inside the system frame; we do not see your review or rating. Apple's own throttle limits this prompt to at most three appearances per rider per 365 days across the whole iOS device. We additionally store a one-shot flag locally so OffTrail itself doesn't re-prompt within the same install.
Analytics & crash reports (Google Firebase)
Since v1.14.1 (iOS) / v0.83 (Android), OffTrail uses Google Firebase for two things, on both platforms:
- Crashlytics — when the app crashes, a crash report (stack trace, device model, OS version, app version) is sent so we can find and fix the bug.
- Analytics — anonymous usage events such as "a ride was started", "a GPX was imported", or "the round-trip planner was used", plus the standard Firebase dimensions (device model, OS version, app version, country). This tells us which features matter and where the app struggles, so we can improve it.
What is never sent to Firebase: your GPS coordinates, your tracks or recordings, track names, routes, or anything that says where you ride. Events are feature counters, not location data. We don't create accounts or identifiers of our own; Firebase uses a per-install app identifier to group events (Google acts as a processor — see Firebase privacy). This data is used only to improve OffTrail.
No ads, no ad tracking. OffTrail has no ad SDKs, no cross-app tracking, and nothing is shared or sold for advertising.
Cookies & website analytics (this site only)
This website uses Google Analytics to understand visits — which pages are read, from which countries, on which devices. It only runs after you accept the cookie banner; decline (or simply ignore it) and no analytics cookie is ever set. This applies to offtrailapp.com only — the app sets no cookies and is covered by the Firebase section above.
- What it collects: page views, approximate location (country/city), device and browser type. IP anonymisation is on. No names, nothing linked to you.
- No ads: no advertising cookies, no remarketing, no cross-site tracking. Analytics only.
- Change your mind: click here to reset your cookie choice — the banner will ask again.
Aside from this opt-in analytics cookie, the site sets none. Your banner choice itself is stored locally in your browser (localStorage), not on a server.
Children
OffTrail is rated 4+ but is not directed at children. Because we don't collect any personal data, no special children's-data provisions apply.
Changes to this policy
When we add a feature that changes what leaves your device, we say so plainly here and update the "Last updated" date. The core stance is a product principle, not a phase: OffTrail is local-first, and network features should be explicit and understandable.
Contact
Questions or pushback: [email protected].