From 49a6d9eaac50cf1eaea48e8f81081d653eee14a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:54:16 +0200 Subject: [PATCH] Add Matomo integration --- astro.config.mjs | 10 ++ src/components/TwinklingStars.astro | 118 ++++++++++++++--------- src/integrations/matomo/index.ts | 71 ++++++++++++++ src/integrations/matomo/matomo.ts | 61 ++++++++++++ src/integrations/matomo/types/index.d.ts | 8 ++ 5 files changed, 224 insertions(+), 44 deletions(-) create mode 100644 src/integrations/matomo/index.ts create mode 100644 src/integrations/matomo/matomo.ts create mode 100644 src/integrations/matomo/types/index.d.ts diff --git a/astro.config.mjs b/astro.config.mjs index b40751b..dc90792 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,6 +3,7 @@ import mdx from "@astrojs/mdx"; import sitemap from "@astrojs/sitemap"; import tailwind from "@astrojs/tailwind"; import solidJs from "@astrojs/solid-js"; +import matomo from "./src/integrations/matomo"; // https://astro.build/config export default defineConfig({ @@ -13,5 +14,14 @@ export default defineConfig({ sitemap(), solidJs(), tailwind({ applyBaseStyles: false }), + matomo({ + enabled: import.meta.env.PROD, // only enable in production + url: "https://analytics.hoelting.dev", + siteId: 3, + disableCookies: true, + enableCrossDomainLinking: true, + domains: ["*.hoelting.dev", "*.www.hoelting.dev"], + respectDoNotTrack: true, + }), ], }); diff --git a/src/components/TwinklingStars.astro b/src/components/TwinklingStars.astro index 3650379..d8ada99 100644 --- a/src/components/TwinklingStars.astro +++ b/src/components/TwinklingStars.astro @@ -7,54 +7,84 @@ */ --- - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/src/integrations/matomo/index.ts b/src/integrations/matomo/index.ts new file mode 100644 index 0000000..4cd185d --- /dev/null +++ b/src/integrations/matomo/index.ts @@ -0,0 +1,71 @@ +import type { AstroIntegration } from "astro"; + +export type MatomoOptions = { + enabled: boolean; + url: string; + siteId: number; + trackerUrl?: string; + srcUrl?: string; + heartBeatTimer?: number; + setCookieDomain?: string; + disableCookies?: boolean; + preconnect?: boolean; + debug?: boolean; + respectDoNotTrack?: boolean; + domains?: string[]; + enableCrossDomainLinking?: boolean; + customCampaignParameters?: { + name?: string; + keyword?: string; + }; +}; + +export default function matomoIntegration( + options: MatomoOptions +): AstroIntegration { + if (!options?.url.endsWith("/")) { + options.url += "/"; + } + + let script: string; + + if (options?.enabled) { + script = `import { initMatomo, preconnectMatomo } from "@integrations/matomo/matomo"; initMatomo(${JSON.stringify( + options + )});`; + + if (options?.preconnect) { + script += `preconnectMatomo(${JSON.stringify(options)});`; + } + } else { + console.info( + "\x1b[43m", + "Matomo", + "\x1b[0m", + "\x1b[34m", + "Is disabled.", + "\x1b[0m" + ); + + script = ""; + } + + return { + name: "matomo", + hooks: { + "astro:config:setup": async ({ injectScript }) => { + if (options?.enabled) { + injectScript("page", script); + console.info( + "\x1b[42m", + "Matomo", + "\x1b[0m", + "\x1b[34m", + "was integrated successfully.", + "\x1b[0m" + ); + } + }, + }, + }; +} diff --git a/src/integrations/matomo/matomo.ts b/src/integrations/matomo/matomo.ts new file mode 100644 index 0000000..0ef98ea --- /dev/null +++ b/src/integrations/matomo/matomo.ts @@ -0,0 +1,61 @@ +import type { MatomoOptions } from "."; + +export function initMatomo(options: MatomoOptions): void { + const _paq = (window._paq = window._paq || []); + + if (options?.disableCookies) _paq.push(["disableCookies"]); + if (options?.heartBeatTimer) + _paq.push(["enableHeartBeatTimer", options.heartBeatTimer]); + if (options?.setCookieDomain) + _paq.push(["setCookieDomain", options.setCookieDomain]); + if (options?.respectDoNotTrack) _paq.push(["setDoNotTrack", true]); + if (options?.domains) _paq.push(["setDomains", options.domains]); + if (options?.enableCrossDomainLinking) + _paq.push(["enableCrossDomainLinking"]); + if (options?.customCampaignParameters?.name) + _paq.push([ + "setCampaignNameKey", + options.customCampaignParameters.name, + ]); + if (options?.customCampaignParameters?.keyword) + _paq.push([ + "setCampaignKeywordKey", + options.customCampaignParameters.keyword, + ]); + + _paq.push(["trackPageView"]); + _paq.push(["enableLinkTracking"]); + + if (options?.debug) { + console.warn("Matomo debug mode enabled!"); + window._mtm = window._mtm || []; + window._mtm.push(["enableDebugMode"]); + } + + (function () { + const u = options?.url; + + _paq.push(["setTrackerUrl", u + (options?.trackerUrl || "matomo.php")]); + _paq.push(["setSiteId", options?.siteId]); + + const d = document, + g = d.createElement("script"), + s = d.getElementsByTagName("script")[0]; + + g.id = "matomo-script"; + g.type = "text/javascript"; + g.async = true; + g.defer = true; + g.src = u + (options?.srcUrl || "matomo.js"); + if (s.parentNode != null && u) s.parentNode.insertBefore(g, s); + })(); +} + +export function preconnectMatomo(options: MatomoOptions): void { + if (!options?.url) return; + + const link = document.createElement("link"); + link.rel = "preconnect"; + link.href = options?.url; + document.head.appendChild(link); +} diff --git a/src/integrations/matomo/types/index.d.ts b/src/integrations/matomo/types/index.d.ts new file mode 100644 index 0000000..557c54c --- /dev/null +++ b/src/integrations/matomo/types/index.d.ts @@ -0,0 +1,8 @@ +export {}; + +declare global { + interface Window { + _paq: Array; + _mtm: Array; + } +}