mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-03-10 04:44:04 +00:00
195 lines
4.4 KiB
JavaScript
195 lines
4.4 KiB
JavaScript
// js/analytics.js
|
|
import { ANALYTICS_CONFIG } from "./analyticsConfig.js";
|
|
|
|
const SCRIPT_ATTR = "data-bitvid-analytics";
|
|
const SCRIPT_IDENTIFIER = "umami";
|
|
const pendingCalls = [];
|
|
let flushTimerId = null;
|
|
let scriptLoadedOnce = false;
|
|
|
|
function isBrowserEnvironment() {
|
|
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
}
|
|
|
|
function flushPendingCalls() {
|
|
if (!isBrowserEnvironment()) {
|
|
return;
|
|
}
|
|
|
|
const umami = window.umami;
|
|
if (!umami) {
|
|
return;
|
|
}
|
|
|
|
while (pendingCalls.length > 0) {
|
|
const { method, args } = pendingCalls.shift();
|
|
const fn = typeof umami[method] === "function" ? umami[method] : null;
|
|
if (!fn) {
|
|
continue;
|
|
}
|
|
try {
|
|
fn.apply(umami, args);
|
|
} catch (err) {
|
|
console.warn("[analytics] Failed to call", method, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
function scheduleFlush() {
|
|
if (!isBrowserEnvironment()) {
|
|
return;
|
|
}
|
|
|
|
if (flushTimerId !== null) {
|
|
return;
|
|
}
|
|
|
|
// 🔧 merged conflicting changes from codex/add-tracking-script-to-all-pages vs unstable
|
|
flushTimerId = window.setInterval(() => {
|
|
if (window.umami && typeof window.umami.track === "function") {
|
|
window.clearInterval(flushTimerId);
|
|
flushTimerId = null;
|
|
flushPendingCalls();
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
export function ensureAnalyticsLoaded(doc = typeof document !== "undefined" ? document : null) {
|
|
if (!doc) {
|
|
return null;
|
|
}
|
|
|
|
let script = doc.querySelector(`script[${SCRIPT_ATTR}]`);
|
|
if (script) {
|
|
if (!scriptLoadedOnce) {
|
|
// If a server rendered script already exists, make sure we flush asap.
|
|
scriptLoadedOnce = true;
|
|
flushPendingCalls();
|
|
}
|
|
return script;
|
|
}
|
|
|
|
script = doc.createElement("script");
|
|
script.defer = true;
|
|
script.src = ANALYTICS_CONFIG.scriptSrc;
|
|
script.setAttribute(SCRIPT_ATTR, SCRIPT_IDENTIFIER);
|
|
script.dataset.websiteId = ANALYTICS_CONFIG.websiteId;
|
|
// Allow Umami to handle automatic pageview tracking by default.
|
|
script.addEventListener("load", () => {
|
|
scriptLoadedOnce = true;
|
|
flushPendingCalls();
|
|
});
|
|
doc.head.appendChild(script);
|
|
|
|
scheduleFlush();
|
|
|
|
return script;
|
|
}
|
|
|
|
function queueCall(method, args) {
|
|
pendingCalls.push({ method, args });
|
|
scheduleFlush();
|
|
}
|
|
|
|
function invokeUmami(method, args) {
|
|
if (!isBrowserEnvironment()) {
|
|
return;
|
|
}
|
|
|
|
ensureAnalyticsLoaded();
|
|
|
|
const umami = window.umami;
|
|
if (umami && typeof umami[method] === "function") {
|
|
try {
|
|
umami[method].apply(umami, args);
|
|
} catch (err) {
|
|
console.warn("[analytics] Failed to call", method, err);
|
|
}
|
|
return;
|
|
}
|
|
|
|
queueCall(method, args);
|
|
}
|
|
|
|
export function trackPageView(path, referrer) {
|
|
if (!isBrowserEnvironment()) {
|
|
return;
|
|
}
|
|
|
|
const resolvedPath =
|
|
typeof path === "string" && path.length > 0
|
|
? path
|
|
: `${window.location.pathname}${window.location.hash || ""}`;
|
|
|
|
const resolvedReferrer =
|
|
typeof referrer === "string" ? referrer : document.referrer || "";
|
|
|
|
// 🔧 merged conflicting changes from codex/add-tracking-script-to-all-pages vs unstable
|
|
let absoluteUrl = resolvedPath;
|
|
try {
|
|
absoluteUrl = new URL(resolvedPath, window.location.origin).toString();
|
|
} catch (err) {
|
|
// Fall back to the provided path if it cannot be resolved.
|
|
}
|
|
|
|
let absoluteReferrer = resolvedReferrer;
|
|
if (resolvedReferrer) {
|
|
try {
|
|
absoluteReferrer = new URL(resolvedReferrer, window.location.origin).toString();
|
|
} catch (err) {
|
|
// Keep original referrer if it cannot be normalized.
|
|
}
|
|
}
|
|
|
|
invokeUmami("track", [
|
|
(basePayload = {}) => ({
|
|
...basePayload,
|
|
url: absoluteUrl || basePayload.url,
|
|
referrer: absoluteReferrer || basePayload.referrer,
|
|
}),
|
|
"pageview",
|
|
]);
|
|
}
|
|
|
|
export function trackVideoView({
|
|
videoId,
|
|
title,
|
|
source,
|
|
hasMagnet,
|
|
hasUrl,
|
|
} = {}) {
|
|
if (!isBrowserEnvironment()) {
|
|
return;
|
|
}
|
|
|
|
const payload = {};
|
|
|
|
if (videoId) {
|
|
payload.videoId = String(videoId);
|
|
}
|
|
|
|
if (title) {
|
|
payload.title = String(title);
|
|
}
|
|
|
|
if (source) {
|
|
payload.source = String(source);
|
|
}
|
|
|
|
if (typeof hasMagnet === "boolean") {
|
|
payload.hasMagnet = hasMagnet;
|
|
}
|
|
|
|
if (typeof hasUrl === "boolean") {
|
|
payload.hasUrl = hasUrl;
|
|
}
|
|
|
|
// 🔧 merged conflicting changes from codex/add-tracking-script-to-all-pages vs unstable
|
|
invokeUmami("track", [ANALYTICS_CONFIG.videoViewEventName, payload]);
|
|
}
|
|
|
|
// Immediately queue the analytics script so page views are captured early.
|
|
if (isBrowserEnvironment()) {
|
|
ensureAnalyticsLoaded();
|
|
}
|