Tags: web-dev analytics concept

Cookies

Date: 2026-08-16


A small string the browser stores and sends back on every matching request. The attributes decide who can read it, how long it survives, and whether it works cross-site — and getting them wrong is either a security hole or a broken checkout.


What it is

A cookie is a name-value pair stored by the browser and attached automatically to subsequent HTTP requests matching its domain and path.

The automatic attachment is the whole point and the whole problem: it’s what makes sessions work without any application code, and it’s what makes cross-site request forgery possible.

server → browser        Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax
browser → server        Cookie: session=abc123        (on every matching request)

The attributes

AttributeDoesGet it wrong and
Expires / Max-AgeSets lifetime. Absent → session cookie, deleted on browser closeUsers are logged out, or logged in forever
DomainWhich hosts receive it. example.com includes subdomainsLeaks to every subdomain including third-party-hosted ones
PathWhich paths receive itRarely useful; not a security boundary
SecureHTTPS onlySent in clear over HTTP
HttpOnlyInvisible to document.cookieAny XSS on your site steals the session
SameSiteCross-site sending behaviourSee below
PartitionedSeparate jar per top-level site (CHIPS)Embedded third-party contexts break

HttpOnly and Secure on any session cookie, always. A session cookie readable by JavaScript turns a single XSS bug into full account takeover.

SameSite

The attribute that breaks things when changed, and the one worth understanding properly.

ValueSent on cross-site requests?
StrictNever — including when following a link from another site
LaxOnly on top-level navigations using GET
NoneAlways. Requires Secure

Strict on a session cookie means a user arriving from a Google result appears logged out, then logged in after any internal navigation — a confusing bug that reads as a session problem. Lax is the sensible default for sessions.

None is required for genuine cross-site use — embedded widgets, payment iframes, third-party analytics. Since it must be paired with Secure, and browsers are increasingly restricting third-party cookies regardless, it’s a diminishing option. See Browser Privacy Restrictions.

First-party and third-party

The distinction is about context, not who set it:

  • First-party — the cookie’s domain matches the site in the address bar
  • Third-party — it doesn’t. An analytics or ad cookie read while you’re on someone else’s site

The same cookie can be either, depending on where the user currently is. This is the mechanism behind cross-site tracking, and therefore the thing every browser privacy change has targeted.

Limits worth knowing

  • ~4KB per cookie, and browsers cap the number per domain. Exceeding it silently drops cookies rather than erroring
  • Sent on every matching request. A page with 30 subresources on your domain sends the whole cookie payload 30 times. Large cookies are a real upload cost on mobile — this is a good reason to keep application state in Client Storage instead
  • No cookie is set for localhost with Secure in some configurations, which is a recurring development-only confusion

Setting them

Server-side, in a response header:

Set-Cookie: id=abc; Max-Age=31536000; Secure;
  HttpOnly; SameSite=Lax

Client-side, in JavaScript:

document.cookie =
  "pref=dark; max-age=31536000; path=/; SameSite=Lax"

These are not equivalent in lifetime. Safari’s tracking prevention caps cookies set via document.cookie at seven days, while server-set cookies keep the expiry the server gave them. That single difference is why analytics tools increasingly recommend server-side cookie setting — see Browser Privacy Restrictions.

Practical

  • Sessions: HttpOnly; Secure; SameSite=Lax, server-set
  • Analytics identifiers: server-set where you can, for lifetime rather than security
  • Consent state: first-party, long-lived, and readable by JavaScript so the tag layer can gate on it — Consent Management
  • Never put personal data in a cookie. It travels on every request and is readable by anything with access to the domain — PII in Analytics
  • Audit what’s set. DevTools → Application → Cookies. Most retail sites carry cookies nobody can identify the owner of, which is both a performance cost and a compliance problem