Cookies, localStorage, and sessionStorage.
Sweden's LEK chap. 6 §18 (transposing EU ePrivacy Directive Art. 5(3)) requires us to disclose every storage mechanism we use, even when none of it is third-party tracking. This page is that disclosure.
Effective: 2026-05-06 · Reviewed quarterly · Last review: 2026-05-06
Summary
- One first-party session cookie: httpOnly, SameSite=Strict, set only after sign-in. Strictly necessary, no consent gate.
- A handful of localStorage and sessionStorage keys: all first-party, used to keep your data offline-available and remember device-level UX preferences.
- No third-party cookies. No analytics SDKs, no advertising pixels, no social-share trackers, no fingerprinting.
- No consent banner for the storage on this page, it's all strictly-necessary or first-party functional, which doesn't require consent under ePrivacy. The GDPR Art. 9 health-data consent banner you see on first visit is a separate thing.
Cookies (HTTP)
| Name | Purpose | Lifetime | Legal basis |
|---|---|---|---|
vl_session |
Authenticates your session after sign-in. httpOnly + SameSite=Strict + Secure. JavaScript can't read it. | 30 days, sliding | Strictly necessary (ePrivacy Art. 5(3) exception) |
vl_csrf |
CSRF token paired with vl_session. Prevents cross-site request forgery on state-changing endpoints. | Session | Strictly necessary |
localStorage keys
All keys are first-party (vitalog.io) and persist across sessions until you sign out / clear browser storage / delete your account. None of these are sent over the network, they live entirely on your device.
| Key | Purpose | Retention |
|---|---|---|
vitalog-state |
Your encrypted protocols, logs, journal, bloodwork, workouts, nutrition. Lives on-device for offline access. | Until sign-out / delete account |
vitalog-visited |
Skip the landing page on return visits. Set to '1' after first visit. |
Until cleared |
vitalog-theme |
Light/dark theme preference. Set to 'light' or 'dark' when you click the theme toggle. Defaults to your system preference. |
Until cleared |
vitalog-gdpr-consentvitalog-gdpr-consent-date |
Records that you consented to the GDPR Art. 9 health-data processing notice and when. Consent is revocable in Settings. | Until consent revoked |
vitalog-device-id |
A device-scoped UUID for sync-source tagging (so we can dedupe edits made on multiple devices). Random; not linked to identity. | Until cleared |
vitalog-auth-tokenvitalog-auth-user |
Sign-in indicator. Used by client-side code to decide whether to render the signed-in UI before the server confirms via the httpOnly cookie. Cleared on sign-out. | Until sign-out |
vitalog-first-visit-atvitalog-has-loggedvitalog-install-dismissed-at |
Drives PWA install-prompt timing, only show after the user has visited 24h+ ago AND logged at least one entry. Pure UX heuristic. | 14 days (dismiss cooldown) / until cleared |
vitalog-tutorial-*vitalog-first-run-tour-donevitalog-swipe-tip-dismissed |
Records that you completed or skipped onboarding flows (first-run tour, swipe-tip overlay), so they don't show again. Boolean flags. | Until cleared |
vitalog-consent-error-reportingvitalog-consent-analyticsvitalog-consent-third-partyvitalog-cloud-data-consent |
Per-category consent toggles surfaced in Settings → Privacy. Recorded so we can prove the basis under GDPR Art. 7(1) and respect your choice without re-prompting. Each is independently revocable. | Until consent revoked |
vitalog-state-backupvitalog-last-auto-backup |
Local snapshot of your encrypted state, kept as a fallback if a sync write goes wrong. Cleared on sign-out / delete account, same retention as vitalog-state. |
Until sign-out / delete account |
vitalog-hlc-nodevitalog-sync-ancestorvitalog-tab-idvitalog-ratings-synced |
Conflict-resolution metadata for cross-device sync (hybrid logical clock node, last-known-common-ancestor pointer, per-tab id, optimistic-mutation tracker). All random or derived; never personally identifying. | Until cleared |
vitalog-langvitalog-chat-muted |
UI preferences (interface language, club-chat notification mute). Recorded only for your device. | Until cleared |
vitalog-dead-letter-countvitalog-dead-letter-list |
Self-healing diagnostic: counts and lists API-write attempts that failed retry so the app can re-queue them when connectivity returns. Cleared on successful drain. | Until drained or cleared |
Additional first-party vitalog-* keys may exist for feature-specific caching (chart data, daily-wrap cache, export tokens, etc.); they follow the same rules: first-party only, never sent over the network as a tracking signal, cleared on sign-out / clear-storage / delete-account. We update this table when we add a category that warrants explicit disclosure.
sessionStorage keys
sessionStorage is per-tab and clears when the tab is closed.
| Key | Purpose |
|---|---|
vitalog-tab-id |
Random per-tab UUID for the WebSocket sync connection. Lets multiple open tabs sync independently without colliding. |
vitalog-auth-uservitalog-auth-at |
Cached user object + login timestamp. Avoids a network round-trip to determine signed-in state on every tab. |
IndexedDB
Encrypted progress photos use IndexedDB for client-side blob storage (the encryption keys never leave your device). The vitalog-photos object store contains AES-256-GCM-encrypted ciphertext only, neither we nor anyone with database access can read the photos. Cleared on sign-out / account deletion.
No third-party storage
VitaLog does not embed advertising pixels (Meta, Google Ads, Twitter), social-share widgets, fingerprinting libraries, or any third-party identifying tracker. We do use Cloudflare Web Analytics for aggregate traffic counts (page URL, referrer, screen size, browser type). It sets no cookies, stores nothing in your browser, and does not identify individual users; the beacon goes to Cloudflare, the same entity that hosts our app (already disclosed in Privacy Policy §11). Typography fonts (Inter + Plus Jakarta Sans) are self-hosted from vitalog.io/fonts/; no requests go to fonts.gstatic.com or any other third-party font CDN.
If you want to verify this, open the browser's DevTools → Application → Storage. Filter by domain. We are vitalog.io and only vitalog.io.
Clearing storage
Settings → Privacy → "Clear local data" wipes every key listed above (you'll be signed out and any unsynced edits lost). Browser-level clearing also works: Site settings → Clear data.
Updates to this policy
We update this page whenever we add, remove, or repurpose a storage key. Material changes are announced in-app at least 30 days before they take effect.
Questions?
Cookie or storage-related questions go to privacy@vitalog.io. Privacy questions more broadly: see the Privacy Policy or write to the same address.