import platform from "platform"; import { CookieCategory } from "~/application/cookies/CookieCategory"; import CookieHelper from "./CookieHelper"; import { AppRootData } from "../data/useRootData"; import { apiPath } from "../app/CanonicalUrlUtils"; // EU-Sterilisation (R-P1a): Google-Analytics-gtag-Aufrufe entfernt. Es bleibt nur die First-Party- // Analytics-Ingestion gegen den eigenen API-Endpunkt (gated über ANALYTICS-Cookie-Consent). type AnalyticsProps = { url: string; rootData: Pick; route?: string; }; export async function addPageView({ url, rootData, route }: AnalyticsProps) { if (rootData.analytics && CookieHelper.hasConsent(rootData.userSession, CookieCategory.ANALYTICS)) { // console.log("[PAGE VIEW]", JSON.stringify({ url, analytics: rootData.analytics })); try { await fetch(new URL(apiPath("analytics/page-views", { mode: "host-aware" }), rootData.apiBaseUrl), { method: "POST", headers: { "Content-Type": "application/json", ...(rootData.analyticsToken ? { "x-analytics-token": rootData.analyticsToken } : {}) }, body: JSON.stringify({ url, route, analytics: { ...rootData.analytics, userAgent: getUserAgentDetails(), }, }), }); } catch (e: any) { // eslint-disable-next-line no-console console.error("[PAGE VIEW]", e.message); } } } type EventProps = AnalyticsProps & { url?: string; action: string; category: string; label: string; value: string; }; export async function addEvent({ url, route, action, category, label, value, rootData }: EventProps) { if (rootData.analytics && CookieHelper.hasConsent(rootData.userSession, CookieCategory.ANALYTICS)) { // console.log("[EVENT]", JSON.stringify({ action, category, label, value, url, analytics: rootData.analytics })); try { await fetch(new URL(apiPath("analytics/events", { mode: "host-aware" }), rootData.apiBaseUrl), { method: "POST", headers: { "Content-Type": "application/json", ...(rootData.analyticsToken ? { "x-analytics-token": rootData.analyticsToken } : {}) }, body: JSON.stringify({ action, category, label, value, url, route, analytics: { ...rootData.analytics, userAgent: getUserAgentDetails(), }, }), }); } catch (e: any) { // eslint-disable-next-line no-console console.error("[PAGE VIEW]", e.message); } } } function getUserAgentDetails(userAgent?: string) { const deviceType = () => { if (!userAgent) { return undefined; } const ua = userAgent; if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) { return "tablet"; } else if (/Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(ua)) { return "mobile"; } return "desktop"; }; return { type: deviceType(), os: { family: platform.os?.family, version: platform.os?.version, }, browser: { name: platform.name, version: platform.version, }, }; } // export async function createUniqueVisitorHash(domain: string, ipAddress: string, userAgent: string) { // const hash = sha256(domain + ipAddress + userAgent); // console.log({ hash }); // return hash; // } export default { addPageView, addEvent, getUserAgentDetails, };