vuejs / v2.vuejs.org

📄 Documentation for Vue 2
https://v2.vuejs.org
MIT License
5.03k stars 3.43k forks source link

Google Analytics #2641

Closed resynth1943 closed 4 years ago

resynth1943 commented 4 years ago

Remove Google Analytics

If you must have an analytics system, might I suggest either:

These solutions are all well-tested and open-source. This, of course, means they can be independently audited for privacy and security. Instead of using a proprietary nonfree system such as Google Analytics, perhaps we could work together to replace it with something slightly more ethical?

Furthermore, the majority of privacy features in evergreen browsers block Google Analytics from being run. I can not say the same for solutions such as Plausible, which suggests they are trusted for their privacy by independent persons.

If you need any more information, please contact me!

sdras commented 4 years ago

Thanks

resynth1943 commented 4 years ago

Why was this closed?

resynth1943 commented 4 years ago

@sdras

yyx990803 commented 4 years ago

Since this website is also open source, you can see that the only thing we are tracking via Google Analytics is page view. We do not use any other Google Analytics features that rely on collecting personal information from our users. The website is also a pure-content static site that does not ask or use any personal identifiable information. That said, I'm not an expert on analytics and privacy, so please elaborate if you think our way of using Google Analytics still leads to privacy issues.

Switching to a different analytics service involves non-trivial cost due to the extremely high traffic our docs get, so it is non-practical for us to consider paid services.

sdras commented 4 years ago

Hey, I closed this issue for a few reasons:

resynth1943 commented 4 years ago

Hey guys! :wave:

We are considering moving to Netlify Analytics, which is server-side and does no tracking

That sounds like a good idea. Isn't that a paid solution though? @sdras


That said, I'm not an expert on analytics and privacy, so please elaborate if you think our way of using Google Analytics still leads to privacy issues.

I mean, even with just tracking page views, there are still some inherent privacy issues when using Google Analytics. For example, Google Analytics seems to fingerprint users, which is a very dangerous privacy violation.

One example of fingerprinting is Google Analytics' uploading of the screen size of the browser.

Just opening the page in Tor Browser sends a request to Google Analytics' collection endpoint. The JavaScript sends this mysterious data:

{
  "Query string": {
    "v": "1",
    "_v": "j83",
    "a": "1398337363",
    "t": "pageview",
    "_s": "1",
    "dl": "https://vuejs.org/",
    "ul": "en-us",
    "de": "UTF-8",
    "dt": "Vue.js",
    "sd": "24-bit",
    "sr": "2000x600",
    "vp": "1988x600",
    "je": "0",
    "_u": "IEBAAAAB~",
    "jid": "791792288",
    "gjid": "834920789",
    "cid": "183173963.1595265292",
    "tid": "UA-46852172-1",
    "_gid": "1707634750.1595265292",
    "_r": "1",
    "z": "1439589530"
  }
}

After some quick inspection of the enormous Google Analytics client, I can see this:

  var hb = T("apiVersion", "v"),
    ib = T("clientVersion", "_v");
  S("anonymizeIp", "aip");
  var jb = S("adSenseId", "a"),
    Va = S("hitType", "t"),
    Ia = S("hitCallback"),
    Ra = S("hitPayload");
  S("nonInteraction", "ni");
  S("currencyCode", "cu");
  S("dataSource", "ds");
  var Vd = S("useBeacon", void 0, !1),
    fa = S("transport");
  S("sessionControl", "sc", "");
  S("sessionGroup", "sg");
  S("queueTime", "qt");
  var Ac = S("_s", "_s");
  S("screenName", "`");
  var kb = S("location", "dl", ""),
    lb = S("referrer", "dr"),
    mb = S("page", "dp", "");
  S("hostname", "dh");
  var nb = S("language", "ul"),
    ob = S("encoding", "de");
  var pb = S("screenColors", "sd"),
    qb = S("screenResolution", "sr"),
    rb = S("viewportSize", "vp"),
    sb = S("javaEnabled", "je"),
    tb = S("flashVersion", "fl");
  S("campaignId", "ci");
  S("campaignName", "cn");
  S("campaignSource", "cs");
  S("campaignMedium", "cm");
  S("campaignKeyword", "ck");
  S("campaignContent", "cc");
  var ub = S("eventCategory", "ec"),
    xb = S("eventAction", "ea"),
    yb = S("eventLabel", "el"),
    zb = S("eventValue", "ev"),
    Bb = S("socialNetwork", "sn"),
    Cb = S("socialAction", "sa"),
    Db = S("socialTarget", "st"),
    Eb = S("l1", "plt"),
    Fb = S("l2", "pdt"),
    Gb = S("l3", "dns"),
    Hb = S("l4", "rrt"),
    Ib = S("l5", "srt"),
    Jb = S("l6", "tcp"),
    Kb = S("l7", "dit"),
    Lb = S("l8", "clt"),
    Ve = S("l9", "_gst"),
    We = S("l10", "_gbt"),
    Xe = S("l11", "_cst"),
    Ye = S("l12", "_cbt"),
    Mb = S("timingCategory", "utc"),
    Nb = S("timingVar", "utv"),
    Ob = S("timingLabel", "utl"),
    Pb = S("timingValue", "utt");
  S("appName", "an");
  S("appVersion", "av", "");
  S("appId", "aid", "");
  S("appInstallerId", "aiid", "");
  S("exDescription", "exd");
  S("exFatal", "exf");
  var Nc = S("expId", "xid"),
    Oc = S("expVar", "xvar"),
    m = S("exp", "exp"),
    Rc = S("_utma", "_utma"),
    Sc = S("_utmz", "_utmz"),
    Tc = S("_utmht", "_utmht"),
    Ua = S("_hc", void 0, 0),
    Xa = S("_ti", void 0, 0),
    Wa = S("_to", void 0, 20);

This seems to be a registry that binds aliases, e.g. appName → an.

Anyway, with that in mind, we can now start to unravel the minified mess of the above JSON request I sent.

request = {
  "Query string": {
    "apiVersion": "1",
    "clientVersion": "j83", // 
    "adSenseId": "1398337363", // you guys use AdSense, huh?
    "hitType": "pageview",
    "_s": "1",
    "location": "https://vuejs.org/",
    "language": "en-us",
    "encoding": "UTF-8",
    "title": "Vue.js",
    "screenColors": "24-bit",
    "screenResolution": "2000x600",
    "viewportSize": "1988x600",
    "javaEnabled": "0",
    "usage": "IEBAAAAB~", // this is really dodgy, it's random on every load.
    "jid": "791792288",
    "gjid": "834920789",
    "clientId": "183173963.1595265292",
    "trackingId": "UA-46852172-1",
    "_gid": "1707634750.1595265292",
    "_r": "1",
    "z": "1439589530" // calculation of "Math.round(2147483647 * Math.random());", couldn't find the real name
  }
}

Looking at all these statistics tells me one thing: using Google Analytics diminishes user privacy.

With that in mind, perhaps sending it to Google in the first place isn't really the wisest idea. I'd love to work something out, and see how we can replace it.


After reloading the page twice, and copying the data sent to the /collect endpoint, I've used a JSON diffing tool to compare the two data sets sent.

5kyejxI

There are a few unique identifiers here, which are also saved as cookies.


As a side note: are you aware that by loading a script that sets tracking cookies, you are supposed to ask for user consent? This is enforced under GDPR: you can find more about that here.

Currently, by using this product, you are sending the following data to Google:

This easily allows Google to fingerprint and watch users travel the internet. They're probably watching you too, right now.

Plus, you said you're just using Google Analytics as a hit counter. Perhaps the majority of this data is actually useless to you?

I'm guessing Netlify's Analytics system doesn't have this same problem? Neither do the FOSS solutions I listed. :stuck_out_tongue: Let's work something out.

I'd like to add on another point: Netlify Analytics is a server-side solution, if I'm not mistaken, which obviously means clients can't block it. This would allow the Vue team to have a much more accurate hit count.

Of course, your target market is developers. A lot of them seem to be blocking Google Analytics, from what I have concluded after extensive investigations.


Google Analytics is quite the slow down too, coming in at a whopping 1106 milliseconds (1.1 seconds) loading time. Just by looking in my developer utilities, it's clear to see that Google Analytics severely slows down the loading time of any and all vuejs.org pages.

This definitely impacts the SEO of vuejs.org, too.


Can't wait to hear back! :stuck_out_tongue: