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

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

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

commented Dec 16, 2018

Any way to add the Optimize snippet to this code?

@DavidKuennen

This comment has been minimized.

Copy link
Owner Author

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

commented Dec 17, 2018

Hi David, I find this useful. Thanks.

@nikrowell

This comment has been minimized.

Copy link

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

commented Dec 23, 2018

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

@Lexicality

This comment has been minimized.

Copy link

commented Dec 23, 2018

What's the onpushstate bit for?

@javiercasares

This comment has been minimized.

Copy link

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

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

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

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

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

commented Jan 28, 2019

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

@martpie

This comment has been minimized.

Copy link

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

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

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

commented Mar 26, 2019

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

@gijo-varghese

This comment has been minimized.

Copy link

commented Apr 20, 2019

does 'Real-Time' work with this?

@JoseeWouters

This comment has been minimized.

Copy link

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.

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.