From 2ea91aaabfec51de37a1289e040de2792654b72b Mon Sep 17 00:00:00 2001 From: Bartosz Hernas Date: Mon, 14 Sep 2020 18:13:59 +0200 Subject: [PATCH 01/10] Ability to unregister umami --- lib/web.js | 8 +++++--- tracker/index.js | 12 ++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/web.js b/lib/web.js index 4a8578f1dd..784a9e1ecb 100644 --- a/lib/web.js +++ b/lib/web.js @@ -39,12 +39,14 @@ export const put = (url, params) => apiRequest('put', url, JSON.stringify(params export const hook = (_this, method, callback) => { const orig = _this[method]; - - return (...args) => { + _this[method] = (...args) => { callback.apply(null, args); - return orig.apply(_this, args); }; + + return () => { + _this[method] = orig; + }; }; export const doNotTrack = () => { diff --git a/tracker/index.js b/tracker/index.js index f7f0092773..0b91d4e713 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -73,8 +73,8 @@ import { removeTrailingSlash } from '../lib/url'; pageView(); }; - history.pushState = hook(history, 'pushState', handlePush); - history.replaceState = hook(history, 'replaceState', handlePush); + const pushStateUnhook = hook(history, 'pushState', handlePush); + const replaceStateUnhook = hook(history, 'replaceState', handlePush); /* Handle events */ @@ -106,4 +106,12 @@ import { removeTrailingSlash } from '../lib/url'; if (!window.umami) { window.umami = event_value => collect('event', { event_type: 'custom', event_value }); } + + if (!window.umamiUnregister) { + window.umamiUnregister = () => { + pushStateUnhook(); + replaceStateUnhook(); + removeEvents(); + }; + } })(window); From d19bcbabe053e6b6eb80138818acaa0bed70ea7a Mon Sep 17 00:00:00 2001 From: Bartosz Hernas Date: Tue, 15 Sep 2020 00:09:09 +0200 Subject: [PATCH 02/10] Different method + fixed lint for tracker + added frame mode for shared URLs --- lib/web.js | 8 ++--- pages/share/[...id].js | 4 +-- tracker/index.js | 69 ++++++++++++++++++++++-------------------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/lib/web.js b/lib/web.js index 784a9e1ecb..4a8578f1dd 100644 --- a/lib/web.js +++ b/lib/web.js @@ -39,13 +39,11 @@ export const put = (url, params) => apiRequest('put', url, JSON.stringify(params export const hook = (_this, method, callback) => { const orig = _this[method]; - _this[method] = (...args) => { + + return (...args) => { callback.apply(null, args); - return orig.apply(_this, args); - }; - return () => { - _this[method] = orig; + return orig.apply(_this, args); }; }; diff --git a/pages/share/[...id].js b/pages/share/[...id].js index 1e0897a9dc..50467bf6cf 100644 --- a/pages/share/[...id].js +++ b/pages/share/[...id].js @@ -6,7 +6,7 @@ import useFetch from 'hooks/useFetch'; export default function SharePage() { const router = useRouter(); - const { id } = router.query; + const { id, frame } = router.query; const shareId = id?.[0]; const { data } = useFetch(shareId ? `/api/share/${shareId}` : null); @@ -15,7 +15,7 @@ export default function SharePage() { } return ( - + ); diff --git a/tracker/index.js b/tracker/index.js index 0b91d4e713..7bb1b7b3a3 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -1,6 +1,6 @@ import 'promise-polyfill/src/polyfill'; import 'unfetch/polyfill'; -import { post, hook, doNotTrack } from '../lib/web'; +import { doNotTrack, hook, post } from '../lib/web'; import { removeTrailingSlash } from '../lib/url'; (window => { @@ -31,25 +31,7 @@ import { removeTrailingSlash } from '../lib/url'; /* Collect metrics */ const collect = (type, params) => { - const payload = { - url: currentUrl, - referrer: currentRef, - website, - hostname, - screen, - language, - }; - - if (params) { - Object.keys(params).forEach(key => { - payload[key] = params[key]; - }); - } - - return post(`${root}/api/collect`, { - type, - payload, - }); + return window.umamiTrack(website, type, params); }; const pageView = () => collect('pageview').then(() => setTimeout(loadEvents, 300)); @@ -73,8 +55,8 @@ import { removeTrailingSlash } from '../lib/url'; pageView(); }; - const pushStateUnhook = hook(history, 'pushState', handlePush); - const replaceStateUnhook = hook(history, 'replaceState', handlePush); + history.pushState = hook(history, 'pushState', handlePush); + history.replaceState = hook(history, 'replaceState', handlePush); /* Handle events */ @@ -86,7 +68,7 @@ import { removeTrailingSlash } from '../lib/url'; }; const loadEvents = () => { - document.querySelectorAll("[class*='umami--']").forEach(element => { + document.querySelectorAll('[class*=\'umami--\']').forEach(element => { element.className.split(' ').forEach(className => { if (/^umami--([a-z]+)--([a-z0-9_]+[a-z0-9-_]+)$/.test(className)) { const [, type, value] = className.split('--'); @@ -99,19 +81,40 @@ import { removeTrailingSlash } from '../lib/url'; }); }; - /* Start */ + if (!window.umamiTrack) { + window.umamiTrack = (type, params, id) => { + if (!id) { + id = website + } + const payload = { + url: currentUrl, + referrer: currentRef, + website: id, + hostname, + screen, + language, + }; + + if (params) { + Object.keys(params).forEach(key => { + payload[key] = params[key]; + }); + } + + return post(`${root}/api/collect`, { + type, + payload, + }); + }; + } - pageView(); + /* Start */ + const skipAuto = new URL(script.src).search.includes('auto=false'); + if (!skipAuto) { + pageView(); + } if (!window.umami) { window.umami = event_value => collect('event', { event_type: 'custom', event_value }); } - - if (!window.umamiUnregister) { - window.umamiUnregister = () => { - pushStateUnhook(); - replaceStateUnhook(); - removeEvents(); - }; - } })(window); From d6d1c68e6dbacdda3aa8b2fac70322a1c873f49e Mon Sep 17 00:00:00 2001 From: Bartosz Hernas Date: Tue, 15 Sep 2020 00:12:09 +0200 Subject: [PATCH 03/10] Fix tracker --- tracker/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tracker/index.js b/tracker/index.js index 7bb1b7b3a3..9c00a47b59 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -55,9 +55,6 @@ import { removeTrailingSlash } from '../lib/url'; pageView(); }; - history.pushState = hook(history, 'pushState', handlePush); - history.replaceState = hook(history, 'replaceState', handlePush); - /* Handle events */ const removeEvents = () => { @@ -84,7 +81,7 @@ import { removeTrailingSlash } from '../lib/url'; if (!window.umamiTrack) { window.umamiTrack = (type, params, id) => { if (!id) { - id = website + id = website; } const payload = { url: currentUrl, @@ -111,6 +108,8 @@ import { removeTrailingSlash } from '../lib/url'; /* Start */ const skipAuto = new URL(script.src).search.includes('auto=false'); if (!skipAuto) { + history.pushState = hook(history, 'pushState', handlePush); + history.replaceState = hook(history, 'replaceState', handlePush); pageView(); } From d5e49141532455b409310b920e98cdf19b0ed3bb Mon Sep 17 00:00:00 2001 From: Bartosz Hernas Date: Tue, 15 Sep 2020 12:03:34 +0200 Subject: [PATCH 04/10] Comments fixed --- pages/share/[...id].js | 4 ++-- tracker/index.js | 44 +++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/pages/share/[...id].js b/pages/share/[...id].js index 50467bf6cf..1e0897a9dc 100644 --- a/pages/share/[...id].js +++ b/pages/share/[...id].js @@ -6,7 +6,7 @@ import useFetch from 'hooks/useFetch'; export default function SharePage() { const router = useRouter(); - const { id, frame } = router.query; + const { id } = router.query; const shareId = id?.[0]; const { data } = useFetch(shareId ? `/api/share/${shareId}` : null); @@ -15,7 +15,7 @@ export default function SharePage() { } return ( - + ); diff --git a/tracker/index.js b/tracker/index.js index 9c00a47b59..ff7f099522 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -19,6 +19,7 @@ import { removeTrailingSlash } from '../lib/url'; const website = script.getAttribute('data-website-id'); const hostUrl = script.getAttribute('data-host-url'); + const skipAuto = script.getAttribute('data-skip-auto'); const root = hostUrl ? removeTrailingSlash(hostUrl) : new URL(script.src).href.split('/').slice(0, -1).join('/'); @@ -29,14 +30,7 @@ import { removeTrailingSlash } from '../lib/url'; let currentRef = document.referrer; /* Collect metrics */ - - const collect = (type, params) => { - return window.umamiTrack(website, type, params); - }; - - const pageView = () => collect('pageview').then(() => setTimeout(loadEvents, 300)); - - const pageEvent = (event_type, event_value) => collect('event', { event_type, event_value }); + const pageViewWithAutoEvents = (url, referrer) => window.umami.pageView(url, referrer).then(() => setTimeout(loadEvents, 300)); /* Handle history */ @@ -52,7 +46,7 @@ import { removeTrailingSlash } from '../lib/url'; currentUrl = newUrl; } - pageView(); + pageViewWithAutoEvents(currentUrl, currentRef); }; /* Handle events */ @@ -69,7 +63,7 @@ import { removeTrailingSlash } from '../lib/url'; element.className.split(' ').forEach(className => { if (/^umami--([a-z]+)--([a-z0-9_]+[a-z0-9-_]+)$/.test(className)) { const [, type, value] = className.split('--'); - const listener = () => pageEvent(type, value); + const listener = () => window.umami.event(type, value); listeners.push([element, type, listener]); element.addEventListener(type, listener, true); @@ -78,14 +72,13 @@ import { removeTrailingSlash } from '../lib/url'; }); }; - if (!window.umamiTrack) { - window.umamiTrack = (type, params, id) => { + if (!window.umami) { + window.umami = event_value => window.umami.event('custom', event_value, currentUrl); + window.umami.collect = (type, params, id) => { if (!id) { id = website; } const payload = { - url: currentUrl, - referrer: currentRef, website: id, hostname, screen, @@ -103,17 +96,24 @@ import { removeTrailingSlash } from '../lib/url'; payload, }); }; + window.umami.pageView = (url = currentUrl, referrer = currentRef) => window.umami.collect('pageview', { + url, + referrer, + }); + window.umami.event = (event_type, event_value, url = currentUrl) => window.umami.collect('event', { + url, + event_type, + event_value, + }); + window.umami.registerAutoEvents = () => { + history.pushState = hook(history, 'pushState', handlePush); + history.replaceState = hook(history, 'replaceState', handlePush); + return pageViewWithAutoEvents(currentUrl, currentRef); + }; } /* Start */ - const skipAuto = new URL(script.src).search.includes('auto=false'); if (!skipAuto) { - history.pushState = hook(history, 'pushState', handlePush); - history.replaceState = hook(history, 'replaceState', handlePush); - pageView(); - } - - if (!window.umami) { - window.umami = event_value => collect('event', { event_type: 'custom', event_value }); + window.umami.registerAutoEvents().catch(e => console.error(e)); } })(window); From 7a71bb1c68256ee611cc6751f9c4295a3714b004 Mon Sep 17 00:00:00 2001 From: Bartosz Hernas Date: Tue, 15 Sep 2020 13:54:35 +0200 Subject: [PATCH 05/10] Better snippet --- .gitignore | 1 + components/forms/TrackingCodeForm.js | 5 +- package.json | 1 + rollup.snippet.config.js | 19 ++++++ tracker/index.js | 91 +++++++++++++++++----------- tracker/snippet.js | 42 +++++++++++++ 6 files changed, 121 insertions(+), 38 deletions(-) create mode 100644 rollup.snippet.config.js create mode 100644 tracker/snippet.js diff --git a/.gitignore b/.gitignore index ca0f3c4f7c..8b349dbb41 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ # production /build /public/umami.js +/public/snippet.js /lang-compiled /lang-formatted diff --git a/components/forms/TrackingCodeForm.js b/components/forms/TrackingCodeForm.js index a98b471db5..36dda30e43 100644 --- a/components/forms/TrackingCodeForm.js +++ b/components/forms/TrackingCodeForm.js @@ -17,12 +17,15 @@ export default function TrackingCodeForm({ values, onClose }) { />

+ {/* Run `npm run build-snippet, and copy paste here the content of public/snippet.js */} + {/* TODO: use webpack importing function to import the content of the file here ? */}