Product Analytics Hides Its Tracking in localStorage
Marketing pixels announce themselves with obvious advertising cookies. Product analytics is sneakier about it. Mixpanel and Amplitude often keep their identifier in localStorage rather than a cookie, which leads teams to assume the ePrivacy cookie rule doesn't apply. It does. Article 5(3) of the ePrivacy Directive covers storing information on, or reading it from, a device, and it doesn't care whether the storage bucket is called a cookie or localStorage. The EDPB confirmed exactly this scope in its 2024 guidelines. A device ID in localStorage is a stored identifier, so it needs consent in the EU the same as a cookie would.
This piece is the tool-specific companion to our broader SaaS product analytics consent guide. Here we get into what Mixpanel and Amplitude actually write, and the opt-out gotcha that catches careful teams.
What Each Tool Stores
Both build a persistent identifier so they can stitch events into a user. Mixpanel's JavaScript SDK keeps its state in a cookie named mp_<token>_mixpanel and a distinct_id value. Amplitude's Browser SDK stores a session cookie containing a deviceId, a randomly generated string that persists across sessions, plus the userId once your app identifies the person. In both cases the identifier is the whole point: it's what lets the tool recognize a returning visitor. That also makes it a non-essential identifier under ePrivacy, which is what puts it behind consent.
Opt-Out Stops the Send, Not Always the Storage
This is the trap. Mixpanel's opt_out_tracking() and Amplitude's setOptOut(true) flip a flag that stops events from being sent. Both projects have open reports where the SDK still wrote a cookie or localStorage entry even with opt-out set (Mixpanel with opt_out_tracking_by_default, Amplitude with optOut: true). For ePrivacy that's a problem, because the violation is the act of storing the identifier before consent, not the transmission of data. So "we called opt-out" is not the same as "we stored nothing." Verify what's actually in the browser rather than trusting the flag.
So Gate Initialization, Then Opt In
Because the opt-out flag doesn't reliably prevent storage, the safe pattern is to not initialize the SDK until consent exists, or to initialize opted-out-by-default and confirm nothing is written, then opt in on acceptance. The load-on-consent version is the one you can prove. Hold the SDK snippet until the visitor accepts analytics, initialize it then, and the device ID is created only after the decision.
// Load-on-consent: nothing is stored until the visitor accepts.
function onAnalyticsConsent(granted) {
if (!granted) return; // no init, no device ID written
// Mixpanel, pinned to the EU residency endpoint:
mixpanel.init("YOUR_TOKEN", {
api_host: "https://api-eu.mixpanel.com",
opt_out_tracking_by_default: false
});
mixpanel.opt_in_tracking();
// Amplitude, EU server zone:
amplitude.init("YOUR_API_KEY", { serverZone: "EU" });
amplitude.setOptOut(false);
}
// On withdrawal, opt out AND stop future initialization:
function onWithdraw() {
mixpanel.opt_out_tracking();
amplitude.setOptOut(true);
}Keep the Data in the EU: Residency Settings
Both tools default to US collection, which drags EU personal data across the Atlantic and adds a transfer question you'd rather not answer. Both offer an EU option. Mixpanel's European Data Residency Program processes and stores the data in its Netherlands data center when you point the SDK at api-eu.mixpanel.com, which keeps the data in the EU. Amplitude has an EU server zone you set with serverZone: "EU". Neither setting removes the consent requirement, the identifier still needs consent, but keeping collection in-region simplifies the transfer analysis considerably.
Server-Side Doesn't Skip the Question
Teams sometimes move Mixpanel or Amplitude to a server-side pipeline to dodge ad blockers, then treat it as consent-exempt. It isn't. If your backend records product events tied to a user who declined analytics, you've processed their personal data without a basis, just somewhere a browser scanner can't see it. Read the consent decision on the server and drop the event when analytics consent is missing. See server-side consent enforcement.
A Word on Legitimate Interest for B2B
B2B SaaS teams often float legitimate interest as the basis for product analytics, reasoning that understanding feature usage is a normal business need. That argument can hold for the GDPR processing side in some cases. It does nothing for the ePrivacy side, which comes first and is separate. Article 5(3) requires consent to store the identifier on the device, and it lists no legitimate-interest exemption. So even with a solid legitimate-interest assessment for the analytics, you still need consent to write the device ID in the EU. The two questions are answered with different keys.
Mixpanel & Amplitude Consent Checklist
The SDK does not initialize until analytics consent is granted
Load-on-consent, because the opt-out flag doesn't reliably prevent storage.
No mp_ cookie, distinct_id, or Amplitude deviceId exists before acceptance
Check localStorage and cookies both. The identifier can live in either.
Collection is pinned to the EU endpoint or server zone
api-eu.mixpanel.com or serverZone EU, to keep data in-region.
Server-side event pipelines drop events for non-consenting users
The lawful-basis question follows the data to the backend.
Withdrawal opts out and prevents re-initialization
A revoked decision has to stop future storage as well as the current send.
Doing It With CookieBeam
CookieBeam holds the Mixpanel and Amplitude snippets in a blocked state and injects them only after the visitor accepts analytics, so the device ID is never written first. Its scanner checks both cookies and localStorage during an audit, which matters here because these tools favor localStorage and a cookie-only check would miss the identifier entirely. If you run events server-side, CookieBeam's consent signal reaches the server so the pipeline can gate on the real decision. Categorize both tools as analytics, wire them to your analytics toggle, and confirm with a scan that nothing sits in storage on first load.
Related Guides and Sources
Continue with SaaS product analytics consent, measuring consent impact on analytics, and Adobe Analytics consent. Primary sources: Mixpanel's protecting user data and GDPR compliance docs, Amplitude's cookies and consent management guide, and the EDPB's Guidelines 2/2023 on the technical scope of ePrivacy Article 5(3).