Privacy and GDPR
This page is written for data-protection officers. It lists exactly what the 3x SDK reads from the visitor's device, when, and what the server stores. The legal assessment is on Legal basis.
Consent modes
The mode is a project setting (tracking.consent.mode, Settings → Tracking → Consent):
| Mode | Before consent | After consent |
|---|---|---|
cookieless (default) | Anonymous measurement without any storage on the device; reads listed below | Session id in sessionStorage, screen width, touch support, stored first touch, ad cookies |
strict | Only URL, referrer, language and clicks/events on the site's own elements; no viewport, scroll, section, visibility, Navigation Timing, screen or touch reads | As cookieless |
require | Nothing is measured; only the consent state is read | As cookieless |
Use strict when your DPO does not accept the necessity argument for viewport and scroll reads
under TDDDG § 25 (2) no. 2. Use require when you want measurement strictly opt-in.
What the SDK reads, and when
| Read | cookieless | strict | require |
|---|---|---|---|
Page URL and path, document.referrer, <html lang> | before consent | before consent | after consent (before consent only to learn the consent state) |
navigator.webdriver, window.top (iframe check) – to switch itself off for bots and embeds | before consent | before consent | before consent |
The project's consent key and the <prefix>notrack opt-out flag in localStorage (read only) | before consent | before consent | before consent |
Sec-GPC / navigator.globalPrivacyControl, DNT (when enabled) | before consent | before consent | before consent |
innerWidth / innerHeight (viewport and fold), scroll position and scrollHeight | before consent | after consent | after consent |
document.visibilityState (engaged time only counts while visible) | before consent | after consent | after consent |
| Navigation Timing type (load, reload, back/forward), prerender state | before consent | after consent (nav is load before) | after consent |
| Section visibility (IntersectionObserver on the site's own sections) | before consent | after consent | after consent |
| Click targets of the site's own content (kind, short label, link target, section) | before consent | before consent | after consent |
State of the site's own <video> elements (play position, duration) | before consent | before consent | after consent |
| Form ids on focus and submit (never field values) | before consent | before consent | after consent |
sessionStorage session id (<prefix>tsid) | after consent | after consent | after consent |
screen.width, navigator.maxTouchPoints | after consent | after consent | after consent |
Stored first-touch attribution (<prefix>attribution, only when enabled) | after consent | after consent | after consent |
Ad cookies _fbp, _fbc (Meta), _ttp (TikTok) – read only, shape-checked | after consent | after consent | after consent |
| CMP APIs (Cookiebot, Usercentrics, Complianz, Borlabs, Google Consent Mode) | when configured, to learn the consent state | same | same |
Writes before consent: none, with one exception – when a visitor opens a URL with
?<notrackParam>=1, the SDK stores the opt-out flag (<prefix>notrack) because the visitor asked
for it. No cookie is ever set by the SDK.
Before consent, ids (session, pageview) exist in memory only and die with the page. Without
consent, screen width = viewport width and touch is reported as false.
What is sent and stored
- Sent: the canonical page path (ids such as UUIDs and long numbers replaced by
:id; query strings never), referrer host (not the full URL), language, campaign parameters (cleaned: no e-mail- or phone-like values), viewport rounded to 10 px, scroll and engagement numbers, event names with identifier-like props, video coverage.identify()data only as SHA-256 hashes. - Not stored: IP addresses, user agents, cookies, form values, typed text, full URLs, query strings. The server derives the country (from an edge header), device class, browser and OS family, and a daily visitor hash whose salt is deleted after the day (Cookieless sessions).
- Personal pages (configured paths that identify a person, such as personalized letters) are isolated: random session, no hash, no referrer, no attribution, hour-truncated times.
- Free text is only accepted for event props you registered explicitly with
privacy: "text"; everything else must look like an identifier (≤ 80 characters, no e-mail or phone patterns).
Global Privacy Control
New projects honour GPC (respectGlobalPrivacyControl: true): a Sec-GPC: 1 header or
navigator.globalPrivacyControl is treated as consent denied – measurement continues cookieless,
but no consent upgrade happens. respectDoNotTrack does the same for DNT: 1 (off by default).
The CPI preset keeps GPC off for parity with cpi-website2.
Retention and erasure
| Data | Kept |
|---|---|
| Raw sessions, pageviews, events, video plays | retentionDays per project (default 180), deleted in chunks by the cleanup job |
| Daily salts and ingest budgets | Deleted after their day |
| Daily aggregates (no visitor data) | 3 years |
| Leads | Until erased, or settings.pii.leadsRetentionDays |
| Conversion request context (IP, user agent, ad cookies, company) | Until uploaded, at most 7 days |
| Audit logs | 365 days |
Erasure: DELETE /v1/projects/{project}/leads/{id} removes a lead and clears the hashes on its
conversions; POST /v1/projects/{project}/purge deletes a project's tracking data (sudo).
Because sessions carry no identifier, a visitor's analytics data cannot be singled out for access
requests – document this in your privacy policy.
Processor and DPA
3x processes data on your behalf. Without the first-party proxy the visitor's browser connects
to the 3x API host directly, so the visitor's IP address reaches the operator of the 3x deployment.
With the proxy the IP still reaches 3x – the proxy forwards it in x-3x-client-ip so sessions
can be told apart. Either way, a data processing agreement (Art. 28 GDPR) with the operator of the
3x deployment is required. When you self-host 3x, you are the operator; your hosting and database
providers are sub-processors.
Privacy policy checklist
- Purpose: reach and quality measurement of the website and advertising campaigns.
- Data: see What is sent and stored; no cookies before consent; daily-rotating visitor hash.
- Consent upgrade: what changes after consent (session continuity, screen size, ad cookies).
- Server-side conversions: which platforms, hashed identifiers, legal basis (Legal basis).
- Retention periods from the table above; processor and hosting location.