Grail Atlas — Cookies
Last updated: 2026-08-01
What this is
The companion to the Privacy page, narrowed to the specific thing browsers call "cookies." Same stance: passion project, no ads, no advertising or cross-site trackers, minimum collection.
Two categories — that's it
| Category | Purpose | Consent |
|---|---|---|
| Essential | Sign-in sessions, CSRF protection, and remembering your cookie-banner choice. The site cannot function without these. | Always on |
| Analytics | Aggregate page counts + Core Web Vitals via Vercel (no cookie, ever). Traffic and product-usage analytics via PostHog, which sets a first-party cookie and a matching localStorage entry so a returning visitor can be recognized across sessions. | Off by default; opt in |
There is no advertising category, and no advertising or cross-site trackers. The site doesn't load Google Tag Manager, Meta Pixel, TikTok Pixel, or any equivalent. Vercel and PostHog are product-analytics tools, not advertising trackers — they don't follow you across other sites, sell data, or build an ad profile — but they are third-party services, so this policy names them rather than pretending the site runs on zero external code.
Your choices
On your first visit the site shows a small consent banner with two buttons: Essential only and Allow analytics. There's no third "Customize" button because there's nothing more granular to customize — the only non-essential category is analytics (Vercel and PostHog together), which is itself binary. You can change your mind anytime from the "Cookie settings" link in the footer. Declining analytics doesn't reduce access to anything on the site. Until you choose, only essential cookies run.
Cookies actually set
This is the live inventory. If the site sets a cookie that isn't on this list, that's a bug — email me at privacy@grailatlas.com.
| Name | Set by | Why | Lifetime |
|---|---|---|---|
__Host-csrf | Grail Atlas | HMAC double-submit CSRF token; protects mutating API routes. __Host- prefix, Secure, SameSite=Strict. | 1 hour |
sb-<project>-auth-token (and .0, .1 chunks) | Supabase Auth | Server-readable session token. Required if you're signed in (saved searches, Grail List). | Until logout (~7 days inactive) |
sb-<project>-auth-token-code-verifier | Supabase Auth | PKCE verifier used during the email-link callback. | 5 minutes |
gw-consent | Grail Atlas | Records your cookie-banner choice so it doesn't re-prompt every visit. First-party, Path=/, SameSite=Lax, Secure over HTTPS. | 24 months |
ph_<project_key>_posthog | PostHog | First-party analytics identifier, so a returning visitor is recognized across sessions. Only set if you click "Allow analytics"; never set otherwise. | ~1 year, or until you revoke consent (which clears it immediately) or clear it yourself |
Per-saved-search RSS feeds at /feeds/saved-search/[id]?token= use a query-string token, not a cookie. The token never appears in browser cookie storage; treat that URL like a bookmark.
Local storage actually set
PostHog's localStorage+cookie persistence mode makes localStorage the primary, durable store for your analytics identifier -- the cookie above is a mirror of the same value, not a separate identifier. Both are only written once you click "Allow analytics," and both are cleared immediately if you revoke.
| Key | Set by | Why | Lifetime |
|---|---|---|---|
ph_<project_key>_posthog | PostHog | Same analytics identifier as the cookie of the same name; this is the primary copy the SDK reads from. Only set if you click "Allow analytics." | Until you revoke consent (cleared immediately) or clear it yourself |
__ph_opt_in_out_<token> | PostHog | Records that you opted out, so a page load after revoking doesn't silently re-enable capture. Written when you click "Essential only" after previously consenting, or use "Cookie settings" to withdraw. | Until you clear it yourself |
Analytics — Vercel (no cookies) and PostHog (first-party cookie, consent-gated)
The site uses Vercel Web Analytics, Vercel Speed Insights, and PostHog to count page views, measure Core Web Vitals, and see aggregate traffic and usage patterns. The two work differently, and this policy used to blur that difference; here's the accurate split.
Vercel stays cookieless, always, whether or not you consent. No cookie, no local-storage entry, no persistent identifier on your device. Each page view sends a small event to Vercel, which derives a short-lived visitor identifier from a hash of the request (User-Agent + truncated IP + a daily-rotated seed). The identifier is discarded after 24 hours and never stored long-term. The raw IP is not stored; it contributes only to the hash and to a country-level geolocation lookup at ingest. No profile is built across sessions and no cross-site tracking is possible. Vercel's privacy doc for this layer is at vercel.com/docs/analytics/privacy-policy.
PostHog, unlike Vercel, does set a cookie. If, and only if, you click "Allow analytics," PostHog sets a first-party cookie (ph_<project_key>_posthog, see the inventory above) and a matching localStorage entry of the same name, so it can recognize a returning visitor across sessions. localStorage is the primary, durable copy of the identifier; the cookie mirrors it. That's the point: without them, a second visit from you looks like a new person, and we can't tell whether the site is retaining anyone. Both are first-party (set by grailatlas.com, not a third-party domain), carry no advertising identifier, and are never used for cross-site tracking. Nothing from PostHog loads, and no request goes to PostHog's servers, until you choose "Allow analytics." If you revoke consent -- by clicking "Essential only" again or using "Cookie settings" -- both the cookie and the localStorage entry are cleared immediately, not just left to expire; PostHog also writes a small __ph_opt_in_out_<token> localStorage entry at that point to remember that you opted out (see the inventory above). PostHog's privacy documentation is at posthog.com/privacy.
Both are gated the same way: nothing loads, and no request goes to Vercel or PostHog, until you click "Allow analytics." Clicking "Essential only" means neither one ever runs on your visit, and no PostHog cookie is ever set. If you'd rather I turn analytics off entirely on my end, email me.
Do Not Track and Global Privacy Control
Browsers' "Do Not Track" signal isn't standardized, but if your browser sends one, Grail Atlas treats it as a decision to decline non-essential cookies. The same goes for Global Privacy Control (GPC), the newer, better-supported signal some browsers and extensions send. Either signal overrides a stored "Allow analytics" choice: PostHog never initializes for a visit where DNT or GPC is present, regardless of what the consent cookie says.
Changes
Material changes re-trigger the consent banner. The "Last updated" date at the top of this page also changes.
Reach me
Privacy / cookie questions: privacy@grailatlas.com