Skip to content

Commit 3e9a7ee

Browse files
authored
Merge pull request umami-software#3381 from YektaDev/script-simplification
Script Simplification
2 parents 63a0460 + 9101f8a commit 3e9a7ee

File tree

1 file changed

+56
-130
lines changed

1 file changed

+56
-130
lines changed

src/tracker/index.js

Lines changed: 56 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88
top,
99
doNotTrack,
1010
} = window;
11-
const { hostname, href, origin } = location;
1211
const { currentScript, referrer } = document;
13-
const localStorage = href.startsWith('data:') ? undefined : window.localStorage;
14-
1512
if (!currentScript) return;
1613

14+
const { hostname, href, origin } = location;
15+
const localStorage = href.startsWith('data:') ? undefined : window.localStorage;
16+
1717
const _data = 'data-';
1818
const _false = 'false';
1919
const _true = 'true';
2020
const attr = currentScript.getAttribute.bind(currentScript);
2121
const website = attr(_data + 'website-id');
2222
const hostUrl = attr(_data + 'host-url');
23-
const tag = attr(_data + 'tag');
23+
const tag = attr(_data + 'tag') || undefined;
2424
const autoTrack = attr(_data + 'auto-track') !== _false;
2525
const dnt = attr(_data + 'do-not-track') === _true;
2626
const excludeSearch = attr(_data + 'exclude-search') === _true;
@@ -41,11 +41,11 @@
4141
website,
4242
screen,
4343
language,
44-
title,
44+
title: document.title,
4545
hostname,
4646
url: currentUrl,
4747
referrer: currentRef,
48-
tag: tag ? tag : undefined,
48+
tag,
4949
id: identity ? identity : undefined,
5050
});
5151

@@ -56,20 +56,14 @@
5656

5757
/* Event handlers */
5858

59-
const handlePush = (state, title, url) => {
59+
const handlePush = (_state, _title, url) => {
6060
if (!url) return;
6161

6262
currentRef = currentUrl;
6363
currentUrl = new URL(url, location.href);
6464

65-
if (excludeSearch) {
66-
currentUrl.search = '';
67-
}
68-
69-
if (excludeHash) {
70-
currentUrl.hash = '';
71-
}
72-
65+
if (excludeSearch) currentUrl.search = '';
66+
if (excludeHash) currentUrl.hash = '';
7367
currentUrl = currentUrl.toString();
7468

7569
if (currentUrl !== currentRef) {
@@ -80,10 +74,8 @@
8074
const handlePathChanges = () => {
8175
const hook = (_this, method, callback) => {
8276
const orig = _this[method];
83-
8477
return (...args) => {
8578
callback.apply(null, args);
86-
8779
return orig.apply(_this, args);
8880
};
8981
};
@@ -92,96 +84,47 @@
9284
history.replaceState = hook(history, 'replaceState', handlePush);
9385
};
9486

95-
const handleTitleChanges = () => {
96-
const observer = new MutationObserver(([entry]) => {
97-
title = entry && entry.target ? entry.target.text : undefined;
98-
});
99-
100-
const node = document.querySelector('head > title');
101-
102-
if (node) {
103-
observer.observe(node, {
104-
subtree: true,
105-
characterData: true,
106-
childList: true,
107-
});
108-
}
109-
};
110-
11187
const handleClicks = () => {
112-
document.addEventListener(
113-
'click',
114-
async e => {
115-
const isSpecialTag = tagName => ['BUTTON', 'A'].includes(tagName);
116-
117-
const trackElement = async el => {
118-
const attr = el.getAttribute.bind(el);
119-
const eventName = attr(eventNameAttribute);
120-
121-
if (eventName) {
122-
const eventData = {};
123-
124-
el.getAttributeNames().forEach(name => {
125-
const match = name.match(eventRegex);
126-
127-
if (match) {
128-
eventData[match[1]] = attr(name);
129-
}
130-
});
131-
132-
return track(eventName, eventData);
133-
}
134-
};
135-
136-
const findParentTag = (rootElem, maxSearchDepth) => {
137-
let currentElement = rootElem;
138-
for (let i = 0; i < maxSearchDepth; i++) {
139-
if (isSpecialTag(currentElement.tagName)) {
140-
return currentElement;
141-
}
142-
currentElement = currentElement.parentElement;
143-
if (!currentElement) {
144-
return null;
145-
}
146-
}
147-
};
88+
const trackElement = async el => {
89+
const eventName = el.getAttribute(eventNameAttribute);
90+
if (eventName) {
91+
const eventData = {};
14892

149-
const el = e.target;
150-
const parentElement = isSpecialTag(el.tagName) ? el : findParentTag(el, 10);
93+
el.getAttributeNames().forEach(name => {
94+
const match = name.match(eventRegex);
95+
if (match) eventData[match[1]] = el.getAttribute(name);
96+
});
15197

152-
if (parentElement) {
153-
const { href, target } = parentElement;
154-
const eventName = parentElement.getAttribute(eventNameAttribute);
98+
return track(eventName, eventData);
99+
}
100+
};
101+
const onClick = async e => {
102+
const el = e.target;
103+
const parentElement = el.closest('a,button');
104+
if (!parentElement) return trackElement(el);
155105

156-
if (eventName) {
157-
if (parentElement.tagName === 'A') {
158-
const external =
159-
target === '_blank' ||
160-
e.ctrlKey ||
161-
e.shiftKey ||
162-
e.metaKey ||
163-
(e.button && e.button === 1);
106+
const { href, target } = parentElement;
107+
if (!parentElement.getAttribute(eventNameAttribute)) return;
164108

165-
if (eventName && href) {
166-
if (!external) {
167-
e.preventDefault();
168-
}
169-
return trackElement(parentElement).then(() => {
170-
if (!external) {
171-
(target === '_top' ? top.location : location).href = href;
172-
}
173-
});
174-
}
175-
} else if (parentElement.tagName === 'BUTTON') {
176-
return trackElement(parentElement);
177-
}
109+
if (parentElement.tagName === 'BUTTON') {
110+
return trackElement(parentElement);
111+
}
112+
if (parentElement.tagName === 'A' && href) {
113+
const external =
114+
target === '_blank' ||
115+
e.ctrlKey ||
116+
e.shiftKey ||
117+
e.metaKey ||
118+
(e.button && e.button === 1);
119+
if (!external) e.preventDefault();
120+
return trackElement(parentElement).then(() => {
121+
if (!external) {
122+
(target === '_top' ? top.location : location).href = href;
178123
}
179-
} else {
180-
return trackElement(el);
181-
}
182-
},
183-
true,
184-
);
124+
});
125+
}
126+
};
127+
document.addEventListener('click', onClick, true);
185128
};
186129

187130
/* Tracking functions */
@@ -195,56 +138,40 @@
195138

196139
const send = async (payload, type = 'event') => {
197140
if (trackingDisabled()) return;
198-
199-
const headers = {
200-
'Content-Type': 'application/json',
201-
};
202-
203-
if (typeof cache !== 'undefined') {
204-
headers['x-umami-cache'] = cache;
205-
}
206-
207141
try {
208142
const res = await fetch(endpoint, {
209143
method: 'POST',
210144
body: JSON.stringify({ type, payload }),
211-
headers,
145+
headers: {
146+
'Content-Type': 'application/json',
147+
...(typeof cache !== 'undefined' && { 'x-umami-cache': cache }),
148+
},
212149
credentials: 'omit',
213150
});
214151

215152
const data = await res.json();
216-
217153
if (data) {
218154
disabled = !!data.disabled;
219155
cache = data.cache;
220156
}
221157
} catch (e) {
222-
/* empty */
158+
/* no-op */
223159
}
224160
};
225161

226162
const init = () => {
227163
if (!initialized) {
164+
initialized = true;
228165
track();
229166
handlePathChanges();
230-
handleTitleChanges();
231167
handleClicks();
232-
initialized = true;
233168
}
234169
};
235170

236-
const track = (name, data) => {
237-
if (typeof name === 'string') {
238-
return send({
239-
...getPayload(),
240-
name,
241-
data,
242-
});
243-
} else if (typeof name === 'object') {
244-
return send({ ...name });
245-
} else if (typeof name === 'function') {
246-
return send(name(getPayload()));
247-
}
171+
const track = (obj, data) => {
172+
if (typeof obj === 'string') return send({ ...getPayload(), name: obj, data });
173+
if (typeof obj === 'object') return send(obj);
174+
if (typeof obj === 'function') return send(obj(getPayload()));
248175
return send(getPayload());
249176
};
250177

@@ -274,10 +201,9 @@
274201

275202
let currentUrl = href;
276203
let currentRef = referrer.startsWith(origin) ? '' : referrer;
277-
let title = document.title;
278-
let cache;
279-
let initialized;
204+
let initialized = false;
280205
let disabled = false;
206+
let cache;
281207
let identity;
282208

283209
if (autoTrack && !trackingDisabled()) {

0 commit comments

Comments
 (0)