Privacy policy
This page describes what mcp-analytics stores, why, and how you can exercise your GDPR rights. Last updated July 2026.
1. Controller
Spreenovate GmbH, Prenzlauer Allee 186, 10405 Berlin, Germany.
Managing directors: Fabian Hallstein, Alexander Kamphorst.
Contact: info@mcp-analytics.com.
We have not appointed a Data Protection Officer because the company is below the German DPO threshold (§ 38 BDSG).
2. Two roles to keep apart
mcp-analytics has two very different relationships with personal data:
(a) You, the mcp-analytics account holder
We store your email address and an API token. Legal basis: contract performance (Art. 6 (1)(b) GDPR). The email is used for transactional messages only (verification link, occasional service notices, plan-limit warnings). No marketing.
(b) Visitors of your sites
When a visitor loads a page that includes our tracking snippet, we record pseudonymous event data. You are the controller for that data; we are your processor (Art. 28 GDPR). The full Data Processing Agreement sets out the processor obligations, sub-processor list, retention, breach notification timelines, and audit rights.
3. What we collect from your visitors
The data set per pageview / event:
- Timestamp, event name, URL path, URL host
- Referrer host (and path in
balanced/allmodes) - UTM parameters (source, medium, campaign)
- Browser, browser version, operating system, device class (parsed from User-Agent)
- The full User-Agent string (used for bot classification; not personal data on its own per Art. 4 GDPR)
- Timezone, browser language, viewport size, color-scheme preference (from privacy-clean Web APIs)
- Engagement time and scroll depth (fired on page-leave)
- A traffic-class label (
userorbot) - Custom event properties you choose to send via
mcpa('track', …)
Raw IP addresses are not persisted in the analytics database. The IP is used in-memory to compute the visitor/session hash and is then discarded. Geo data (country/region/city) is reserved in the schema but currently empty.
One narrow exception: if an IP repeatedly sends invalid
payloads (unknown site IDs) to our ingest endpoint, we record that IP in a
separate abuse_events table for anti-abuse purposes (legal
basis: Art. 6 (1)(f) GDPR, legitimate interest in service availability).
These records are not used for analytics and are not joined with visitor
data.
For bot detection, the ingest service additionally keeps
transient, day-scoped abuse counters in memory (in all
privacy modes, including strict): a salted hash of IP and
User-Agent — the same daily-rotating primitive as above, never the raw
IP — counts same-day repeat fetches so that scrapers posing as browsers
can be labelled as bots. These counters are never written to disk or to
the analytics database, cannot be joined with stored events, and
become permanently unlinkable at 00:00 UTC when the daily salt rotates
(immediately on service restart), after which the inert counter data is
purged from memory within approximately 26 hours (legal basis:
Art. 6 (1)(f) GDPR, legitimate interest in measurement accuracy and
abuse prevention).
4. How visitors are counted (and why no banner)
The strict and balanced privacy modes (balanced is the default for new sites) compute server-side identifiers as:
session_id = SHA-256(daily_salt + site_salt + ip + user_agent + site_id) (balanced appends a "|session" suffix)
visitor_id = SHA-256(daily_salt + site_salt + ip + user_agent + site_id + "|visitor") (balanced only; in strict mode no visitor identifier is computed at all)
The daily_salt rotates at 00:00 UTC and is part of every hash, in every mode. The IP is used in-memory for these hashes and then dropped; it is not written to the analytics database. The User-Agent is stored separately as a string (used for bot classification, not for re-identification).
Result: visitors cannot be re-identified across days in either mode; no
cookie, no localStorage, no fingerprint that survives midnight UTC. The
German DSK and the EDPB consider this sufficient anonymisation to skip the
cookie banner requirement (ePrivacy / TTDSG § 25). The all
mode opts into a 2-year first-party cookie and shifts consent
responsibility to you (the site owner).
Do-Not-Track signals are honoured as a hard opt-out in strict
and balanced; in all mode the site owner decides.
5. Where the data lives
- Hetzner Online GmbH (Falkenstein, Germany): primary infrastructure. Hetzner privacy policy.
- ClickHouse on the same EU server: analytics events. 2-year TTL on raw events.
- SQLite on the same EU server: accounts, sites, usage counters.
- Postmark (ActiveCampaign LLC), USA: transactional email delivery. Transfer is covered by Standard Contractual Clauses (SCCs) and DPF certification. Only your email address and the verification-link content are transmitted.
6. Retention
- Raw events in ClickHouse: 2 years, then automatic delete via TTL.
- Account data: until you ask us to delete it.
- Verification tokens: 24 hours validity, purged after use.
- Server access logs (kamal-proxy): rotated every 10 MB per container, no centralised retention.
7. Your rights
You have the right to:
- access your data (Art. 15 GDPR)
- correct it (Art. 16)
- erase it (Art. 17): write us at info@mcp-analytics.com
- port it out (Art. 20)
- object to processing (Art. 21)
- complain to a supervisory authority. For Berlin that is the Berliner Beauftragte für Datenschutz und Informationsfreiheit.
8. Cookies on this site
The mcp-analytics website (the one you are reading) does not set any
tracking cookies. Rails sets a single transactional session cookie
(_mcp_analytics_session) only after you submit a form. It
expires when you close the browser.