Incognito-Wiki/docs/superpowers/specs/2026-08-15-gdpr-matomo-tracking-design.md

82 lines
5.2 KiB
Markdown

# GDPR-Gated Matomo Tracking Design
## Goal
Add Matomo analytics to the Astro Starlight wiki without sending analytics requests or loading the remote Matomo client before a visitor explicitly consents. Visitors must be able to decline without losing site functionality and withdraw consent later.
This implementation supports privacy compliance but does not, by itself, guarantee legal compliance. The Matomo server configuration and the association's privacy documentation must match the behavior described here.
## Chosen approach
Use Starlight's global `head` configuration to load a small local consent controller on every page. The controller owns the consent interface and loads `https://analytics.msvincognito.nl/matomo.js` only after affirmative consent.
This follows Starlight's supported analytics integration point without overriding framework components. It also avoids making a request to the analytics host before the visitor chooses to participate.
## Visitor experience
- On a first visit, show an accessible consent banner that briefly explains first-party, cookieless analytics and links to `https://msvincognito.nl/privacy-policy`.
- Show equally visible **Accept analytics** and **Decline** actions. The wiki remains fully usable after either choice.
- Remember the choice locally so the banner does not reappear on each page.
- Keep a visible **Privacy settings** control available after a choice. It reopens the banner so consent can be changed or withdrawn.
- If browser storage is unavailable, fail privately: do not track automatically, and ask again on a later page load.
## Tracking behavior
The local controller uses a versioned, wiki-specific storage key with three states: no decision, accepted, or declined.
When the state is accepted, initialize `window._paq` and queue Matomo commands in privacy-first order:
1. require tracking consent as defense in depth;
2. disable analytics cookies;
3. grant consent for the current page load based on the stored choice;
4. set the HTTPS tracker URL to `https://analytics.msvincognito.nl/matomo.php`;
5. set site ID `1`;
6. track the page view and enable link tracking;
7. asynchronously load `https://analytics.msvincognito.nl/matomo.js` once.
When the state is declined, do not initialize Matomo or load any resource from the analytics origin.
When an accepted choice is withdrawn, queue Matomo's consent-revocation command if the tracker has already loaded, remove any Matomo cookies defensively, persist the declined state, and stop future tracking. The current page is not reloaded.
The current Starlight site uses normal document navigation, not Astro's `ClientRouter`, so each page load initializes at most one page view. The controller must still guard against duplicate initialization.
## Project structure
- Add one focused client script for consent state, UI behavior, and conditional Matomo loading.
- Register that script globally through `astro.config.mjs`, using the configured Astro base path so subpath deployments continue to work.
- Add the banner and settings-control styles to the existing `src/styles/incognito.css` file.
- Add focused Node tests alongside the existing tests. Tests should exercise observable behavior with a lightweight DOM rather than duplicate the implementation.
No third-party consent-management dependency is added.
## Accessibility and privacy requirements
- Use a labelled dialog/banner region with keyboard-operable native buttons.
- Move focus into the banner when privacy settings are reopened and restore a sensible focus target after a decision.
- Do not preselect consent, treat inactivity as consent, or make acceptance visually easier than refusal.
- Use clear language that identifies MSV Incognito, the analytics purpose, the cookieless configuration, and the withdrawal route.
- Do not record the consent choice in Matomo.
## Verification
Automated tests must verify that:
- no Matomo script or queue is created before consent;
- acceptance persists the choice and loads the expected HTTPS Matomo endpoint once;
- decline persists the choice without loading Matomo;
- withdrawal changes the stored choice, invokes revocation when possible, and prevents later initialization;
- the global Starlight configuration includes the local consent controller with base-path support;
- a production build contains the controller and consent UI styling.
Run the project's full `npm run verify` command after the focused red/green test cycle.
## Required operational follow-up
Before deployment, the Matomo administrator should confirm server-side IP anonymization, appropriate log and analytics retention periods, restricted administrator access, and that data is not repurposed for advertising or cross-site profiling. The privacy page must describe the analytics purpose, data categories, retention, controller identity, consent withdrawal, and data-subject rights.
## References
- [Starlight global head configuration](https://starlight.astro.build/reference/configuration/#head)
- [Matomo tracking consent API](https://developer.matomo.org/guides/tracking-consent)
- [Matomo JavaScript tracking API](https://developer.matomo.org/guides/tracking-javascript)
- [Dutch DPA cookie-banner guidance](https://autoriteitpersoonsgegevens.nl/actueel/ap-pakt-misleidende-cookiebanners-aan)