Privacy Recommended
Store each preference where it is needed
Keep a visitor's preferences in local storage when only the browser needs them. Use a cookie only when the server must know the preference before it answers.
How to do it
Local storage stays on the device and is never sent with requests. A theme or a dismissed notice belongs there, read by a tiny script in the head before the first paint. A cookie travels with every request, so the server can send the right language or currency at once. Give such a cookie Secure, SameSite=Lax and no longer a life than the preference needs. Under EU rules, storage the visitor asked for is usually exempt from consent, but say it in the privacy policy. Never set a cookie only for your own scripts to read. Wrap storage in try, because private windows can block it.
Example
| Question | Local storage | Cookie |
|---|---|---|
| Sent to the server? | Never | With every request |
| Server can use it for the first response? | No | Yes |
| Read before first paint? | Yes, from an inline script | Yes, by the server |
| Size | About 5 MB per site | About 4 KB each |
| Good for | Theme, layout, dismissed notices | Language, currency, region |
<!-- Local storage: applied before the first paint, never leaves the device -->
<script>try { const t = localStorage.getItem("theme"); if (t) document.documentElement.dataset.theme = t } catch (e) {}</script>
Set-Cookie: lang=sv; Path=/; Max-Age=31536000; Secure; SameSite=Lax
How to check
Set the preference and reload. It shows at once with no flash, and requests carry no cookie unless the server reads it.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers website playbook: https://agentwranglers.se/playbook/website/privacy/preference-storage.