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 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.