Is Savings add-on safe?

Medium risk

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.

Inspiring Benefitsv1.0.28Chrome Web Store
50Risk
Who publishes it

Inspiring Benefits - no other listings under this identity, 1 shared hostname

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Inspiring Benefits
Registered address
C. AZALEA 209 P01 A, Alcobendas Madrid, Madrid 28109, ES
Registered contact
Manuel Ocaña Roldán

Shared hosts - 1 hostname

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

faqs.contigomas.com
Also called by 2 other listings, including Saving Button

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

MediumunwantedCWE-359Dynamic sandbox

Dynamic analysis observed a Google Analytics request from Savings add-on.

What actually happens

You did this

You install the extension or interact with merchant-related pages on Chrome.

The extension did this

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.

Captured request

GEThttps://www.google-analytics.com/collect?tid=UA-173466035-1&cid=980dcb08-f35d-426a-b91a-7bf3b7f4d981

GET request observed during dynamic analysis; no request body was recorded.

Fields sent or constructed for the Google Analytics event

  • 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.

The code that does this

Analytics defaults, persistent ID storage, and event forwarding

Readable version

Readable analytics sender

bg.js:390-423
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())  }}

Readable Chrome defaults

bg.js:2058-2069
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()

Readable stored client ID initialization

bg.js:2137-2151
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;

Readable sendAnalytics gate

bg.js:2998-3003
key: "sendAnalytics",value: function(t) {  var e = t.data,    n = t.sendResponse;  this.settings.data.isAnalyticsEnabled && this.analytics.send(e), n && n(!0)}

The code that does this

Merchant names become analytics event labels

Readable version

Readable search-result event labels

content/bundle.js:564-579
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}

Readable click event labels

content/bundle.js:609-618
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  })}

Readable success-window event labels

content/bundle.js:235-265
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)  })))()}

External analytics destination

    • www.google-analytics.com

    Receives extension Google Analytics collect events with the tracking ID, client ID, event names, and merchant labels.

What it can do

Permissions this extension asks for, as declared in version 1.0.28. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    *://*/*

  • See the address and title of every tab you have open

    tabs

  • Watch every request your browser makes

    webRequest

  • Store data in your browser

    storage

  • Store an unlimited amount of data in your browser

    unlimitedStorage

  • Read and change cookies, including the ones that keep you signed in

    cookies

Where it sends data

Destinations our analysis observed Savings add-on 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.

  • www.google-analytics.comwidely used

    Savings add-on sends data to www.google-analytics.com. A widely used service: 388 other extensions we have analyzed send data here.

Updated 30 September 2026ldfdohgfoolmacfbdekmbpoofhahcfgg