Is Savings add-on safe?
Savings add-on sends merchant names and interaction events to Google Analytics using a persistent identifier, without prompting Chrome users for consent.
On Chrome, the extension enables Google Analytics tracking by default and never shows the consent notification that Firefox users see. Each session is tied to a persistent UUID stored in local storage, which is sent alongside events such as installs, logins, and merchant page visits. Merchant names from search and success pages are included in the event labels transmitted to Google Analytics.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Chrome sends merchant activity to Google Analytics by default
Dynamic analysis observed a Google Analytics request from Savings add-on.
Installs start with analytics enabled, prompt disabled; the request used tracking ID UA-173466035-1.
It logs install, login, search, success events with merchant.
You install the extension or interact with merchant-related pages on Chrome.
The extension sends Google Analytics events using a persistent client ID before showing a Google Analytics consent prompt on Chrome.
The code turns that prompt off for Chrome while leaving analytics enabled by default.
| Field | Value | Why it matters | |
|---|---|---|---|
Analytics property | UA-173466035-1 | Identifies which Google Analytics property receives the extension event. | |
Client identifier | 980dcb08-f35d-426a-b91a-7bf3b7f4d981 | Lets repeated extension events be tied to the same browser profile over time. | |
Event category | SERP | Shows which part of the extension generated the event. | |
Event action | SERP show | Describes what happened in the extension, such as showing or clicking a merchant result. | |
Merchant label | Amazon | Can reveal which merchant or shopping context was active when the extension event fired. |
Analytics defaults, persistent ID storage, and event forwarding
class c {
constructor({
tid: t,
cid: e
}) {
this.data = {
v: 1,
tid: t,
t: "event",
cid: e || c.uuidv4(),
ec: null,
ea: null,
el: null,
ev: null,
z: null
}
}
static uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, t => {
const e = 16 * Math.random() | 0;
return ("x" == t ? e : 3 & e | 8).toString(16)
})
}
static random(t = 1e7, e = 2147483647) {
return t + Math.floor(Math.random() * (e - t))
}
send(t) {
const e = {
...this.data,
...t,
z: c.random()
};
return fetch("https://www.google-analytics.com/collect?" + new URLSearchParams(e).toString())
}
}this.isChrome = "chrome" === Object(h.a)();
var r = Object(h.c)(null === (e = chrome) || void 0 === e || null === (e = e.i18n) || void 0 === e ? void 0 : e.getUILanguage());
this.data = {
locale: r,
showGuide: !0,
isAnalyticsEnabled: this.isChrome,
analyticsClientId: null,
isNotificationEnabled: !0,
showGa: !this.isChrome,
token: null,
isLocaleChanged: !1
}, this.isReady = !1, this.init()case 0:
return t.next = 1, this.getSettings();
case 1:
if (e = t.sent, n = e.analyticsClientId) {
t.next = 2;
break
}
return n = Object(m.e)(), t.next = 2, this.setSettings({
analyticsClientId: n
});
case 2:
Object.assign(this.data, {
tid: b.f,
cid: n,
ev: 1
}), this.isReady = !0;key: "sendAnalytics",
value: function(t) {
var e = t.data,
n = t.sendResponse;
this.settings.data.isAnalyticsEnabled && this.analytics.send(e), n && n(!0)
}Merchant names become analytics event labels
key: "createSERP",
value: function(A) {
var B = this;
Object(j.c)({
ec: "SERP",
ea: "SERP show",
el: A.name
});
var E = document.createElement("span");
return E.className = this.className, E.innerHTML = this.template(A), E.addEventListener("click", (function(w) {
w.stopPropagation(), w.preventDefault(), B.constructor.onClick({
el: E,
merchant: A
})
})), E
}key: "onClick",
value: function(A) {
var B = A.el,
E = A.merchant;
B.parentNode.querySelector("a").click(), Object(j.c)({
ec: "SERP",
ea: "SERP click",
el: E.name
})
}methods: {
close: function(A) {
this.$store.commit("update", {
merchant: h(h({}, this.$store.state.merchant), {}, {
showNotification: !1
})
}), Object(j.c)({
ec: "Success Window",
ea: "Click ".concat(A),
el: this.merchant.name
})
}
},
mounted: function() {
var A = this;
return s()(F.a.mark((function B() {
var E;
return F.a.wrap((function(B) {
for (;;) switch (B.prev = B.next) {
case 0:
return B.next = 1, Object(M.b)({
action: "getHtmlContent",
data: {
mid: A.merchant.id
}
});
case 1:
E = B.sent, A.htmlContent = JSON.parse(JSON.stringify(E)), Object(j.c)({
ec: "Success Window",
ea: "Show",
el: A.merchant.name
});
case 2:
case "end":
return B.stop()
}
}), B)
})))()
}- www.google-analytics.com
Receives extension Google Analytics collect events with the tracking ID, client ID, event names, and merchant labels.