Legal disclaimer: This document describes the technical data-processing architecture of Mallard Metrics and provides general information about applicable privacy regulations. It is not legal advice. Every operator deploying Mallard Metrics bears independent responsibility for complying with data protection law in their jurisdiction. Consult a qualified data protection attorney before deploying this software to process data from real users.
- What Data Is Processed
- What Is and Is Not Stored
- Visitor Identification Architecture
- GDPR Analysis
- ePrivacy Directive (Cookie Law)
- CCPA Analysis
- The GitHub Pages / Live Demo Question
- What Operators Must Do
- What Mallard Metrics Does Not Do
- Comparison with Other Analytics Tools
- Definitions and Primary Sources
Every HTTP request to POST /api/event (or GET /api/event for pixel tracking) causes the
server to process the following data. "Process" under GDPR means any operation performed on
data, including reading it from a request header — storage is not required for processing to
occur.
| Data item | Source | Purpose | Lifetime |
|---|---|---|---|
| IP address | X-Forwarded-For / X-Real-IP / socket |
GeoIP lookup + visitor ID derivation | Single request (~µs); dropped when handler returns |
| Raw User-Agent string | User-Agent request header |
UA parsing + bot detection + visitor ID derivation | Single request (~µs); dropped when handler returns |
No IP address is ever written to the event buffer, to DuckDB or to Parquet. On the
analytics path it is never logged either: it exists only for the duration of the request,
as GeoIP input and as HMAC input. The relevant code is in src/ingest/handler.rs and
src/ingest/visitor_id.rs.
There is one deliberate exception, and it is not on the analytics path. Authentication
events — a failed login, a lockout, first-run setup, a logout, an API-key operation —
log a truncated client address so an operator can investigate an attack against the
dashboard. anonymize_ip (src/api/auth.rs) keeps the IPv4 /24 or the IPv6 /48
prefix and discards the rest; a value that does not parse as an address is replaced with
a fixed placeholder rather than echoed. These lines identify a network, not a person, and
they are written only for operator-authentication activity, never for a site visitor.
Whether they persist at all is a property of the operator's log retention, which is
outside this application's control — see GDPR obligations this triggers.
| Field | Type | Example value | Retained |
|---|---|---|---|
visitor_id |
64-char hex string | a3f2…c9d1 |
Until partition deleted |
timestamp |
UTC datetime | 2024-01-15T14:23:01 |
Until partition deleted |
event_name |
String | pageview |
Until partition deleted |
site_id |
String | example.com |
Until partition deleted |
pathname |
String | /pricing |
Until partition deleted |
hostname |
String (optional) | example.com |
Until partition deleted |
referrer |
String (optional) | https://google.com/search?q=… |
Until partition deleted |
referrer_source |
String (optional) | Google |
Until partition deleted |
utm_source |
String (optional) | newsletter |
Until partition deleted |
utm_medium |
String (optional) | email |
Until partition deleted |
utm_campaign |
String (optional) | spring-sale |
Until partition deleted |
utm_content |
String (optional) | hero-cta |
Until partition deleted |
utm_term |
String (optional) | analytics software |
Until partition deleted |
browser |
String (optional) | Chrome |
Until partition deleted |
browser_version |
String (optional) | 120.0 |
Until partition deleted |
os |
String (optional) | Windows |
Until partition deleted |
os_version |
String (optional) | 10.0 |
Until partition deleted |
device_type |
String (optional) | desktop |
Until partition deleted |
screen_size |
String (optional) | 1920 |
Until partition deleted |
country_code |
String (optional) | DE |
Until partition deleted |
region |
String (optional) | Bavaria |
Until partition deleted |
city |
String (optional) | Munich |
Until partition deleted |
props |
JSON string (optional) | {"plan":"pro"} |
Until partition deleted |
revenue_amount |
Float (optional) | 49.99 |
Until partition deleted |
revenue_currency |
String (optional) | EUR |
Until partition deleted |
Retention period is controlled by MALLARD_RETENTION_DAYS (default: 0 = unlimited).
| Claim | Accurate? | Nuance |
|---|---|---|
| IP addresses are not stored | Yes | Not written anywhere to disk. Processed in RAM per-request only. |
| Raw User-Agent strings are not stored | Yes | Only four parsed fields (browser name, version, OS name, version) are stored. |
| Visitor IDs are pseudonymous, not anonymous | Yes | See Visitor Identification Architecture. |
| Geographic data is stored | Yes | country_code, region, city are derived from the IP and stored permanently. |
| Referrer URLs are stored | Yes | May include search queries or campaign parameters sent by the browser. |
Custom props are stored |
Yes | Operators control what custom properties are collected via the tracking script. |
The phrase "no PII storage" as commonly used in analytics marketing means: no directly identifying personal data (name, email, full IP address, raw User-Agent string) is written to disk. That characterisation is accurate for Mallard Metrics.
However, under GDPR, pseudonymous data is still personal data (GDPR Recital 26; Art. 4(5)). The stored visitor ID hash is pseudonymous personal data. The stored geographic data was derived from an IP address (personal data). GDPR therefore applies to the stored data, not only to the ephemeral processing.
Step 1 — Salt derivation:
Key: MALLARD_SECRET
Input: "mallard-metrics/salt/v2" + "|" + salt_period
where salt_period = floor(days_since_epoch / visitor_salt_rotation_days)
Output: salt (64-char hex)
Step 2 — Visitor ID derivation:
Key: salt (from Step 1)
Input: SITE_ID + "|" + IP_ADDRESS + "|" + USER_AGENT
Output: visitor_id (64-char hex, stored in Parquet)
Source: src/ingest/visitor_id.rs.
Two properties are worth calling out:
- The secret is the HMAC key, not part of the message. This is the conventional construction and means the secret's full entropy contributes as key material.
- The site ID is part of the input. Without it, one person visiting two
sites hosted on the same instance produced the same identifier on both, so
anyone able to read the stored data could correlate them across sites. Because
every query already filters by
site_id, this costs nothing analytically.
Salt periods are numbered from the Unix epoch, so period boundaries do not drift with when the process happened to start.
| Property | Guaranteed | Notes |
|---|---|---|
| IP not stored | Yes | Only the hash output is retained |
| Different visitors produce different IDs | Yes | Property-tested |
| Same visitor produces the same ID within a salt period | Yes | Enables deduplication without cookies |
| Same visitor produces different IDs across salt periods | Yes | Salt rotates every visitor_salt_rotation_days (default: 1) |
| One visitor is not correlatable across two sites | Yes | The site ID is part of the HMAC input |
| ID cannot be reversed to recover the IP | Practically yes | HMAC-SHA256 is one-way; brute-force over the IP space is impractical without the secret |
Salt rotation is the mechanism that keeps a visitor ID from becoming a long-lived identifier. It is also, unavoidably, the thing that limits what the analytics can measure — and the two cannot be separated. Being explicit about it matters more than presenting a number that looks precise.
With the default one-day rotation:
- "Unique visitors" over a multi-day range counts visitor-days, not people. A person who visits every day for a month contributes about 30 to a 30-day unique-visitor figure. The number is not wrong so much as differently defined, and it is the same definition Plausible and similar cookieless tools use.
- Weekly retention cohorts cannot work at all. A visitor returning in week 1
carries an identifier unrelated to the one they had in week 0, so retention
past the first week is structurally zero regardless of how loyal the audience
is.
GET /api/stats/retentionreports this in anidentity_supports_cohortsfield and an explanatorycaveatrather than presenting the zeros as a finding. - Sessions spanning UTC midnight split in two. A visit from 23:55 to 00:05 is recorded as two visits.
Raising visitor_salt_rotation_days makes those measurements meaningful, at a
real privacy cost: the identifier survives longer, so the window in which an
operator holding both the secret and contemporaneous network logs could correlate
a visitor to an IP grows correspondingly. Retention over N weeks needs a
rotation of at least (N - 1) × 7 days.
This is a deployment decision with a legal dimension, not a tuning knob. If you raise it, say so in your privacy notice and record the reasoning in your Art. 30 record.
No. GDPR Recital 26 draws a clear distinction: data is anonymous only when it is "impossible" — or would require "disproportionate" effort — for "any person" to identify the individual. The visitor ID is pseudonymous (Art. 4(5)) because:
- The operator holds
MALLARD_SECRET. With the secret and a target date, they can regenerate the salt for that period. - If an operator also had access to network logs containing the original IP addresses, they
could in principle correlate those IPs to visitor IDs for the same salt period.
Lengthening
visitor_salt_rotation_dayswidens that window proportionally. - Pseudonymous data therefore remains personal data subject to GDPR (Recital 26, confirmed in EDPB Opinion 05/2022 on anonymisation techniques).
The design substantially reduces re-identification risk, but does not eliminate GDPR applicability.
Yes, if the deployment processes data of individuals in the EU/EEA. GDPR applies to any controller or processor established in the EU/EEA, or any controller/processor that processes personal data of EU/EEA data subjects regardless of where the controller is located (GDPR Art. 3 — territorial scope).
A self-hosted instance receiving traffic from EU users is subject to GDPR regardless of where the server is located.
Yes. The Court of Justice of the EU ruled in Breyer v. Bundesrepublik Deutschland (Case C‑582/14, 19 October 2016) that dynamic IP addresses constitute personal data for a website operator who has the legal means — such as seeking disclosure from the ISP — to identify the individual. Subsequent EDPB guidance reaffirms this.
Mallard Metrics processes (but does not store) IP addresses. That temporary processing still constitutes processing of personal data under GDPR Art. 4(2).
GDPR Art. 6(1) requires a lawful basis for every processing activity. For web analytics, the most commonly applicable bases are:
Operators may rely on legitimate interests when:
- There is a genuine legitimate interest (e.g., understanding how a website is used to improve it)
- The processing is necessary for that interest
- The interest is not overridden by the data subject's rights and freedoms
Under legitimate interests, consent is not required and no cookie/consent banner is needed, but operators must:
- Complete a Legitimate Interests Assessment (LIA) documenting the balancing test
- Publish a privacy notice (Art. 13/14) disclosing:
- Categories of data processed
- Purposes and legal basis
- Retention periods
- Data subject rights (access, erasure, objection)
- Contact information for the data controller
- Honour objections from data subjects (Art. 21 right to object)
The EDPB's Guidelines 06/2020 on targeting of social media users and Guidelines 02/2019 on processing of personal data under Article 6(1)(b) GDPR provide relevant context, though they address different scenarios. The core balancing test is described in EDPB Opinion 06/2014 on legitimate interests.
Operators may instead rely on freely-given, specific, informed, unambiguous consent. This generally requires a consent banner. Once consent is withdrawn, processing must stop.
For a self-hosted analytics tool with privacy-preserving design, legitimate interests is typically the appropriate basis. The EDPB has acknowledged that privacy-respecting analytics can qualify. However, the specific balancing test must be performed by the operator for their deployment context.
Regardless of lawful basis, operators must be able to respond to:
| Right | Article | Implication for Mallard Metrics |
|---|---|---|
| Right of access | Art. 15 | Operator must be able to produce data for a given visitor |
| Right to erasure | Art. 17 | Operator must be able to delete records for a visitor |
| Right to restriction | Art. 18 | Operator must be able to restrict processing |
| Right to data portability | Art. 20 | Applies only to consent-based or contract-based processing |
| Right to object | Art. 21 | Especially relevant under legitimate interests |
Note on erasure: Because the visitor ID is a pseudonymous hash — not a name, email, or stored IP — responding to erasure requests requires the operator to know which visitor ID hash corresponds to the requesting individual. Without the original IP and UA, the operator may be unable to correlate stored records to a specific individual. Operators should document this limitation in their privacy notice.
If the Mallard Metrics instance is hosted outside the EU/EEA, GDPR Chapter V applies to the data transfer. Applicable mechanisms include Standard Contractual Clauses (SCCs) or adequacy decisions. Operators must assess this for their specific hosting arrangement.
Organisations with 250 or more employees, or whose processing is not occasional, or that process special-category data, must maintain a record of processing activities. Analytics is typically recurring and should be included in the Art. 30 record.
The ePrivacy Directive (2002/58/EC), as implemented in national law across EU member states, requires prior consent for:
"the storing of information, or the gaining of access to information already stored, in the terminal equipment of a subscriber or user" — Art. 5(3), ePrivacy Directive
Mallard Metrics does not set cookies and does not access terminal storage on the visitor's device. The visitor ID is derived server-side from request data; no information is written to or read from the browser.
Consequence: Art. 5(3) ePrivacy does not require consent for Mallard Metrics' visitor identification mechanism.
However, this does not exempt the operator from GDPR (see above). The ePrivacy analysis and the GDPR analysis are separate inquiries.
ePrivacy is implemented differently in each member state. Germany's TTDSG §25, France's CNIL guidelines, and the UK's PECR each have their own specific requirements. Some national authorities have issued specific guidance on cookie-free analytics. Operators deploying in specific jurisdictions should consult applicable national guidance.
The California Consumer Privacy Act (Cal. Civ. Code § 1798.100 et seq.), as amended by CPRA, applies to for-profit businesses that meet at least one threshold:
- Annual gross revenue exceeding $25 million
- Buy, sell, receive, or share personal information of 100,000 or more California consumers or households per year
- Derive 50% or more of annual revenue from selling or sharing personal information
A small open-source project or individual deploying Mallard Metrics may fall below all three thresholds. Operators must assess their own applicability.
Under CCPA § 1798.140(v)(1), "personal information" includes:
- IP addresses (explicitly listed)
- Unique identifiers — the visitor ID hash qualifies as a "unique identifier" under § 1798.140(ae)
- Geolocation data (country, region, city stored by Mallard Metrics)
- Inferences drawn from personal information to create a profile (aggregate analytics)
Obligations if CCPA applies:
- Disclose categories of personal information collected in a privacy policy
- Disclose the purposes for which personal information is used
- Provide a "Do Not Sell or Share My Personal Information" link if applicable
- Honor rights to know, delete, correct, and opt-out
- Maintain records of consumer requests
Mallard Metrics does not "sell" personal information (no data leaves the self-hosted instance), but the "share" definition in CPRA may cover cross-context behavioural advertising — which Mallard Metrics does not perform.
Embedding Mallard Metrics as a live demo on a public site introduces concrete legal obligations:
When a visitor loads your GitHub Pages site with an embedded Mallard Metrics demo:
- Their browser may send requests to the Mallard Metrics instance
- The instance temporarily processes their IP address and User-Agent
- Their approximate geographic location (country, region, city) is stored in Parquet
- A pseudonymous visitor ID is generated and stored
This is real personal data processing, not simulation.
| Obligation | Source | Notes |
|---|---|---|
| Lawful basis | Art. 6 | Legitimate interests requires LIA; consent requires banner |
| Privacy notice | Art. 13 | Must be provided at time of data collection |
| Data processor agreement | Art. 28 | If GitHub acts as a processor on your behalf |
| Record of processing | Art. 30 | May apply depending on organisation size |
Option A — Synthetic data (recommended): Pre-populate the demo instance with synthetic, generated event data. No real visitor data is processed. Add a banner stating: "This demo uses synthetic data; no visitor information is collected." This eliminates GDPR obligations for the demo instance.
Option B — Consent-gated iframe: Show a consent notice before loading the iframe. Only embed after explicit consent. This requires a consent management mechanism.
Option C — Privacy notice + legitimate interests: Publish a privacy notice covering the demo, complete a Legitimate Interests Assessment, and ensure the demo instance's data processing is disclosed to visitors. Higher compliance burden than Option A.
Option D — Read-only dashboard, no tracking script: Host a Mallard Metrics dashboard showing pre-loaded synthetic data without deploying the tracking script to GitHub Pages visitors.
Mallard Metrics provides two deployment profiles:
| Profile | Target | Core metric impact | Regulatory posture |
|---|---|---|---|
| Standard (default) | Maximum analytics depth | Full unique-visitor counting, city-level geo, browser versions | Operator must complete LIA + privacy notice |
GDPR-Friendly (gdpr_mode = true) |
Reduced fingerprinting surface | Daily unique visitors still tracked; geo limited to country; versions suppressed | Substantially reduced data processing scope; supports legitimate interests or consent-based deployments |
The easiest path is the gdpr_mode convenience flag. Set either in your TOML config:
gdpr_mode = true
retention_days = 30 # GDPR Art. 5(1)(e) storage limitation — recommendedOr via environment variables:
MALLARD_GDPR_MODE=true
MALLARD_RETENTION_DAYS=30When gdpr_mode = true, the following transformations are applied at ingestion time:
| Setting | Effect | Privacy impact |
|---|---|---|
strip_referrer_query = true |
Strips ?query and #fragment from referrer URLs before storing |
Prevents leaking search terms (e.g. ?q=medical+condition) |
round_timestamps = true |
Timestamps stored at hour precision (e.g. 2024-03-15T14:00:00) |
Reduces fingerprinting via timing correlation |
suppress_browser_version = true |
Stores browser name only (Chrome, not Chrome 120.0) |
Reduces UA-based fingerprinting |
suppress_os_version = true |
Stores OS name only (Windows, not Windows 10.0) |
Reduces UA-based fingerprinting |
suppress_screen_size = true |
Omits screen width and device type entirely | Eliminates screen-size fingerprinting vector |
geoip_precision = "country" |
Stores country code only; region and city set to NULL | City/region are more identifying than country |
Individual flags can be set without enabling the full gdpr_mode bundle:
# Example: strip referrer queries and limit geo, but keep browser/OS versions
strip_referrer_query = true
geoip_precision = "country"
retention_days = 30| Flag | Env var | Default | Description |
|---|---|---|---|
gdpr_mode |
MALLARD_GDPR_MODE |
false |
Enable the GDPR-friendly bundle (forces all flags below on) |
strip_referrer_query |
MALLARD_STRIP_REFERRER_QUERY |
false |
Strip ?query and #fragment from referrer URLs |
round_timestamps |
MALLARD_ROUND_TIMESTAMPS |
false |
Round timestamps to nearest hour |
suppress_visitor_id |
MALLARD_SUPPRESS_VISITOR_ID |
false |
Replace HMAC visitor ID with random UUID per request (breaks unique-visitor counting) |
suppress_browser_version |
MALLARD_SUPPRESS_BROWSER_VERSION |
false |
Store browser name only |
suppress_os_version |
MALLARD_SUPPRESS_OS_VERSION |
false |
Store OS name only |
suppress_screen_size |
MALLARD_SUPPRESS_SCREEN_SIZE |
false |
Omit screen_size and device_type |
geoip_precision |
MALLARD_GEOIP_PRECISION |
"city" |
"city", "region", "country", or "none" |
This flag is not activated by gdpr_mode because it eliminates the unique-visitor metric
entirely. When enabled, each request receives a fresh random UUID instead of the HMAC-derived
hash, making cross-request linkability impossible. Tradeoff: "unique visitors" becomes
an approximation of page-load count, not actual visitor deduplication.
Enable explicitly only if your legal analysis concludes that even the daily-rotating pseudonymous ID constitutes unacceptable processing risk:
MALLARD_SUPPRESS_VISITOR_ID=trueMallard Metrics provides an admin-authenticated endpoint to permanently delete analytics data:
DELETE /api/gdpr/erase?site_id=example.com&start_date=2024-01-01&end_date=2024-01-31
Authorization: Bearer <admin-api-key>This endpoint:
- Deletes all matching rows from the DuckDB hot-events table
- Removes the on-disk Parquet partition directories for the site + date range
(partition layout:
data/events/site_id={site_id}/date={date}/) - Refreshes the
events_allVIEW so subsequent queries reflect the deletion
Response:
{
"status": "erased",
"site_id": "example.com",
"start_date": "2024-01-01",
"end_date": "2024-01-31",
"db_records_deleted": 1247,
"parquet_partitions_deleted": 31
}Limitation: Because visitor IDs are pseudonymous hashes (not names or email addresses), it is not possible to identify which stored rows correspond to a specific natural person without the original IP address and User-Agent string. Art. 17 erasure therefore operates on the site + date-range granularity — the finest granularity operators can act on when responding to a GDPR erasure request. Document this limitation in your privacy notice.
This section summarises the minimum obligations for a legally compliant deployment.
- Legal review: Have a qualified data protection attorney review your deployment for your jurisdiction and user base
- Privacy notice: Publish a privacy notice on your site disclosing the data processing described in the Persistently stored table above
- Lawful basis: Document your chosen lawful basis (legitimate interests is typical)
- Legitimate Interests Assessment: If using legitimate interests, complete and document a balancing test (template available from the ICO and CNIL)
- Art. 30 record: Include analytics in your record of processing activities if required
- Data processor agreements: If using a hosting provider, ensure an appropriate DPA is in place
- Set
MALLARD_RETENTION_DAYSto the shortest period that meets your analytics needs (30 days recommended for EU deployments) - Consider enabling
MALLARD_GDPR_MODE=truefor EU/EEA deployments - Do not collect custom
propscontaining PII (names, emails, user IDs that are direct identifiers) without explicit legal basis and privacy notice disclosure - Enable
MALLARD_SECURE_COOKIES=truein production (TLS deployments) - Set
MALLARD_SECRETto a strong random value and protect it as a secret
- Maintain a process for responding to data subject rights requests (use
DELETE /api/gdpr/erasefor Art. 17 erasure requests) - Monitor applicable supervisory authority guidance for updates to cookie-free analytics interpretations
- Review retention periods periodically
The following activities are not performed by Mallard Metrics, regardless of configuration:
- Does not set HTTP cookies
- Does not read or write browser
localStorageorsessionStorage - Does not use browser fingerprinting techniques that access device APIs (WebGL, Canvas, AudioContext)
- Does not store raw IP addresses anywhere on disk
- Does not store raw User-Agent strings anywhere on disk
- Does not transmit collected data to any third party
- Does not perform cross-site tracking
- Does not serve advertising
- Does not sell data
| Feature | Mallard Metrics (Standard) | Mallard Metrics (GDPR Mode) | Google Analytics 4 | Plausible Analytics | Fathom Analytics |
|---|---|---|---|---|---|
| Self-hosted | Yes | Yes | No | Yes (paid) / No (cloud) | No |
| Cookies set | No | No | Yes (session + persistent) | No | No |
| IP stored | No | No | Yes (anonymised) | No | No |
| Raw UA stored | No | No | Yes | No | No |
| Browser version stored | Yes | No | Yes | Yes | Yes |
| OS version stored | Yes | No | Yes | Yes | Yes |
| Screen size stored | Yes | No | Yes | No | No |
| Geo stored | Country/region/city | Country only | Country/region/city | Country only | Country only |
| Referrer query stored | Yes | No | Yes | No | No |
| Timestamp precision | Millisecond | Hour | Millisecond | Day | Day |
| Visitor ID type | Daily-rotating HMAC hash | Daily-rotating HMAC hash | Persistent cookie-based | Daily-rotating hash | Daily-rotating hash |
| Data erasure API | Yes (site + date range) | Yes (site + date range) | No (Google-controlled) | No | No |
| GDPR applicability | Yes (pseudonymous data) | Yes (reduced scope) | Yes (personal data) | Yes (pseudonymous data) | Yes (pseudonymous data) |
| Consent needed (ePrivacy) | No (no terminal storage access) | No | Yes (cookies) | No | No |
| Consent needed (GDPR) | Depends on lawful basis | More defensible under LI | Yes (or other basis) | Depends on lawful basis | Depends on lawful basis |
| Data controller | You (self-hosted operator) | You (self-hosted operator) | Plausible or you | Fathom |
All legal citations below refer to publicly available primary sources.
| Term | Definition | Source |
|---|---|---|
| Personal data | "Any information relating to an identified or identifiable natural person" | GDPR Art. 4(1) |
| Processing | "Any operation… performed on personal data, whether or not by automated means" — includes collection, storage, retrieval, and use | GDPR Art. 4(2) |
| Pseudonymisation | "Processing of personal data in such a manner that the personal data can no longer be attributed to a specific data subject without the use of additional information" | GDPR Art. 4(5) |
| Pseudonymised data is personal data | "The principles of data protection should… not apply to anonymous information… [This] does not therefore concern the processing of such anonymous information, including for statistical or research purposes." The contrapositive: pseudonymous data does apply. | GDPR Recital 26 |
| Lawful basis | Processing is lawful only if at least one listed condition is met | GDPR Art. 6(1) |
| Legitimate interests | "Processing is necessary for the purposes of the legitimate interests pursued by the controller or by a third party, except where such interests are overridden by the interests or fundamental rights and freedoms of the data subject" | GDPR Art. 6(1)(f) |
| Transparency | Controller must provide specific information at time of collection | GDPR Art. 13 |
| Right to erasure | Data subject may request erasure in defined circumstances | GDPR Art. 17 |
| Right to object | Data subject may object to processing under legitimate interests | GDPR Art. 21 |
| Document | Relevance |
|---|---|
| CJEU Case C‑582/14, Breyer v. Bundesrepublik Deutschland (19 Oct 2016) | Dynamic IP addresses are personal data for website operators |
| EDPB Opinion 05/2022 on the European Commission's Draft Decision pursuant to Art. 25(6) GDPR for the United States | Reaffirms pseudonymous data is personal data |
| EDPB Guidelines 06/2020 on targeting of social media users | Elaborates on legitimate interests balancing test |
| EDPB Guidelines 2/2019 on the processing of personal data under Article 6(1)(b) GDPR | Scope of necessity test for lawful bases |
| Article 29 Working Party Opinion 06/2014 on legitimate interests | Detailed three-part test for legitimate interests |
| ePrivacy Directive 2002/58/EC, Art. 5(3) | Terminal storage consent requirement ("cookie law") |
| ICO Guidance on legitimate interests | Practical LIA template (UK-focused, broadly applicable) — ico.org.uk |
| CNIL guidance on analytics without consent | France-specific guidance; one of the more permissive interpretations for privacy-preserving analytics — cnil.fr |
| Term | Source |
|---|---|
| Definition of "personal information" (includes IP addresses and unique identifiers) | Cal. Civ. Code § 1798.140(v)(1) |
| Definition of "unique identifier" | Cal. Civ. Code § 1798.140(ae) |
| Business thresholds for CCPA applicability | Cal. Civ. Code § 1798.140(d) |
This document describes the project's privacy model as implemented in the source code. Privacy law evolves; operators should verify current regulatory guidance before relying on it for compliance.