Skip to content
Cookie Policy

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

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-consent
vitalog-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-token
vitalog-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-at
vitalog-has-logged
vitalog-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-done
vitalog-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-reporting
vitalog-consent-analytics
vitalog-consent-third-party
vitalog-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-backup
vitalog-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-node
vitalog-sync-ancestor
vitalog-tab-id
vitalog-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-lang
vitalog-chat-muted
UI preferences (interface language, club-chat notification mute). Recorded only for your device. Until cleared
vitalog-dead-letter-count
vitalog-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-user
vitalog-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.