Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Minimal Analytics Snippet
(function (context, trackingId, options) {
const history = context.history;
const doc = document;
const nav = navigator || {};
const storage = localStorage;
const encode = encodeURIComponent;
const pushState = history.pushState;
const typeException = 'exception';
const generateId = () => Math.random().toString(36);
const getId = () => {
if (!storage.cid) {
storage.cid = generateId()
}
return storage.cid;
};
const serialize = (obj) => {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
if(obj[p] !== undefined) {
str.push(encode(p) + "=" + encode(obj[p]));
}
}
}
return str.join("&");
};
const track = (
type,
eventCategory,
eventAction,
eventLabel,
eventValue,
exceptionDescription,
exceptionFatal
) => {
const url = 'https://www.google-analytics.com/collect';
const data = serialize({
v: '1',
ds: 'web',
aip: options.anonymizeIp ? 1 : undefined,
tid: trackingId,
cid: getId(),
t: type || 'pageview',
sd: options.colorDepth && screen.colorDepth ? `${screen.colorDepth}-bits` : undefined,
dr: doc.referrer || undefined,
dt: doc.title,
dl: doc.location.origin + doc.location.pathname + doc.location.search,
ul: options.language ? (nav.language || "").toLowerCase() : undefined,
de: options.characterSet ? doc.characterSet : undefined,
sr: options.screenSize ? `${(context.screen || {}).width}x${(context.screen || {}).height}` : undefined,
vp: options.screenSize && context.visualViewport ? `${(context.visualViewport || {}).width}x${(context.visualViewport || {}).height}` : undefined,
ec: eventCategory || undefined,
ea: eventAction || undefined,
el: eventLabel || undefined,
ev: eventValue || undefined,
exd: exceptionDescription || undefined,
exf: typeof exceptionFatal !== 'undefined' && !!exceptionFatal === false ? 0 : undefined,
});
if(nav.sendBeacon) {
nav.sendBeacon(url, data)
} else {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.send(data);
}
};
const trackEvent = (category, action, label, value) => track('event', category, action, label, value);
const trackException = (description, fatal) => track(typeException, null, null, null, null, description, fatal);
history.pushState = function (state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({ state: state });
}
setTimeout(track, options.delay || 10);
return pushState.apply(history, arguments);
}
track();
context.ma = {
trackEvent,
trackException
}
})(window, "XX-XXXXXXXXX-X", {
anonymizeIp: true,
colorDepth: true,
characterSet: true,
screenSize: true,
language: true
});
@tudou-wp

This comment has been minimized.

Copy link

@tudou-wp tudou-wp commented Dec 14, 2018

Before I saw this, I always host ga.js locally to improve performance. I'm thinking post action to GA with nginx in the back-end.
I have the same problem like you with GTM, thank you for making this!
Could this method be used to track speed, events and goals too?

@DavidKuennen

This comment has been minimized.

Copy link
Owner Author

@DavidKuennen DavidKuennen commented Dec 14, 2018

@tudou-wp currently not, but I got a lot of feature requests exposing a function to add events. It shouldn't add any significant size.

For all those who want to create their own version, here is the official documentation of this GA endpoint: https://developers.google.com/analytics/devguides/collection/protocol/v1/reference

I'm using https://babeljs.io/en/repl to minify and convert it to a snippet.

@brandonmcconnell

This comment has been minimized.

Copy link

@brandonmcconnell brandonmcconnell commented Dec 16, 2018

Any way to add the Optimize snippet to this code?

@DavidKuennen

This comment has been minimized.

Copy link
Owner Author

@DavidKuennen DavidKuennen commented Dec 16, 2018

Improvements:

  • Using navigator.sendBeacon if available
  • Ability to track events
  • Ability to track exceptions
@neodigm

This comment has been minimized.

Copy link

@neodigm neodigm commented Dec 17, 2018

Hi David, I find this useful. Thanks.

@nikrowell

This comment has been minimized.

Copy link

@nikrowell nikrowell commented Dec 18, 2018

Clever! Would be interested in seeing this on npm, obviously with the mga.init({...}) abstracted out.
Thanks for sharing!

@webmasterish

This comment has been minimized.

Copy link

@webmasterish webmasterish commented Dec 23, 2018

Great idea! Just used it to make a VuePress plugin.

@Lexicality

This comment has been minimized.

Copy link

@Lexicality Lexicality commented Dec 23, 2018

What's the onpushstate bit for?

@javiercasares

This comment has been minimized.

Copy link

@javiercasares javiercasares commented Dec 26, 2018

To compliance with the GDPR and similar, we have 2 options:

ga('create', 'UA-123456789-1');
ga('set', 'allowAdFeatures', false);
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');

This supports "anonymizeIp"... is it possible to support "allowAdFeatures"?

@javiercasares

This comment has been minimized.

Copy link

@javiercasares javiercasares commented Dec 27, 2018

FYI, I've launched a WordPress plugin based on your code... https://wordpress.org/plugins/minimal-analytics/

@standoski

This comment has been minimized.

Copy link

@standoski standoski commented Jan 6, 2019

  1. Thanks for sharing this implementation!

  2. Please add somewhere on the https://minimalanalytics.com/ the time when was last updated the snippet code from there.

  3. Could you make a version that have implemented the "timing" features?
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#timing

Thanks!

@nwellnhof

This comment has been minimized.

Copy link

@nwellnhof nwellnhof commented Jan 14, 2019

Support for custom parameters, for example to implement custom dimensions, would be great.

@waqasy

This comment has been minimized.

Copy link

@waqasy waqasy commented Jan 21, 2019

How to send pageview hit?

ma('pageview', pageURL); ??

EDIT: I think only track(); will record pageview hit. I need to record pageview on quick view products.

@pau-ker

This comment has been minimized.

Copy link

@pau-ker pau-ker commented Jan 28, 2019

Will this work with the 'ga-disable-UA-XXXXXXX-X' OptOut Cookie?

@martpie

This comment has been minimized.

Copy link

@martpie martpie commented Feb 8, 2019

Awesome script!

I am running into a similar problem than @nwellnhof, I am using it as a Nuxt plugin (similarly as https://nuxtjs.org/faq/google-analytics#how-to-use-google-analytics-), but it seems that when changing routes, no even is recorded.

Typically, Nuxt tells us to add something like

  app.router.afterEach((to, from) => {
    /*
    ** We tell Google Analytics to add a `pageview`
    */
    ga('set', 'page', to.fullPath)
    ga('send', 'pageview')
  })

Also works for single page applications made with the likes of react and vue.js.

Did someone verify it?

@vnglst

This comment has been minimized.

Copy link

@vnglst vnglst commented Mar 16, 2019

I've created an npm packages for this, mainly for personal use: https://www.npmjs.com/package/minimal-analytics

I'm also thinking about creating an even more minimal version of analytics, that does the bare minimum of tracking (i.e. only pageviews + ip) just like StatCounter in the old day.

@WesCook

This comment has been minimized.

Copy link

@WesCook WesCook commented Mar 26, 2019

Any idea if this snippet functions well in an external script file? It's kind of a big block to embed on every page.

edit: I've had a chance to test this. Everything seems to work just fine in a separate file.

@curtisbelt

This comment has been minimized.

Copy link

@curtisbelt curtisbelt commented Mar 26, 2019

@martpie any luck with Nuxt.js integration? I'm in the same boat as you, just found this.

@JoseeWouters

This comment has been minimized.

Copy link

@JoseeWouters JoseeWouters commented May 12, 2019

Great script, thanks!

@curtisbelt @martpie I've got it working with Nuxt.js. I've put the code in a separate js file in my static folder and included it in the head property in my nuxt.config.js file. Analytics is showing the slugs of the pages I visited.

@jcuenod

This comment has been minimized.

Copy link

@jcuenod jcuenod commented Jun 2, 2019

I'm with @waqasy: Is it possible to do something like ma.trackPageview(pageURL)? It looks like some old pageview code was removed...

@kaknut

This comment has been minimized.

Copy link

@kaknut kaknut commented Jun 20, 2019

Can anyone who uses this please tell me whether it only tracks pageviews or other basic stuffs like sessions and number of users?

@midudev

This comment has been minimized.

Copy link

@midudev midudev commented Aug 11, 2019

Hi @kaknut! Yes, pageviews are tracked correctly as well as session and number of users. Example of something that's not being tracked: RUM performance.

@bkarlson

This comment has been minimized.

Copy link

@bkarlson bkarlson commented Oct 9, 2019

Fantastic script! You can probably make it support hashed routes out of the box by adding + doc.hash @ L47

@bkarlson

This comment has been minimized.

Copy link

@bkarlson bkarlson commented Oct 17, 2019

any idea how to implement sampleRate in this script?

@bkarlson

This comment has been minimized.

Copy link

@bkarlson bkarlson commented Dec 6, 2019

btw, I just realized this fails in Safari incognito mode due to localStorage not available

(DOM Exception 22): The quota has been exceeded.

@janispritzkau

This comment has been minimized.

Copy link

@janispritzkau janispritzkau commented Feb 24, 2020

I created one that's compatible with the cookie format of the Google analytics.js script. It's very minimal, just under 700 bytes when minified

https://gist.github.com/janispritzkau/c9fe29242af53fd1b10a847da78b3406

@brielov

This comment has been minimized.

Copy link

@brielov brielov commented Mar 24, 2020

What about using URLSearchParams instead of serialize?

@janispritzkau

This comment has been minimized.

Copy link

@janispritzkau janispritzkau commented Mar 25, 2020

Yep. It would make sense if you're only targeting browsers that support ES6 and newer. I used it in my tiny analytics script

@wpsumo

This comment has been minimized.

Copy link

@wpsumo wpsumo commented May 28, 2020

How do I track event with inline js in minimal analytics?
Is it just Event: onClick="ma.trackEvent('Category', 'Action', 'Label', 'Value');" instead of onClick="ga('send', 'event', 'category', 'action', 'label', value);"

@winston0410

This comment has been minimized.

Copy link

@winston0410 winston0410 commented Jun 15, 2020

How do I make this script work with Turbolinks? It seems like it cannot capture pageview if I am using Turbolinks with it.

@idarek

This comment has been minimized.

Copy link

@idarek idarek commented Sep 7, 2020

Hello, can somebody advise:

  1. which code is up-to-date? the above minimal-analytics-snippet.js or https://minimalanalytics.com/ as there are differences hence not sure which one to use in the first place.
  2. If I understand correctly, this will only send information when the user will visit the site and will not work in the background to measure the time spent on the website (session duration)?
@WesCook

This comment has been minimized.

Copy link

@WesCook WesCook commented Sep 7, 2020

@idarek, the code above is in its original form. The version on https://minimalanalytics.com/ is minified. Use the minified version in production to produce a smaller page.

@idarek

This comment has been minimized.

Copy link

@idarek idarek commented Sep 8, 2020

Anybody about the other part? Is it possible to add timings?

  1. If I understand correctly, this will only send information when the user will visit the site and will not work in the background to measure the time spent on the website (session duration)?
@brielov

This comment has been minimized.

Copy link

@brielov brielov commented Sep 8, 2020

@idarek The snippet is very well thought but you can use it as a template to build your own and even convert it to a function and call it whenever you want, I've used this as a base for my react projects and converted it as a hook.

@idarek

This comment has been minimized.

Copy link

@idarek idarek commented Oct 3, 2020

Installed on my website without any modification. Firstly though that will lose insight into average session duration (i know that is not accurate but always something) but I didn't which is great. Nice improvement recorded for the website as well. Great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.