privacy

last updated: 2026-05-16

This is the plain-language version of what sonderframe.works (the site) collects about visitors, why, and how to make it go away. The behavior described here matches what the code actually does. If you ever find a discrepancy, that's a bug — please tell me at young@sonderframe.works and I'll fix it.

tl;dr

what I collect

edge request logs (every visitor, including non-consenting EU visitors)

FieldDetail
tsWhen the request happened, millisecond precision (UTC).
Country, region, cityDerived from your IP by Cloudflare. Used for geographic aggregates.
ASN / network operatorHelps distinguish university/ISP/datacenter traffic.
User-AgentYour browser / OS, or the bot's identifier.
Referer (hostname only)e.g. google.com — not the full URL.
Path requested, status code, response size, response timeStandard HTTP log fields.
anon_hashAn irreversible SHA-256 hash of (IP + UA + today's date + a secret salt), truncated. Resets every UTC midnight, so I can recognize repeat hits within a day but cannot tie one day to another for non-consenting visitors.
ClassificationOne of human, verified_bot, ai_crawler, unknown_bot, suspicious. Computed from the user-agent and Cloudflare's bot signals.

IP addresses

I store your IP address only if (a) you're outside the EU/UK/EEA, or (b) you accepted the consent banner. Otherwise the IP is used once to compute anon_hash and is never written to disk.

behavioral events (only with consent or outside EU)

A small script sf.js on each page sends additional data about how you read:

This data is associated with your _sf_vid cookie (a random ID, see below).

cookies (only with consent or outside EU)

CookiePurposeLifetime
_sf_vidRandom visitor ID, used to recognize you across visits. Not linked to any external profile.1 year
_sf_sidRandom session ID, used to group requests within ~30 minutes of activity.30 minutes, sliding
_sf_consentStores your choice from the banner (granted or denied).1 year

None of these are HttpOnly because the analytics script reads them. None are third-party. All are SameSite=Lax.

what I do not collect

the mobile app (Thought-filled Words)

The Thought-filled Words app (iOS and Android) sends me two kinds of data. The behavior described here matches what the code actually does, same rule as above.

crash reports (Sentry)

If the app crashes, a crash report goes to Sentry so I can fix it. It contains the stack trace, app version, OS version, and device model — no name, no email, nothing you typed.

usage events (first-party, my own server)

The app records which parts of it get used — a word was viewed, the opening was skipped, the info panel was opened, a setting was changed, the purchase page was reached, a download finished — plus a few health signals (how long the app took to start, whether memory ran low). Each event carries the app version, OS version, device class (phone or tablet), and the app's display language.

These events are tied to a random install ID — a number the app makes up the first time it runs. It is not your advertising ID, not your device serial, not derived from anything about you, and deleting the app deletes it. I cannot connect it to you, and I don't try.

The events go to the same infrastructure as the site's analytics (my own VPS — see "who has access"). No IP address and no location are stored with app events — the server writes only what the app sent. There are no third-party analytics SDKs, no advertising SDKs, and nothing is shared with anyone.

what the app does not collect

app data retention

App usage events are kept for 2 years (a ClickHouse TTL enforces this), then deleted automatically.

why I collect it

legal basis (GDPR speak)

how long I keep it

who has access

Just me. No third-party analytics processors, no data brokers. The data lives on a small VPS I rent and on Cloudflare R2 (for backups). No data is shared, sold, or sent to advertisers.

Cloudflare and the VPS host are technical sub-processors: they handle bits flowing across their wires, not analytics queries.

your rights (GDPR / UK-GDPR / CCPA)

Contact for any of the above: young@sonderframe.works. I'll respond within 30 days as required by GDPR (and usually much sooner).

changes

If I change this page in a way that materially changes what's collected or who has access, I'll bump the date at the top and explain the change here.

← back to sonderframe.works