Last updated: 2026-05-16
The short version
We set up to four first-party cookies. None is for marketing, analytics, or tracking. The session cookie carries your sign-in. The pending cookie lives only during the OIDC sign-in handshake. The language cookie remembers which interface language you chose. The coaching cookie keeps your place in a day’s coaching exercises.
We also run cookieless analytics via a self-hosted Umami instance. Cookieless means exactly what it says: zero cookies — and the script writes nothing to your browser’s storage either. There is one localStorage opt-out flag you can set yourself to switch the analytics off — details below.
That’s the entire policy.
Details — cookies
| Cookie name | Purpose | Type | Lifetime |
|---|---|---|---|
omk_session | Carries the signed session token. Required for sign-in to work. | First-party, HttpOnly, Secure, SameSite=Lax, encrypted | 30 days, refreshed on activity |
omk_pending | Carries the OAuth state value during the OIDC sign-in handshake. Cleared the moment sign-in completes. | First-party, HttpOnly, Secure, SameSite=Lax, encrypted | 10 minutes max — the OIDC round-trip |
lang | Remembers your interface language (en, nl, el) so you don’t have to re-pick on every page. | First-party, Secure, SameSite=Lax, no PII | 365 days |
omk_coaching_session | Keeps your place in a day’s coaching exercises — which exercise you’re on, what you completed this session, whether the pacing nudge was shown. No PII beyond your own session’s exercise state. | First-party, signed + encrypted (same protection as the session cookie) | 24 hours — clears itself so tomorrow starts a fresh session |
All four cookies are strictly necessary for the features they carry — the session + pending pair handle sign-in, the language cookie carries a no-PII preference that controls page rendering, and the coaching cookie exists only while you use the coaching exercises, holding the pacing state they need to work.
Details — analytics (cookieless, self-hosted Umami)
We run a self-hosted instance of Umami on a domain we own (analytics.cubeos.app). The Umami script is loaded as a deferred third-party script but it is explicitly cookieless — it sets no cookies on omoikane.coach, and it sends no cookies to analytics.cubeos.app (the analytics request goes out with credentials: omit). Server-side, Umami records anonymous aggregates only — no IP storage, no cross-site identifiers, no fingerprint persisted across sessions.
The script itself writes nothing to your browser’s storage. It honours one localStorage entry on omoikane.coach that you can set yourself:
| localStorage key | Purpose | Lifetime |
|---|---|---|
umami.disabled | Per-device opt-out flag. If you set this to 1 in your browser dev-tools (or via a privacy extension that injects it), the script stops sending any events from your browser. We never set this for you. | Persists until you clear browser data. |
The entry contains no personal data, identifiers, or anything joinable to your account. The whole point of running our own Umami is to get aggregate page-view counts without the surveillance overhead of a third-party analytics provider.
What we deliberately do not set
- Marketing cookies
- Analytics cookies (the analytics we run is cookieless)
- Third-party cookies set by us — we place none.
analytics.cubeos.appis operator-owned, served first-party for the analytics tag, and the analytics requests it receives carrycredentials: omit - Tracking pixels
- Cross-site fingerprint stores
Third-party services on the page
Two third-party services load on our pages, and you should know what they receive:
- Bunny Fonts (
fonts.bunny.net) serves our web fonts. Your browser sends it the usual request data — IP address and browser headers — to fetch the font files. It sets no cookies. - Cloudflare Turnstile (
challenges.cloudflare.com) is the bot-check widget on our contact form. The script loads on every page but only runs a check where a form embeds the widget. During a check, your browser exchanges bot-or-human signals with Cloudflare, and the widget may keep state inside its own frame. We receive only the pass/fail result — none of the browser signals reach us.
Why no banner
EU cookie law requires a consent banner only for cookies that are not strictly necessary for the service to work. The session cookie is strictly necessary (no session = no app), so no banner is needed.
If we ever set a non-essential cookie, you’d see a banner asking, and the answer would default to “no”.