Skip to content

docs: describe stored data, consent, and storage limits - #231

Merged
sadjow merged 2 commits into
mainfrom
docs/privacy-and-consent
Oct 15, 2026
Merged

sadjow merged 2 commits into
mainfrom
docs/privacy-and-consent

Conversation

@sadjow

@sadjow sadjow commented Oct 14, 2026

Copy link
Copy Markdown
Member

The README described what the module stores in a few scattered sentences. This adds a Privacy and consent section and documents the storage limits that affect production sites.

Privacy and consent:

  • A table of the three keys the module writes, in localStorage and sessionStorage, and when each is written.
  • What each history entry holds, including the full landing URL with its query string and fragment.
  • A note that the module reads its keys and applies retention at startup even while tracking is disabled.
  • When consent is needed. It links Article 5(3) of the ePrivacy Directive, the EDPB's Guidelines 2/2023, and the UK ICO's guidance on storage and access technologies. It also explains why stored click IDs can be personal data under the GDPR. It states that the README is not legal advice.
  • A consent plugin example. It starts with tracking disabled, enables or disables tracking from the consent tool's callback, and checks consent in utm:before-track, because a saved preference outlives consent that expires without a callback.
  • A list of ways to collect less: fewer click IDs, captureWithoutCampaign: false, retention limits, and redacting the landing URL in a hook.

Storage limits:

  • Without retention options, every new tab that lands on the site adds an entry. At about 0.7 KB per entry, around 150 entries exceed Express's 100 KB default request body limit when a form sends the whole history, so the README suggests sending firstTouch and lastTouch.
  • localStorage holds about 5 MiB per origin. Once it is full, new visits stay in memory and are lost on reload. The README recommends maxEntries and usually maxAge.
  • Safari deletes storage written by scripts after seven days without a click, tap, or key press on the site, so a visitor who converts later loses the original first touch. Private windows discard history, and www and the apex domain keep separate histories. For long sales cycles, the README suggests sending the first touch to your server on the first visit and linking the later lead with a cookie your server sets, which Safari's seven-day limit does not cover.

The Composable section now also says that the server renders the configured trackingEnabled value, so displays of the tracking preference need <ClientOnly> just like displays of history. The click ID paragraph links to the new section instead of repeating it.

Each limit and legal reference links its source: WebKit's tracking prevention page, MDN's storage quota page, Express's body-parser documentation, EUR-Lex, the EDPB, and the ICO. The entry size and the 150-entry figure come from measuring the JSON that getAttribution() returns for seeded histories of realistic entries: 38.7 KB at 50 entries and 140 KB at 200.

Validation: pnpm format:check and pnpm lint --max-warnings 0 pass.

@sadjow
sadjow merged commit f4f4843 into main Oct 15, 2026
7 checks passed
@sadjow
sadjow deleted the docs/privacy-and-consent branch October 15, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant