Files
shop/plugins/umami.client.ts
T
libretech bf3b8ea3da
build / build (pull_request) Successful in 1m10s
Analytics: queued events, once-per-order revenue, heatmap on product pages
trackEvent queues events until the deferred Umami script exists (they
were dropped when fired in onMounted) and drops them silently after 10 s.
The result page sends purchase-completed with revenue/currency once per
order (localStorage guard, set only after sending). The plugin honours
Do Not Track and loads recorder.js only on /details/* for Umami heatmaps.
bun test utils/trackEvent.test.ts: 4 pass. Netcup #115.
2026-10-15 04:16:42 +02:00

36 lines
1.1 KiB
TypeScript

export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const scriptUrl = config.public.umamiScriptUrl as string;
const websiteId = config.public.umamiWebsiteId as string;
if (!scriptUrl || !websiteId) return;
useHead({
script: [
{
src: scriptUrl,
defer: true,
"data-website-id": websiteId,
"data-do-not-track": "true"
}
]
});
// Heatmap recorder only on product pages (no personal data there). It needs
// heatmapEnabled on the Umami website, set via umami/analytics/reports.json.
const recorderUrl = scriptUrl.replace(/script\.js(\?.*)?$/, "recorder.js");
let recorderLoaded = false;
const loadRecorder = (path: string) => {
if (recorderLoaded || !path.startsWith("/details/")) return;
if (navigator.doNotTrack === "1") return;
recorderLoaded = true;
const el = document.createElement("script");
el.src = recorderUrl;
el.defer = true;
el.dataset.websiteId = websiteId;
document.head.appendChild(el);
};
const router = useRouter();
loadRecorder(router.currentRoute.value.path);
router.afterEach((to) => loadRecorder(to.path));
});