diff --git a/.env.example b/.env.example index 89d630e..65080b4 100644 --- a/.env.example +++ b/.env.example @@ -5,22 +5,22 @@ WEB_PORT=3000 API_PORT=4000 # DB -POSTGRES_DB= -POSTGRES_USER= +POSTGRES_DB=flint +POSTGRES_USER=flint POSTGRES_PASSWORD= # REDIS REDIS_PASSWORD= # URLS PROD -WEB_URL=https://yourdomain.com +WEB_URL=http://localhost:3000 API_BASE_URL=http://api:4000 -NEXT_PUBLIC_API_BASE_URL=https://api.yourdomain.com +NEXT_PUBLIC_API_BASE_URL=http://localhost:4000 # DISCORD DISCORD_CLIENT_ID= DISCORD_CLIENT_SECRET= -DISCORD_REDIRECT_URI=https://api.yourdomain.com/auth/discord/callback +DISCORD_REDIRECT_URI=http://localhost:4000/auth/discord/callback # Session/auth JWT_SECRET= @@ -34,3 +34,8 @@ TOKEN_ENCRYPTION_KEY= # Multi-tenant API limits TENANT_RATE_LIMIT_MAX=120 TENANT_RATE_LIMIT_WINDOW_SECONDS=60 + +# Matomo Analytics (optional - leave empty to disable) +# NEXT_PUBLIC_MATOMO_URL= +# NEXT_PUBLIC_MATOMO_SITE_ID= + diff --git a/apps/web/app/[locale]/layout.tsx b/apps/web/app/[locale]/layout.tsx index da9c5b7..420c068 100644 --- a/apps/web/app/[locale]/layout.tsx +++ b/apps/web/app/[locale]/layout.tsx @@ -4,6 +4,7 @@ import { hasLocale, NextIntlClientProvider } from "next-intl"; import { getMessages, getTranslations } from "next-intl/server"; import { notFound } from "next/navigation"; +import { MatomoScript } from "../../components/MatomoScript"; import { RTL_LOCALES, routing } from "../../i18n/routing"; import "../globals.css"; @@ -130,6 +131,7 @@ export default async function LocaleLayout({ + {children} diff --git a/apps/web/components/MatomoScript.tsx b/apps/web/components/MatomoScript.tsx new file mode 100644 index 0000000..0975016 --- /dev/null +++ b/apps/web/components/MatomoScript.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { useEffect } from 'react'; + +/** + * Matomo Analytics Script Component + * Injects the Matomo tracking script only if MATOMO_URL and MATOMO_SITE_ID are configured + * + * Environment variables: + * - NEXT_PUBLIC_MATOMO_URL: Base URL of Matomo instance (e.g., https://analytics.arthurp.fr/) + * - NEXT_PUBLIC_MATOMO_SITE_ID: Site ID in Matomo (e.g., 9) + */ +export function MatomoScript() { + useEffect(() => { + // Check if Matomo is properly configured + const matomoUrl = process.env.NEXT_PUBLIC_MATOMO_URL?.trim(); + const matomoSiteId = process.env.NEXT_PUBLIC_MATOMO_SITE_ID?.trim(); + + // Skip if not configured + if (!matomoUrl || !matomoSiteId) { + if (process.env.NODE_ENV === 'development') { + console.debug('[Matomo] Not configured. Skipping analytics.'); + } + return; + } + + // Initialize Matomo tracking array + (window as any)._paq = (window as any)._paq || []; + const _paq = (window as any)._paq; + + // Set up tracking + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + _paq.push(['setTrackerUrl', `${matomoUrl}matomo.php`]); + _paq.push(['setSiteId', matomoSiteId]); + + // Inject the Matomo script + const script = document.createElement('script'); + script.async = true; + script.src = `${matomoUrl}matomo.js`; + script.defer = true; + + const firstScript = document.getElementsByTagName('script')[0]; + if (firstScript && firstScript.parentNode) { + firstScript.parentNode.insertBefore(script, firstScript); + } + }, []); + + return null; +}