+
Page links
page one
@@ -114,12 +114,11 @@ export function TestConsole({ websiteId }: { websiteId: string }) {
-
+
Click events
-
+
+
+ DIV with attribute
+
+
-
+
Javascript events
-
-
-
-
-
- >
+
+
+
)}
);
diff --git a/src/components/hooks/useDateRange.ts b/src/components/hooks/useDateRange.ts
index 115546c7..764c5968 100644
--- a/src/components/hooks/useDateRange.ts
+++ b/src/components/hooks/useDateRange.ts
@@ -46,7 +46,7 @@ export function useDateRange(websiteId?: string) {
};
return [dateRange, saveDateRange] as [
- { startDate: Date; endDate: Date; modified?: number; value?: string },
+ { startDate: Date; endDate: Date; modified?: number; value?: string; unit?: string },
(value: string | DateRange) => void,
];
}
diff --git a/src/components/metrics/EventsChart.tsx b/src/components/metrics/EventsChart.tsx
index be6d4a0c..d4f85ed7 100644
--- a/src/components/metrics/EventsChart.tsx
+++ b/src/components/metrics/EventsChart.tsx
@@ -77,10 +77,10 @@ export function EventsChart({ websiteId, className, token }: EventsChartProps) {
className={className}
datasets={datasets}
unit={unit}
- loading={isLoading}
- stacked
+ stacked={true}
renderXLabel={renderDateLabels(unit, locale)}
renderTooltipPopup={renderStatusTooltipPopup(unit, locale)}
+ isLoading={isLoading}
/>
);
}
diff --git a/src/components/metrics/Legend.tsx b/src/components/metrics/Legend.tsx
index ce8a3381..95e4a3d2 100644
--- a/src/components/metrics/Legend.tsx
+++ b/src/components/metrics/Legend.tsx
@@ -10,7 +10,7 @@ export function Legend({ chart }) {
const { locale } = useLocale();
const forceUpdate = useForceUpdate();
- const handleClick = index => {
+ const handleClick = (index: string | number) => {
const meta = chart.getDatasetMeta(index);
meta.hidden = meta.hidden === null ? !chart.data.datasets[index].hidden : null;
diff --git a/src/tracker/index.js b/src/tracker/index.js
index 709adc6c..326cd825 100644
--- a/src/tracker/index.js
+++ b/src/tracker/index.js
@@ -31,16 +31,6 @@
/* Helper functions */
- const hook = (_this, method, callback) => {
- const orig = _this[method];
-
- return (...args) => {
- callback.apply(null, args);
-
- return orig.apply(_this, args);
- };
- };
-
const getPath = url => {
try {
return new URL(url).pathname;
@@ -59,10 +49,7 @@
referrer: currentRef,
});
- /* Tracking functions */
- const trackingDisabled = () =>
- (localStorage && localStorage.getItem('umami.disabled')) ||
- (domain && !domains.includes(hostname));
+ /* Event handlers */
const handlePush = (state, title, url) => {
if (!url) return;
@@ -75,77 +62,25 @@
}
};
- const handleClick = () => {
- const trackElement = el => {
- const attr = el.getAttribute.bind(el);
- const eventName = attr(eventNameAttribute);
+ const handlePathChanges = () => {
+ const hook = (_this, method, callback) => {
+ const orig = _this[method];
- if (eventName) {
- const eventData = {};
+ return (...args) => {
+ callback.apply(null, args);
- el.getAttributeNames().forEach(name => {
- const match = name.match(eventRegex);
-
- if (match) {
- eventData[match[1]] = attr(name);
- }
- });
-
- return track(eventName, eventData);
- }
- return Promise.resolve();
- };
-
- const callback = e => {
- const findATagParent = (rootElem, maxSearchDepth) => {
- let currentElement = rootElem;
- for (let i = 0; i < maxSearchDepth; i++) {
- if (currentElement.tagName === 'A') {
- return currentElement;
- }
- currentElement = currentElement.parentElement;
- if (!currentElement) {
- return null;
- }
- }
- return null;
+ return orig.apply(_this, args);
};
-
- const el = e.target;
- const anchor = el.tagName === 'A' ? el : findATagParent(el, 10);
-
- if (anchor) {
- const { href, target } = anchor;
- const external =
- target === '_blank' ||
- e.ctrlKey ||
- e.shiftKey ||
- e.metaKey ||
- (e.button && e.button === 1);
- const eventName = anchor.getAttribute(eventNameAttribute);
-
- if (eventName && href) {
- if (!external) {
- e.preventDefault();
- }
- return trackElement(anchor).then(() => {
- if (!external) location.href = href;
- });
- }
- } else {
- trackElement(el);
- }
};
- document.addEventListener('click', callback, true);
+ history.pushState = hook(history, 'pushState', handlePush);
+ history.replaceState = hook(history, 'replaceState', handlePush);
};
- const observeTitle = () => {
- const callback = ([entry]) => {
+ const handleTitleChanges = () => {
+ const observer = new MutationObserver(([entry]) => {
title = entry && entry.target ? entry.target.text : undefined;
- };
-
- const observer = new MutationObserver(callback);
+ });
const node = document.querySelector('head > title');
@@ -158,6 +93,86 @@
}
};
+ const handleClicks = () => {
+ document.addEventListener(
+ 'click',
+ async e => {
+ const isSpecialTag = tagName => ['BUTTON', 'A'].includes(tagName);
+
+ const trackElement = async el => {
+ const attr = el.getAttribute.bind(el);
+ const eventName = attr(eventNameAttribute);
+
+ if (eventName) {
+ const eventData = {};
+
+ el.getAttributeNames().forEach(name => {
+ const match = name.match(eventRegex);
+
+ if (match) {
+ eventData[match[1]] = attr(name);
+ }
+ });
+
+ return track(eventName, eventData);
+ }
+ };
+
+ const findParentTag = (rootElem, maxSearchDepth) => {
+ let currentElement = rootElem;
+ for (let i = 0; i < maxSearchDepth; i++) {
+ if (isSpecialTag(currentElement.tagName)) {
+ return currentElement;
+ }
+ currentElement = currentElement.parentElement;
+ if (!currentElement) {
+ return null;
+ }
+ }
+ };
+
+ const el = e.target;
+ const parentElement = isSpecialTag(el.tagName) ? el : findParentTag(el, 10);
+
+ if (parentElement) {
+ const { href, target } = parentElement;
+ const eventName = parentElement.getAttribute(eventNameAttribute);
+
+ if (eventName) {
+ if (parentElement.tagName === 'A') {
+ const external =
+ target === '_blank' ||
+ e.ctrlKey ||
+ e.shiftKey ||
+ e.metaKey ||
+ (e.button && e.button === 1);
+
+ if (eventName && href) {
+ if (!external) {
+ e.preventDefault();
+ }
+ return trackElement(parentElement).then(() => {
+ if (!external) location.href = href;
+ });
+ }
+ } else if (parentElement.tagName === 'BUTTON') {
+ return trackElement(parentElement);
+ }
+ }
+ } else {
+ return trackElement(el);
+ }
+ },
+ true,
+ );
+ };
+
+ /* Tracking functions */
+
+ const trackingDisabled = () =>
+ (localStorage && localStorage.getItem('umami.disabled')) ||
+ (domain && !domains.includes(hostname));
+
const send = async (payload, type = 'event') => {
if (trackingDisabled()) return;
const headers = {
@@ -173,6 +188,7 @@
headers,
});
const text = await res.text();
+
return (cache = text);
} catch {
/* empty */
@@ -212,10 +228,9 @@
let initialized;
if (autoTrack && !trackingDisabled()) {
- history.pushState = hook(history, 'pushState', handlePush);
- history.replaceState = hook(history, 'replaceState', handlePush);
- handleClick();
- observeTitle();
+ handlePathChanges();
+ handleTitleChanges();
+ handleClicks();
const init = () => {
if (document.readyState === 'complete' && !initialized) {
diff --git a/yarn.lock b/yarn.lock
index 3315cf11..26d175ea 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2074,15 +2074,6 @@
dependencies:
slash "^4.0.0"
-"@rollup/plugin-buble@^1.0.2":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@rollup/plugin-buble/-/plugin-buble-1.0.3.tgz#6ce275f062a3bac583472cf14f54aa5f0957dccf"
- integrity sha512-QYD9BKkJoof0FdCFeSYYhF6/Y8e0Mnf+098xGgmWOFJ4UPHlWujjqOYeVwEm2hJPOmlR5k7HPUdAjqtOWhN64Q==
- dependencies:
- "@rollup/pluginutils" "^5.0.1"
- "@types/buble" "^0.19.2"
- buble "^0.20.0"
-
"@rollup/plugin-commonjs@^25.0.4":
version "25.0.7"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz#145cec7589ad952171aeb6a585bbeabd0fd3b4cf"
@@ -2343,13 +2334,6 @@
dependencies:
"@babel/types" "^7.20.7"
-"@types/buble@^0.19.2":
- version "0.19.2"
- resolved "https://registry.yarnpkg.com/@types/buble/-/buble-0.19.2.tgz#a4289d20b175b3c206aaad80caabdabe3ecdfdd1"
- integrity sha512-uUD8zIfXMKThmFkahTXDGI3CthFH1kMg2dOm3KLi4GlC5cbARA64bEcUMbbWdWdE73eoc/iBB9PiTMqH0dNS2Q==
- dependencies:
- magic-string "^0.25.0"
-
"@types/estree@*":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.3.tgz#2be19e759a3dd18c79f9f436bd7363556c1a73dd"
@@ -2729,12 +2713,7 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.4.tgz#06e83c5027f464eef861c329be81454bc8b70780"
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
-acorn-dynamic-import@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948"
- integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==
-
-acorn-jsx@^5.2.0, acorn-jsx@^5.3.2:
+acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
@@ -2744,11 +2723,6 @@ acorn-walk@^8.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.1.tgz#2f10f5b69329d90ae18c58bf1fa8fccd8b959a43"
integrity sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==
-acorn@^6.4.1:
- version "6.4.2"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
- integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
-
acorn@^8.10.0, acorn@^8.4.1, acorn@^8.9.0:
version "8.11.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b"
@@ -3135,19 +3109,6 @@ browserslist@^4.0.0, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^
node-releases "^2.0.13"
update-browserslist-db "^1.0.13"
-buble@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/buble/-/buble-0.20.0.tgz#a143979a8d968b7f76b57f38f2e7ce7cfe938d1f"
- integrity sha512-/1gnaMQE8xvd5qsNBl+iTuyjJ9XxeaVxAMF86dQ4EyxFJOZtsgOS8Ra+7WHgZTam5IFDtt4BguN0sH0tVTKrOw==
- dependencies:
- acorn "^6.4.1"
- acorn-dynamic-import "^4.0.0"
- acorn-jsx "^5.2.0"
- chalk "^2.4.2"
- magic-string "^0.25.7"
- minimist "^1.2.5"
- regexpu-core "4.5.4"
-
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
@@ -6092,13 +6053,6 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
-magic-string@^0.25.0, magic-string@^0.25.7:
- version "0.25.9"
- resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
- integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
- dependencies:
- sourcemap-codec "^1.4.8"
-
magic-string@^0.30.0, magic-string@^0.30.2, magic-string@^0.30.3:
version "0.30.5"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9"
@@ -6272,7 +6226,7 @@ minimist-options@4.1.0, minimist-options@^4.0.2:
is-plain-obj "^1.1.0"
kind-of "^6.0.3"
-minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6:
+minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -7828,14 +7782,7 @@ regenerate-unicode-properties@^10.1.0:
dependencies:
regenerate "^1.4.2"
-regenerate-unicode-properties@^8.0.2:
- version "8.2.0"
- resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
- integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==
- dependencies:
- regenerate "^1.4.0"
-
-regenerate@^1.4.0, regenerate@^1.4.2:
+regenerate@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
@@ -7866,18 +7813,6 @@ regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1:
define-properties "^1.2.0"
set-function-name "^2.0.0"
-regexpu-core@4.5.4:
- version "4.5.4"
- resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae"
- integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==
- dependencies:
- regenerate "^1.4.0"
- regenerate-unicode-properties "^8.0.2"
- regjsgen "^0.5.0"
- regjsparser "^0.6.0"
- unicode-match-property-ecmascript "^1.0.4"
- unicode-match-property-value-ecmascript "^1.1.0"
-
regexpu-core@^5.3.1:
version "5.3.2"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b"
@@ -7890,18 +7825,6 @@ regexpu-core@^5.3.1:
unicode-match-property-ecmascript "^2.0.0"
unicode-match-property-value-ecmascript "^2.1.0"
-regjsgen@^0.5.0:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733"
- integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==
-
-regjsparser@^0.6.0:
- version "0.6.9"
- resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.9.tgz#b489eef7c9a2ce43727627011429cf833a7183e6"
- integrity sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==
- dependencies:
- jsesc "~0.5.0"
-
regjsparser@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
@@ -8326,11 +8249,6 @@ source-map@^0.6.0, source-map@^0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-sourcemap-codec@^1.4.8:
- version "1.4.8"
- resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
- integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
-
spdx-correct@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
@@ -9022,24 +8940,11 @@ unenv@^1.7.4:
node-fetch-native "^1.4.1"
pathe "^1.1.1"
-unicode-canonical-property-names-ecmascript@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
- integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
-
unicode-canonical-property-names-ecmascript@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
-unicode-match-property-ecmascript@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
- integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
- dependencies:
- unicode-canonical-property-names-ecmascript "^1.0.4"
- unicode-property-aliases-ecmascript "^1.0.4"
-
unicode-match-property-ecmascript@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
@@ -9048,21 +8953,11 @@ unicode-match-property-ecmascript@^2.0.0:
unicode-canonical-property-names-ecmascript "^2.0.0"
unicode-property-aliases-ecmascript "^2.0.0"
-unicode-match-property-value-ecmascript@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531"
- integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==
-
unicode-match-property-value-ecmascript@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
-unicode-property-aliases-ecmascript@^1.0.4:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4"
- integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==
-
unicode-property-aliases-ecmascript@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"