Skip to content

Commit 6a2fddb

Browse files
adriaandotcomAdriaan
authored andcommitted
Add auto events script
1 parent a355d50 commit 6a2fddb

File tree

4 files changed

+212
-0
lines changed

4 files changed

+212
-0
lines changed

dist/latest/auto-events.js

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/latest/auto-events.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

minify.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,18 @@ const files = [
211211
url: "docs.simpleanalytics.com/embed-graph-on-your-site",
212212
},
213213
},
214+
{
215+
type: "js",
216+
input: `${__dirname}/src/auto-events.js`,
217+
output: `auto-events.js`,
218+
variables: {
219+
minify: true,
220+
version: 1,
221+
sri: false,
222+
script: "auto-events.js",
223+
url: "docs.simpleanalytics.com/automated-events",
224+
},
225+
},
214226
];
215227

216228
for (const file of files) {

src/auto-events.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
(function saAutomatedEvents(window) {
2+
// Skip server side rendered pages
3+
if (typeof window === "undefined") return;
4+
5+
var log = function (message, type) {
6+
var logger = type === "warn" ? console.warn : console.log;
7+
return logger("Simple Analytics auto events:", message);
8+
};
9+
10+
var doc = window.document;
11+
12+
var scriptElement =
13+
doc.currentScript || doc.querySelector('script[src*="auto-events.js"]');
14+
15+
var setting = function (attribute, type, defaultValue) {
16+
var value = scriptElement && scriptElement.dataset[attribute];
17+
18+
// Booleans
19+
if (type === "bool" && (value === "true" || value === "false"))
20+
return value === "true";
21+
else if (type === "bool") return defaultValue;
22+
23+
// Arrays
24+
if (type === "array" && value)
25+
return value
26+
.split(",")
27+
.map(function (item) {
28+
return item.trim();
29+
})
30+
.filter(Boolean);
31+
else if (type === "array") return defaultValue;
32+
};
33+
34+
var collectTypes = setting("collect", "array", [
35+
"outbound",
36+
"emails",
37+
"downloads",
38+
]);
39+
var fullUrls = setting("fullUrls", "bool", false);
40+
41+
var options = {
42+
// What to collect
43+
outbound: collectTypes.indexOf("outbound") > -1,
44+
emails: collectTypes.indexOf("emails") > -1,
45+
downloads: collectTypes.indexOf("downloads") > -1,
46+
// Downloads: enter file extensions you want to collect
47+
downloadsExtensions: setting("extensions", "array", [
48+
"pdf",
49+
"csv",
50+
"docx",
51+
"xlsx",
52+
"zip",
53+
"doc",
54+
"xls",
55+
]),
56+
57+
// All: use title attribute if set for event name (for all events)
58+
// THIS TAKES PRECEDENCE OVER OTHER SETTINGS BELOW
59+
title: setting("useTitle", "bool", true),
60+
// Outbound: use full URL of the links? false for just the hostname
61+
outboundFullUrl: fullUrls,
62+
// Downloads: if taking event name from URL, use full URL or just filename (default)
63+
downloadsFullUrl: fullUrls,
64+
};
65+
66+
// For minifying the script
67+
var optionsLink = options;
68+
69+
if (typeof optionsLink === "undefined")
70+
log("options object not found, please specify", "warn");
71+
72+
window.saAutomatedLink = function saAutomatedLink(element, type) {
73+
try {
74+
if (!element) return log("no element found");
75+
var sent = false;
76+
77+
var callback = function () {
78+
if (!sent && !element.hasAttribute("target"))
79+
document.location = element.getAttribute("href");
80+
sent = true;
81+
};
82+
83+
if (window.sa_event) {
84+
var hostname = element.hostname;
85+
var pathname = element.pathname;
86+
var useTitle = false;
87+
if (optionsLink.title && element.hasAttribute("title")) {
88+
var theTitle = element.getAttribute("title").trim();
89+
if (theTitle != "") useTitle = true;
90+
}
91+
92+
var event;
93+
94+
if (useTitle) {
95+
event = theTitle;
96+
} else {
97+
switch (type) {
98+
case "outbound": {
99+
event = hostname + (optionsLink.outboundFullUrl ? pathname : "");
100+
break;
101+
}
102+
case "download": {
103+
event = optionsLink.downloadsFullUrl
104+
? hostname + pathname
105+
: pathname.split("/").pop();
106+
break;
107+
}
108+
case "email": {
109+
var href = element.getAttribute("href");
110+
event = (href.split(":")[1] || "").split("?")[0];
111+
break;
112+
}
113+
}
114+
}
115+
116+
var clean =
117+
type +
118+
"_" +
119+
event.replace(/[^a-z0-9]+/gi, "_").replace(/(^_+|_+$)/g, "");
120+
121+
sa_event(clean, callback);
122+
123+
log("collected " + clean);
124+
125+
return window.setTimeout(callback, 5000);
126+
} else {
127+
log("sa_event is not defined", "warn");
128+
return callback();
129+
}
130+
} catch (error) {
131+
log(error.message, "warn");
132+
}
133+
};
134+
135+
function onDOMContentLoaded() {
136+
try {
137+
var a = document.getElementsByTagName("a");
138+
139+
// Loop over all links on the page
140+
for (var i = 0; i < a.length; i++) {
141+
var link = a[i];
142+
var collect = false;
143+
144+
// We don't want to overwrite website behaviour so we check for the onclick attribute
145+
if (!link.getAttribute("onclick")) {
146+
// Collect download clicks
147+
if (
148+
optionsLink.downloads &&
149+
/^https?:\/\//i.test(link.href) &&
150+
new RegExp(
151+
".(" + (optionsLink.downloadsExtensions || []).join("|") + ")",
152+
"i"
153+
).test(link.pathname)
154+
) {
155+
collect = "download";
156+
157+
// Collect outbound links clicks
158+
} else if (
159+
optionsLink.outbound &&
160+
/^https?:\/\//i.test(link.href) &&
161+
link.hostname !== window.location.hostname
162+
) {
163+
collect = "outbound";
164+
165+
// Collect email clicks
166+
} else if (optionsLink.emails && /^mailto:/i.test(link.href)) {
167+
collect = "email";
168+
}
169+
170+
if (collect) {
171+
var onClickAttribute = "saAutomatedLink(this, '" + collect + "');";
172+
173+
if (
174+
!link.hasAttribute("target") ||
175+
link.getAttribute("target") === "_self"
176+
)
177+
onClickAttribute += " return false;";
178+
179+
link.setAttribute("onclick", onClickAttribute);
180+
}
181+
}
182+
}
183+
} catch (error) {
184+
log(error.message, "warn");
185+
}
186+
}
187+
188+
if (doc.readyState === "ready" || doc.readyState === "complete") {
189+
onDOMContentLoaded();
190+
} else {
191+
document.addEventListener("readystatechange", function (event) {
192+
if (event.target.readyState === "complete") onDOMContentLoaded();
193+
});
194+
}
195+
})(window);

0 commit comments

Comments
 (0)