diff --git a/Dockerfile b/Dockerfile index 67b6617..d585eea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,13 @@ RUN npm ci FROM base AS builder ARG NEXT_PUBLIC_SITE_URL +ARG NEXT_PUBLIC_UMAMI_SCRIPT_URL +ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID +ARG NEXT_PUBLIC_UMAMI_DOMAINS ENV NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL +ENV NEXT_PUBLIC_UMAMI_SCRIPT_URL=$NEXT_PUBLIC_UMAMI_SCRIPT_URL +ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=$NEXT_PUBLIC_UMAMI_WEBSITE_ID +ENV NEXT_PUBLIC_UMAMI_DOMAINS=$NEXT_PUBLIC_UMAMI_DOMAINS ENV DATABASE_URL=postgresql://build:build@localhost:5432/build?schema=public COPY --from=deps /app/node_modules ./node_modules diff --git a/deploy/production.env.example b/deploy/production.env.example index 2d4ad83..a063b02 100644 --- a/deploy/production.env.example +++ b/deploy/production.env.example @@ -21,6 +21,12 @@ AUTH_URL="https://[deine-domain.de]" NEXTAUTH_URL="https://[deine-domain.de]" NEXT_PUBLIC_SITE_URL="https://[deine-domain.de]" +# Umami Analytics (optional, cookieless) +# In Umami unter Website -> Tracking code auslesen. +NEXT_PUBLIC_UMAMI_SCRIPT_URL="https://analytics.[deine-domain.de]/script.js" +NEXT_PUBLIC_UMAMI_WEBSITE_ID="[UMAMI_WEBSITE_ID]" +NEXT_PUBLIC_UMAMI_DOMAINS="[deine-domain.de],www.[deine-domain.de]" + # Mailversand via Resend RESEND_API_KEY="re_[PRODUCTION_API_KEY]" EMAIL_FROM="Kita-Planer <[absender@deine-domain.de]>" diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml index 020c840..abd55f8 100644 --- a/docker-compose.coolify.yml +++ b/docker-compose.coolify.yml @@ -5,6 +5,9 @@ services: dockerfile: Dockerfile args: NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:?} + NEXT_PUBLIC_UMAMI_SCRIPT_URL: ${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-} + NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${NEXT_PUBLIC_UMAMI_WEBSITE_ID:-} + NEXT_PUBLIC_UMAMI_DOMAINS: ${NEXT_PUBLIC_UMAMI_DOMAINS:-} environment: NODE_ENV: production PORT: 3000 @@ -14,6 +17,9 @@ services: AUTH_URL: ${AUTH_URL:?} NEXTAUTH_URL: ${NEXTAUTH_URL:?} NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:?} + NEXT_PUBLIC_UMAMI_SCRIPT_URL: ${NEXT_PUBLIC_UMAMI_SCRIPT_URL:-} + NEXT_PUBLIC_UMAMI_WEBSITE_ID: ${NEXT_PUBLIC_UMAMI_WEBSITE_ID:-} + NEXT_PUBLIC_UMAMI_DOMAINS: ${NEXT_PUBLIC_UMAMI_DOMAINS:-} RESEND_API_KEY: ${RESEND_API_KEY:?} EMAIL_FROM: ${EMAIL_FROM:?} ADMIN_EMAIL: ${ADMIN_EMAIL:?} diff --git a/src/app/datenschutz/page.tsx b/src/app/datenschutz/page.tsx index 5eb7d6c..f637990 100644 --- a/src/app/datenschutz/page.tsx +++ b/src/app/datenschutz/page.tsx @@ -180,14 +180,31 @@ export default function DatenschutzPage() {

Kita-Planer verwendet technisch notwendige Cookies oder vergleichbare Technologien, um Login-Sitzungen sicher - bereitzustellen. [Falls Analyse- oder Marketing-Tools eingesetzt - werden, hier ergänzen.] + bereitzustellen. Für die öffentliche Website kann zusätzlich + Umami Analytics eingesetzt werden, um Seitenaufrufe anonymisiert + und ohne Cookies auszuwerten.

- 8. Rechte betroffener Personen + 8. Webanalyse mit Umami +

+

+ Wir nutzen [Umami-Instanz / Betreiber eintragen], um die Nutzung + der öffentlichen Website statistisch auszuwerten. Umami verwendet + keine Cookies, respektiert die Do-Not-Track-Einstellung des + Browsers und erfasst keine Analyseaufrufe im geschützten + Dashboard. Erfasst werden insbesondere Seitenaufrufe, + Referrer-Informationen, Browser-, Geräte- und Länderinformationen + in aggregierter Form. Die Rechtsgrundlage ist [Rechtsgrundlage + prüfen und eintragen]. +

+
+ +
+

+ 9. Rechte betroffener Personen

Betroffene Personen haben nach Maßgabe der DSGVO Rechte auf @@ -199,7 +216,7 @@ export default function DatenschutzPage() {

- 9. Beschwerderecht + 10. Beschwerderecht

Betroffene Personen können sich bei einer @@ -211,7 +228,7 @@ export default function DatenschutzPage() {

- 10. Aktualität dieser Datenschutzerklärung + 11. Aktualität dieser Datenschutzerklärung

Stand: [Datum]. Wir behalten uns vor, diese Datenschutzerklärung diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4ea8233..31d853c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { Toaster } from "@/components/ui/sonner"; +import { UmamiAnalytics } from "@/components/analytics/umami-analytics"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -59,6 +60,7 @@ export default function RootLayout({ > {children} + diff --git a/src/components/analytics/umami-analytics.tsx b/src/components/analytics/umami-analytics.tsx new file mode 100644 index 0000000..8205a3f --- /dev/null +++ b/src/components/analytics/umami-analytics.tsx @@ -0,0 +1,48 @@ +import Script from "next/script"; + +const publicAnalyticsPaths = new Set([ + "/", + "/impressum", + "/datenschutz", + "/login", + "/register", +]); + +export function UmamiAnalytics() { + const scriptUrl = process.env.NEXT_PUBLIC_UMAMI_SCRIPT_URL; + const websiteId = process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID; + const domains = process.env.NEXT_PUBLIC_UMAMI_DOMAINS; + + if (!scriptUrl || !websiteId) { + return null; + } + + return ( + <> + +