feat: integrate umami script locally
This commit is contained in:
parent
9a1b1adc72
commit
fd36310bb3
148
web/public/umami_script.js
Normal file
148
web/public/umami_script.js
Normal file
@ -0,0 +1,148 @@
|
||||
! function() {
|
||||
"use strict";
|
||||
! function(t) {
|
||||
var e = t.screen,
|
||||
n = e.width,
|
||||
r = e.height,
|
||||
a = t.navigator.language,
|
||||
i = t.location,
|
||||
o = t.localStorage,
|
||||
u = t.document,
|
||||
c = t.history,
|
||||
f = "jan.ai",
|
||||
s = "main page",
|
||||
l = i.search,
|
||||
d = u.currentScript;
|
||||
if (d) {
|
||||
var m = "data-",
|
||||
h = d.getAttribute.bind(d),
|
||||
v = h(m + "website-id"),
|
||||
p = h(m + "host-url"),
|
||||
g = "false" !== h(m + "auto-track"),
|
||||
y = h(m + "do-not-track"),
|
||||
b = h(m + "domains") || "",
|
||||
S = b.split(",").map((function(t) {
|
||||
return t.trim()
|
||||
})),
|
||||
k = (p ? p.replace(/\/$/, "") : d.src.split("/").slice(0, -1).join("/")) + "/api/send",
|
||||
w = n + "x" + r,
|
||||
N = /data-umami-event-([\w-_]+)/,
|
||||
T = m + "umami-event",
|
||||
j = 300,
|
||||
A = function(t, e, n) {
|
||||
var r = t[e];
|
||||
return function() {
|
||||
for (var e = [], a = arguments.length; a--;) e[a] = arguments[a];
|
||||
return n.apply(null, e), r.apply(t, e)
|
||||
}
|
||||
},
|
||||
x = function() {
|
||||
return {
|
||||
website: v,
|
||||
hostname: f,
|
||||
screen: w,
|
||||
language: a,
|
||||
title: M,
|
||||
url: I,
|
||||
referrer: J
|
||||
}
|
||||
},
|
||||
E = function() {
|
||||
return o && o.getItem("umami.disabled") || y && function() {
|
||||
var e = t.doNotTrack,
|
||||
n = t.navigator,
|
||||
r = t.external,
|
||||
a = "msTrackingProtectionEnabled",
|
||||
i = e || n.doNotTrack || n.msDoNotTrack || r && a in r && r[a]();
|
||||
return "1" == i || "yes" === i
|
||||
}() || b && !S.includes(f)
|
||||
},
|
||||
O = function(t, e, n) {
|
||||
n && (J = I, (I = function(t) {
|
||||
try {
|
||||
return new URL(t).pathname
|
||||
} catch (e) {
|
||||
return t
|
||||
}
|
||||
}(n.toString())) !== J && setTimeout(D, j))
|
||||
},
|
||||
L = function(t, e) {
|
||||
if (void 0 === e && (e = "event"), !E()) {
|
||||
var n = {
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
return void 0 !== K && (n["x-umami-cache"] = K), fetch(k, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
type: e,
|
||||
payload: t
|
||||
}),
|
||||
headers: n
|
||||
}).then((function(t) {
|
||||
return t.text()
|
||||
})).then((function(t) {
|
||||
return K = t
|
||||
})).catch((function() {}))
|
||||
}
|
||||
},
|
||||
D = function(t, e) {
|
||||
return L("string" == typeof t ? Object.assign({}, x(), {
|
||||
name: t,
|
||||
data: "object" == typeof e ? e : void 0
|
||||
}) : "object" == typeof t ? t : "function" == typeof t ? t(x()) : x())
|
||||
};
|
||||
t.umami || (t.umami = {
|
||||
track: D,
|
||||
identify: function(t) {
|
||||
return L(Object.assign({}, x(), {
|
||||
data: t
|
||||
}), "identify")
|
||||
}
|
||||
});
|
||||
var K, P, _, q, C, I = "" + s + l,
|
||||
J = u.referrer,
|
||||
M = u.title;
|
||||
if (g && !E()) {
|
||||
c.pushState = A(c, "pushState", O), c.replaceState = A(c, "replaceState", O), C = function(t) {
|
||||
var e = t.getAttribute.bind(t),
|
||||
n = e(T);
|
||||
if (n) {
|
||||
var r = {};
|
||||
return t.getAttributeNames().forEach((function(t) {
|
||||
var n = t.match(N);
|
||||
n && (r[n[1]] = e(t))
|
||||
})), D(n, r)
|
||||
}
|
||||
return Promise.resolve()
|
||||
}, u.addEventListener("click", (function(t) {
|
||||
var e = t.target,
|
||||
n = "A" === e.tagName ? e : function(t, e) {
|
||||
for (var n = t, r = 0; r < e; r++) {
|
||||
if ("A" === n.tagName) return n;
|
||||
if (!(n = n.parentElement)) return null
|
||||
}
|
||||
return null
|
||||
}(e, 10);
|
||||
if (n) {
|
||||
var r = n.href,
|
||||
a = "_blank" === n.target || t.ctrlKey || t.shiftKey || t.metaKey || t.button && 1 === t.button;
|
||||
if (n.getAttribute(T) && r) return a || t.preventDefault(), C(n).then((function() {
|
||||
a || (i.href = r)
|
||||
}))
|
||||
} else C(e)
|
||||
}), !0), _ = new MutationObserver((function(t) {
|
||||
var e = t[0];
|
||||
M = e && e.target ? e.target.text : void 0
|
||||
})), (q = u.querySelector("head > title")) && _.observe(q, {
|
||||
subtree: !0,
|
||||
characterData: !0,
|
||||
childList: !0
|
||||
});
|
||||
var R = function() {
|
||||
"complete" !== u.readyState || P || (D(), P = !0)
|
||||
};
|
||||
u.addEventListener("readystatechange", R, !0), R()
|
||||
}
|
||||
}
|
||||
}(window)
|
||||
}();
|
||||
@ -1,31 +1,67 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
const Umami = () => {
|
||||
useEffect(() => {
|
||||
if (!VERSION || !ANALYTICS_HOST || !ANALYTICS_ID) return
|
||||
fetch(ANALYTICS_HOST, {
|
||||
method: 'POST',
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
payload: {
|
||||
website: ANALYTICS_ID,
|
||||
hostname: 'jan.ai',
|
||||
screen: `${screen.width}x${screen.height}`,
|
||||
language: navigator.language,
|
||||
referrer: 'index.html',
|
||||
data: { version: VERSION },
|
||||
type: 'event',
|
||||
title: document.title,
|
||||
url: 'index.html',
|
||||
name: VERSION,
|
||||
},
|
||||
type: 'event',
|
||||
}),
|
||||
})
|
||||
}, [])
|
||||
import Script from 'next/script'
|
||||
|
||||
return <></>
|
||||
// Define the type for the umami data object
|
||||
interface UmamiData {
|
||||
version: string
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
umami:
|
||||
| {
|
||||
track: (event: string, data?: UmamiData) => void
|
||||
}
|
||||
| undefined
|
||||
}
|
||||
}
|
||||
|
||||
const Umami = () => {
|
||||
const appVersion = VERSION
|
||||
const analyticsScriptPath = './umami_script.js'
|
||||
const analyticsId = ANALYTICS_ID
|
||||
|
||||
useEffect(() => {
|
||||
if (!appVersion || !analyticsScriptPath || !analyticsId) return
|
||||
|
||||
const ping = () => {
|
||||
// Check if umami is defined before ping
|
||||
if (window.umami !== null && typeof window.umami !== 'undefined') {
|
||||
window.umami.track(appVersion, {
|
||||
version: appVersion,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for umami to be defined before ping
|
||||
if (window.umami !== null && typeof window.umami !== 'undefined') {
|
||||
ping()
|
||||
} else {
|
||||
// Listen for umami script load event
|
||||
document.addEventListener('umami:loaded', ping)
|
||||
}
|
||||
|
||||
// Cleanup function to remove event listener if the component unmounts
|
||||
return () => {
|
||||
document.removeEventListener('umami:loaded', ping)
|
||||
}
|
||||
}, [appVersion, analyticsScriptPath, analyticsId])
|
||||
|
||||
return (
|
||||
<>
|
||||
{appVersion && analyticsScriptPath && analyticsId && (
|
||||
<Script
|
||||
src={analyticsScriptPath}
|
||||
data-website-id={analyticsId}
|
||||
data-cache="true"
|
||||
data-host-url="https://eu.umami.is"
|
||||
defer
|
||||
onLoad={() => document.dispatchEvent(new Event('umami:loaded'))}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Umami
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user