Summary
- There are no accounts. We never collect a login, email address, name, or phone number.
- There are no ads at all. We use analytics (Google Analytics) to understand usage, but your location, the music you edit, and your journey recordings are never sent to analytics (see below).
- Your device stores one anonymous random ID (a device ID). It doesn't identify who you are.
- If you're just listening, no location is sent to the server. Your position is sent only when you explicitly PUBLISH, and when you explicitly share a journey.
- A journey (a recorded movement log) contains a GPS track. Sharing one can reveal your home or workplace. Sharing always requires an explicit action, and a warning always appears beforehand.
Device ID
The first time you open the app, a random UUID (v4) is generated and stored in your device's localStorage under the key ptg:device-id. This isn't authentication — it's an anonymous ID used only to attribute published content and for server-side rate limiting and abuse prevention. It isn't linked to a name, email, advertising ID, or anything similar.
Clearing your browser storage, or using a different browser or device, gives you a different ID (in environments where storage isn't available, such as private browsing, you get a disposable ID every time you open the page). Exporting/importing a backup carries this ID along with it.
What gets sent to the server
Sending only ever happens in the situations below. For each one, here's exactly what's sent and what's stored.
- 1. Publishing (PUBLISH)
-
Sent only when you explicitly PUBLISH from the EDIT MENU. What's sent:
- The layer (AREA / SPOT) and the cell's ID and coordinates
- The edited pattern (the actual content — steps, pitches, resolution, and so on)
- Your tribe (RED / GREEN / BLUE)
- The generator version
- A key to prevent duplicate resends (an idempotency key)
- The device ID
- A Cloudflare Turnstile token (for bot detection)
- If a position is available, that fix (latitude, longitude, accuracy, and time acquired)
Stored on the server (Cloudflare D1): the full revision described above (layer, cell ID, coordinates, sequence number, device ID, pattern, generator version, idempotency key, creation time, tribe), the position fix (latitude, longitude, accuracy), a flag for whether that fix could be verified as inside the cell, and the country code Cloudflare derives from the connecting IP. The country code is only recorded — it's never used as a reason to reject a request.
The position fix is used to confirm you're inside the cell, and the latitude/longitude are stored after that check. If no position is available, no fix is sent and it's recorded as "unverified".
- 2. Listen beacon
-
Staying in the same cell for a certain amount of time while playing sends a small signal reporting that "this cell was actually listened to." It resets the decay clock and builds the footfall heatmap.
What's sent: the layer and ID of the cell you listened to, and the device ID.
What's stored: only a per-cell aggregate (layer, cell ID, coordinates, running count, last time). The device ID is never written to the database — it's only used in memory for rate limiting while the request is processed, and disappears once the request finishes. There's no record of who listened where.
What's shown on the map: the footfall heatmap is never drawn finer than AREA (~250m across). SPOT-level footfall (~70m across) only ever reaches the map summed into the AREA that contains it, and the API refuses to serve it at SPOT granularity at all (zooming in changes nothing). SPOT aggregates keep being recorded for the decay clock, but they are not shown at a granularity that would read as "somebody was standing at that address."
The same thinking applies to time: the "last listened at" time that leaves the server is coarsened to the day (that day's 00:00 UTC). At millisecond precision it would be a record that "somebody was in this cell at 14:32." Decay is computed per day anyway, so rounding it changes nothing about what you hear. (PUBLISH times are not rounded — publishing is a deliberate, attributed act.)
- 3. Report endpoint
-
There is no report button in the app (a published cell holds no free text, image, or audio, so there is little real harm for a report to protect against, and the button was removed). The endpoint itself remains for operator/contact-driven reports and for future journey reports. If it's ever used, what's sent: the target layer and cell ID, the device ID, and an optional reason. What's stored: the same, plus the time received and its handling status. See Help for details.
- 4. Sharing a journey
-
A journey contains your entire GPS track. Whoever receives your shared link can replay exactly the route you walked. That can reveal your home, workplace, or commute.
Sharing always requires an explicit action from you, and a privacy confirmation dialog always appears first. Simply recording or saving a journey sends nothing.
What's sent: a gzip-compressed stream of the journey's events (your GPS and listening path, a snapshot of the pattern and timbre for each cell, jumps made by tapping the map, edits made during recording, PLAY / STOP), plus the title, start time, duration, event count, device ID, and a Turnstile token.
What's stored: the journey itself in Cloudflare R2, with metadata (ID, title, start time, duration, event count, size, device ID, creation time, takedown status) in D1. The device ID here is deliberately kept so misuse can be moderated.
The share ID is a random 12 characters. Anyone with the link can play it back.
- 5. Loading the world
-
These are requests to load the reference time for playback sync, and published data for whatever range is currently shown. The device ID is never sent. All that's sent is the coordinates of the region needed. That said, since this is still a network request, Cloudflare does see your connecting IP address and the request time.
Retention and deletion
- Published content accumulates as an append-only history. Overwriting doesn't remove past revisions — the current content simply becomes the "published head".
- A takedown is a soft delete. If content is taken down following a report or operator decision, that revision is marked as taken down, stops playing, and the published head is reconstructed from the remaining revisions. The history row itself isn't deleted.
- Taking down a shared journey marks the metadata as taken down and actually deletes the underlying file (in R2). It also becomes unreachable via a direct link.
- Published cell content that nobody publishes to or listens to reverts, step by step, to its original generated content over 90 days, after a 14-day grace period (decay).
What stays on your device (never sent unless shared)
- Journeys (recordings) — IndexedDB (
ptg-journeys). Stays only on this device unless you share it. - Unpublished drafts — localStorage. Never sent until you PUBLISH.
- Tribe, language, movement FX settings, volume — localStorage.
- OUTPUT EQ — localStorage. A monitoring setting that never reaches the recording or the server.
- Backup files — export/import happens entirely on your device. Never sent to the server.
- Device ID — localStorage (
ptg:device-id).
Clearing your browser's site data erases all of this (anything already published, or any journey already shared, remains on the server).
About location
- Getting your location requires browser permission, and only starts when you press the GPS button.
- The position it acquires is processed on-device for the most part (determining which cell you're in, following you on the map, and reflecting it in the sound).
- Your position only ever reaches the server in two cases: the fix attached to a PUBLISH, and the track included in a shared journey.
- Just playing back or browsing the map sends no position.
Third parties reached just by opening the page
These connections happen just from loading the page, without you doing anything. Each of them receives your IP address and basic browser information (such as the User-Agent).
- Cloudflare (hosting, API, and data storage)
-
Handles delivering the site, the API, and storage in D1 and R2. It receives your IP address, connecting country, and a record of the request.
Cloudflare privacy policy - Cloudflare Turnstile (bot detection)
-
Bot protection used only for PUBLISH and journey sharing. The script only loads the first time you enter EDIT mode — it never loads if you're just listening.
Cloudflare privacy policy - CARTO (map tiles) / OpenStreetMap (map data)
-
The map's background imagery loads from CARTO's delivery servers. Which area of the map you're viewing (tile coordinates and zoom) is sent along with your IP address. The map data itself comes from OpenStreetMap.
CARTO privacy policy / OSM Foundation privacy policy - Google Fonts
-
The app itself loads a pixel font for the UI. The explanation pages — Help, Privacy, and Donation links (including this page) — also load a body typeface (LINE Seed JP). Both are loaded from
fonts.googleapis.com/fonts.gstatic.com, which sends Google your IP address and browser information.
Google privacy policy - unpkg (CDN)
-
Loads the stylesheet for the Leaflet map library from
unpkg.com. It receives your IP address and browser information.
- Cloudflare Zaraz / Google Analytics (analytics)
- Loaded to measure usage, only once consent has been given. Details, and exactly where the line is drawn on never sending location and similar data, are in the Analytics section.
Nothing else reaches out externally. There are no ad networks, no social-media tracking pixels, and no A/B testing tools.
Analytics (Google Analytics)
We use Google Analytics 4 (GA4) to understand usage across the whole site. It's delivered through Cloudflare Zaraz, rather than an analytics tag embedded directly in the app's code.
Your location (GPS), the music you edit, and the contents of your journeys are never sent to analytics.
Analytics only ever sees the granularity of "a page was viewed." Cell IDs, latitude/longitude, journey contents, and the device ID (ptg:device-id) above are never sent as analytics event parameters or custom dimensions. They only ever reach our own APIs listed above.
What analytics collects
- Page views (which page, when, and how many times it was opened; how URLs are handled is below)
- Referrer (where you came from)
- A rough region estimated from your IP address (country/region level — not a precise location)
- General information such as device and browser type, screen size, and language
-
Behavioral events — what you did. Only a fixed, predetermined set of types and choices is ever sent:
- Mode switches (PLAY / EDIT)
- Starting/stopping playback
- Starting/ending a journey recording, starting/ending a replay, and whether a share succeeded
- Whether a PUBLISH succeeded, and whether it targeted one layer or two
- Toggling the map's STAIN display, selecting an OUTPUT EQ preset, changing tribe, and exporting/importing a backup
All that rides along with these events is a fixed choice and a small number, like the ones in parentheses above. It's implemented so that free-text input or identifiers simply can't be passed through.
How URLs are handled — differs between info pages and the app itself
We record the URL to know which page was read, but this site has two kinds of pages with very different characters, so they're handled differently.
- Information pages (this Privacy page, Help, Donation links)
-
The URL is recorded as-is (
/help/,/privacy/,/support/). This is so we can tell which explanation page was read. These URLs contain no location — they only reveal which page was opened. - The app itself
-
The app's URL contains your current cell (
/{zone}/{area}/{spot}) — the URL itself is a coordinate. So before an app page view is sent to analytics, it's replaced with a constant value,/(the site's root), with the cell part stripped out. All that's recorded is "the app was opened" — this coordinate never reaches analytics.The address bar's URL is rewritten every time you walk into a new cell, but that rewrite is never sent to analytics either.
In short, all that's recorded is which of the information pages was read — where you were in the app can never be reconstructed from any page-view record. This handling is what keeps the promise made at the top: your location, the music you edit, and your journey contents are never sent to analytics.
About consent
Consent for analytics is managed by Cloudflare Zaraz's consent tool. Visitors from applicable regions are asked to confirm consent before analytics starts running. You can change or withdraw your consent at any time from the same consent banner (reopen it from the settings link shown on screen). Withdrawing stops all further analytics.
Cookies / identifiers used by analytics
Google Analytics uses a cookie (such as _ga) or an equivalent local identifier, to count visits from the same browser together. These are entirely separate from this app's own device ID (ptg:device-id), and the two are never linked. The device ID never reaches analytics, and no analytics identifier is ever tied to this app's world data.
Reference links: Google privacy policy / How Google Analytics uses data / Cloudflare privacy policy (Zaraz)
Cookies
The app's own state (drafts, settings, journeys, and so on) is stored in localStorage / sessionStorage / IndexedDB, not cookies. Cookies are used only for the analytics above and its consent management. Other third parties may also set their own cookies.
Use by children
There are no accounts or payments, and we never collect names or contact details. That said, since the app handles location data, a parent or guardian should be involved in deciding whether a child uses it. Sharing a journey in particular hands over the exact route walked.
Requesting removal or correction
- For published content — you can't take it down yourself, but anyone standing at that location can overwrite it with LOAD SEED → PUBLISH. If nobody visits, it decays back to its generated sound naturally (see Help). If it still needs attention, please contact us at the address below.
- For a shared journey, or for anything the above doesn't cover, please contact us at the address below. Telling us the share ID, or roughly where and when it was published, helps us find it.
- A device ID is an anonymous random value — we have no way to identify you from it. Because of that, please include information that identifies your request's target (share ID, URL, date/time, and so on).
Changes
If we change the content, we'll update the "Last updated" date on this page.