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 analytics SDKs (Google Analytics, Plausible, Fathom, Mixpanel), advertising pixels (Meta, Google Ads, Twitter), social-share widgets, fingerprinting libraries, or any other third-party storage. The single external resource our pages load is Google Fonts (Inter + Plus Jakarta Sans) for typography, Google receives only a font request with your IP and User-Agent; no cookies or persistent identifiers are set by them on our origin.
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.