Is Privacy Extension for WA Web safe?
Privacy Extension for WhatsApp Web sends WhatsApp page telemetry and a persistent client ID to Google Analytics.
On web.whatsapp.com, the extension injects a page script that hooks WhatsApp events and sends analytics beacons. Those beacons include a localStorage client ID plus page details such as the current URL, referrer, title, language, screen size, WhatsApp version, and login/logout/authenticated events.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Injected WhatsApp Web page script sends persistent ID to Google Analytics
Opening WhatsApp Web makes the extension's injected page script create a persistent client ID and send it, plus the page URL, referrer and title, to Google Analytics with no consent prompt.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
Opens web.whatsapp.com with the extension enabled.
The extension's content script is already registered on every web.whatsapp.com page.
The injected page script creates a persistent tracking ID and sends it, the page URL, referrer, and title to Google Analytics.
The beacon fires automatically on page load, with no consent prompt in the extension's own UI.
204 No Content, standard Google Analytics Measurement Protocol acknowledgment with no response body.
en=page_view&_ee=1&ep.authenticated=true&ep.method=multidevice&_et=812- Persistent client ID1765583280.1788897100
A unique ID stored in your browser that links every WhatsApp Web visit to the same identity over time.
- Page addresshttps://web.whatsapp.com/
The full WhatsApp Web URL open when the beacon fires.
- Page title and script versionW: -, WA-JS: 4.3.0
The tab title, rewritten by the script to include its bundled library version.
- Login statusauthenticated=true
Whether you are currently signed in to WhatsApp Web in this browser session.
- Event nameen=page_view
Which action triggered the beacon: page view, login, logout, or ongoing engagement.
The bundled Tracker class builds the persistent client ID and beacons it via sendBeacon
Client ID creation, header fields, and processEvents()
inject/inject.jsclass Tracker { static get clientState() { const isFirstVisit = !localStorage.cid; const clientId = localStorage.cid || sessionStorage.cid || randomInt(1e9) + "." + Math.floor(Date.now() / 1000); localStorage.cid = sessionStorage.cid = clientId; return { firstVisit: isFirstVisit, cid: clientId }; } constructor(trackingId) { this.trackingId = trackingId; this.events = []; this.userProperties = {}; this.lastTime = Date.now(); this.hitsCount = 1; this.documentTitle = ""; } getHeader() { const { cid, firstVisit } = Tracker.clientState; return { v: 2, tid: this.trackingId, // Google Analytics measurement ID cid, // the persistent client ID _fv: firstVisit ? 1 : undefined, ul: (navigator.language || "").toLowerCase() || undefined, sr: `${screen.width}x${screen.height}`, dl: location.href, // full page URL dr: document.referrer, dt: this.documentTitle || document.title }; } processEvents() { const events = this.events; if (this.events = [], !events.length) return; const eventParams = events.map(([name, props, elapsed]) => { const pairs = [["en", name], ["_ee", "1"]]; for (const key in props) pairs.push([`ep.${key}`, String(props[key])]); pairs.push(["_et", String(elapsed)]); return pairs; }); const headerParams = Object.entries(this.getHeader()) .filter(([, v]) => v !== undefined) .map(([k, v]) => [k, String(v)]); const query = new URLSearchParams(headerParams); // Beacon fires with no user interaction and no consent prompt. navigator.sendBeacon(`${Tracker.collectURL}?${query}`); }}Tracker.collectURL = "https://analytics.google.com/g/collect";A Tracker is created hardcoded to the extension's own GA property on page load
inject/inject.jsexport const waVersion = "4.3.0";// One Tracker per WhatsApp page load, hardcoded to this extension's// own Google Analytics property, gated only by an internal config flag.const titleParts = ["W: ", "-", ", WA-JS: ", waVersion];const primaryTracker = new Tracker("G-MTQ4KY110F");const secondaryTracker = config.googleAnalyticsId ? new Tracker(config.googleAnalyticsId) : null;internalEvents.on("loader.injected", () => { const authenticated = isAuthenticated(); const method = isMultiDevice() ? "multidevice" : "legacy"; if (!config.disableGoogleAnalytics) { primaryTracker.documentTitle = titleParts.join(""); primaryTracker.setUserProperty("method", method); primaryTracker.setUserProperty("wa_js", waVersion); primaryTracker.setUserProperty("powered_by", config.poweredBy || "-"); } if (secondaryTracker && !config.disableGoogleAnalytics) { primaryTracker.trackEvent("page_view", { authenticated, method }); }});- analytics.google.com
Google's Measurement Protocol endpoint. Receives the client ID, page URL, referrer, and title on every WhatsApp Web page load.
Where it sends data
Destinations our analysis observed Privacy Extension for WA Web contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- analytics.google.comwidely used
Privacy Extension for WA Web sends data to analytics.google.com. A widely used service: 25 other extensions we have analysed send data here.