MBO-Tech-IT-Webseite/components/analytics/PageTracker.tsx

80 lines
2.5 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { usePathname } from "next/navigation";
const EXCLUDED_PREFIXES = ["/admin", "/api", "/_next"];
export function PageTracker() {
const pathname = usePathname();
const viewIdRef = useRef<string | null>(null);
const startTimeRef = useRef<number>(Date.now());
function getSessionId(): string {
let sid = sessionStorage.getItem("_mpv_sid");
if (!sid) {
sid = crypto.randomUUID();
sessionStorage.setItem("_mpv_sid", sid);
}
return sid;
}
useEffect(() => {
if (EXCLUDED_PREFIXES.some((p) => pathname.startsWith(p))) return;
startTimeRef.current = Date.now();
viewIdRef.current = null;
fetch("/api/analytics/track", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
path: pathname,
session_id: getSessionId(),
referrer: typeof document !== "undefined" ? document.referrer || undefined : undefined,
}),
})
.then((r) => r.json())
.then((d) => { viewIdRef.current = d.view_id ?? null; })
.catch(() => {});
function sendDuration() {
if (!viewIdRef.current) return;
const ms = Date.now() - startTimeRef.current;
const blob = new Blob(
[JSON.stringify({ path: pathname, session_id: getSessionId(), view_id: viewIdRef.current, duration_ms: ms })],
{ type: "application/json" }
);
navigator.sendBeacon("/api/analytics/track", blob);
}
function trackPhoneClick(event: Event) {
const target = event.target as HTMLElement;
const link = target.closest('a[href^="tel:"]');
if (!link) return;
const phoneNumber = link.getAttribute("href")?.replace("tel:", "").trim();
if (!phoneNumber) return;
const sourceElement =
link.getAttribute("data-source-element") ||
link.closest("[data-source-element]")?.getAttribute("data-source-element") ||
"unknown";
fetch("/api/analytics/track-phone-click", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phone_number: phoneNumber, source_page: pathname, source_element: sourceElement, session_id: getSessionId() }),
}).catch(() => {});
}
window.addEventListener("pagehide", sendDuration);
document.addEventListener("click", trackPhoneClick);
return () => {
document.removeEventListener("click", trackPhoneClick);
window.removeEventListener("pagehide", sendDuration);
sendDuration();
};
}, [pathname]);
return null;
}