Skip to content

Instantly share code, notes, and snippets.

@mesaavukatlik
Forked from janispritzkau/analytics.js
Created April 22, 2021 08:51
Show Gist options
  • Save mesaavukatlik/9280e6d665b5762ea187b5451c3db538 to your computer and use it in GitHub Desktop.
Save mesaavukatlik/9280e6d665b5762ea187b5451c3db538 to your computer and use it in GitHub Desktop.
Minimal Google Analytics script in modern javascript (677 bytes minified)
((document, location, navigator) => {
const domain = location.hostname.split(".")
const match = document.cookie.match(/(^|; ?)_ga=GA1\.\d\.(\d+\.\d+)(;|$)/)
// use existing client id or generate one
const cid = match ? match[2] : ~~(2147483648 * Math.random()) + "." + ~~(Date.now() / 1000)
// set cookie at highest possible domain level
for (let i = domain.length; i--;) {
const cookie = `_ga=GA1.${domain.length - i}.${cid}`
document.cookie = `${cookie}; max-age=63115200; domain=${domain.slice(i).join(".")}`
if (document.cookie.split(/; ?/).includes(cookie)) break
}
// alternatively set the cookie at a specified domain
// document.cookie = `_ga=GA1.3.${cid}; max-age=63115200; domain=subdomain.example.com`
// you can also use a custom storage mechanism for the client ID if you do not need to be compatible with the _ga cookie.
window.track = (type, ec, ea, el, ev) => {
const data = {
v: 1,
tid: "UA-XXXX-Y", // replace with your tracking id
aip: 1,
cid,
t: type,
dr: document.referrer,
dt: document.title,
dl: location.href,
ul: navigator.language.toLowerCase(),
sr: `${screen.width}x${screen.height}`,
vp: `${innerWidth}x${innerHeight}`
}
if (ec) data.ec = ec
if (ea) data.ea = ea
if (el) data.el = el
if (ev) data.ev = ev
navigator.sendBeacon("https://google-analytics.com/collect", new URLSearchParams(data))
}
track("pageview")
})(document, location, navigator)
// minified ES2015 (677 bytes)
((e,a,t)=>{for(var i,o,n=a.hostname.split("."),c=e.cookie.match(/(^|; ?)_ga=GA1\.\d\.(\d+\.\d+)(;|$)/),r=c?c[2]:~~(2e9*Math.random())+"."+~~(Date.now()/1e3),l=n.length;l--&&(o=`_ga=GA1.${n.length-l}.${r}`,e.cookie=`${o};max-age=63115200;domain=${n.slice(l).join(".")}`,!e.cookie.split(/; ?/).includes(o)););track=((o,n,c,l,d)=>{i={v:1,tid:"UA-XXXX-Y",aip:1,cid:r,t:o,dr:e.referrer,dt:e.title,dl:a.href,ul:t.language.toLowerCase(),sr:`${screen.width}x${screen.height}`,vp:`${innerWidth}x${innerHeight}`},n&&(i.ec=n),c&&(i.ea=c),l&&(i.el=l),d&&(i.ev=d),t.sendBeacon("https://google-analytics.com/collect",new URLSearchParams(i))}),track("pageview")})(document,location,navigator)
// minified ES5 (819 bytes)
!function(e,n,t){for(var o,a,i,c,r,d="https://google-analytics.com/collect",s=n.hostname.split("."),l=e.cookie.match(/(^|; ?)_ga=GA1\.\d\.(\d+\.\d+)(;|$)/),h=l?l[2]:~~(2e9*Math.random())+"."+~~(Date.now()/1e3),g=s.length;g--&&(r="_ga=GA1."+(s.length-g)+"."+h,e.cookie=r+";max-age=63115200;domain="+s.slice(g).join("."),-1==e.cookie.split(/; ?/).indexOf(r)););track=((r,s,l,g,p)=>{if(o={v:1,tid:"UA-XXXX-Y",aip:1,cid:h,t:r,dr:e.referrer,dt:e.title,dl:n.href,ul:t.language.toLowerCase(),sr:screen.width+"x"+screen.height,vp:innerWidth+"x"+innerHeight},s&&(o.ec=s),l&&(o.ea=l),g&&(o.el=g),p&&(o.ev=p),t.sendBeacon)t.sendBeacon(d,new URLSearchParams(o));else{for(c in a=[],i=new XMLHttpRequest,o)a.push(k+"="+encodeURIComponent(o[c]));i.open("POST",d),i.send(a.join("&"))}}),track("pageview")}(document,location,navigator);
@mindplay-dk
Copy link

mindplay-dk commented Oct 21, 2024

EDIT: I realized too late this script doesn't work since GA4 - and the updates I posted (below) don't work either.

To others finding this gist in search of a minimal viable replacement, here is one for GA4 that still receives updates:

https://gist.github.com/idarek/9ade69ac2a2ef00d98ab950426af5791


I was wondering if we could also make the script GDPR compliant.

I don't want to track users, or pester them for permissions - I just want to use GA to count page views, etc.

  • Instead of using a cookie with a 2-year life span, it uses sessionStorage, so that we're no longer tracking users, and instead only tracking the visit.
  • If the user keeps a tab open for more than 12 hours, we also cycle the client ID, ensuring we count two days of activity as two visits.
((document, location, navigator) => {
  // Generate a new client ID
  const generateCid = () => ~~(2147483648 * Math.random()) + "." + ~~(Date.now() / 1000);

  // Get or generate a new client ID, rotating it every 24 hours
  const getSessionCid = () => {
    let cid = sessionStorage.getItem('_ga_session_id');
    const cidTimestamp = parseInt(sessionStorage.getItem('_ga_session_id_timestamp') || '0');

    // Rotate the client ID every 24 hours
    if (!cid || (Date.now() - cidTimestamp) > 12*60*60*1000) {
      cid = generateCid();
      sessionStorage.setItem('_ga_session_id', cid);
      sessionStorage.setItem('_ga_session_id_timestamp', Date.now().toString());
    }

    return cid;
  };

  window.track = (type, ec, ea, el, ev) => {
    const cid = getSessionCid();
    const data = {
      v: 1,
      tid: "UA-XXXX-Y", // replace with your tracking id
      aip: 1,
      cid,
      t: type,
      dr: document.referrer,
      dt: document.title,
      dl: location.href,
      ul: navigator.language.toLowerCase(),
      sr: `${screen.width}x${screen.height}`,
      vp: `${innerWidth}x${innerHeight}`
    };

    if (ec) data.ec = ec;
    if (ea) data.ea = ea;
    if (el) data.el = el;
    if (ev) data.ev = ev;

    navigator.sendBeacon("https://google-analytics.com/collect", new URLSearchParams(data));
  };

  track("pageview");
})(document, location, navigator);

I understand this will produce different (higher) unique visitor numbers, but I think that's probably okay, as long as we understand that what we mean by unique visitors is now slightly different from the usual Google Analytics definition.

What do you think of this approach?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment