/* Sandbar website analytics. Add to a page: It sets no cookies and stores nothing in the browser. It sends the page path, the referrer, the language and the browser's own user agent, and it honors Do Not Track. Options on the tag: data-hash (count #hash changes as pages), data-auto="false" (send nothing until you call sandbar.view() yourself). Custom events: sandbar.track("signup", {plan: "pro"}). */ (function () { var tag = document.currentScript; if (!tag) return; var site = tag.getAttribute('data-website'); if (!site) return; var base = tag.src.replace(/\/script\.js(\?.*)?$/, ''); var dnt = navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNotTrack === '1'; var withHash = tag.hasAttribute('data-hash'); var last = ''; var first = true; function send(body) { if (dnt) return; body.website = site; body.hostname = location.hostname; body.language = navigator.language || ''; var json = JSON.stringify(body); // text/plain keeps this a "simple" cross-origin request, so no preflight is needed try { if (navigator.sendBeacon && navigator.sendBeacon(base + '/api/send', new Blob([json], { type: 'text/plain' }))) return; } catch (e) { /* fall through to fetch */ } try { fetch(base + '/api/send', { method: 'POST', body: json, headers: { 'Content-Type': 'text/plain' }, keepalive: true, mode: 'cors', credentials: 'omit' }); } catch (e) { /* analytics must never break the page */ } } function view() { var path = location.pathname + (withHash ? location.hash : ''); if (path === last) return; last = path; send({ path: path, referrer: first ? document.referrer : '' }); first = false; } function hook(name) { var orig = history[name]; if (!orig) return; history[name] = function () { var r = orig.apply(this, arguments); setTimeout(view, 0); return r; }; } hook('pushState'); hook('replaceState'); window.addEventListener('popstate', function () { setTimeout(view, 0); }); if (withHash) window.addEventListener('hashchange', function () { setTimeout(view, 0); }); window.sandbar = { view: view, track: function (name, data) { if (!name) return; send({ path: location.pathname, event: String(name).slice(0, 80), data: data }); } }; if (tag.getAttribute('data-auto') === 'false') return; if (document.readyState === 'complete') view(); else window.addEventListener('load', view); })();