From dbe36ad381c00b0d3401fd23c2b41e8d0d3b9854 Mon Sep 17 00:00:00 2001 From: Martin Porwoll Date: Fri, 5 Dec 2025 14:26:08 +0000 Subject: [PATCH] feat: add super admin role and update documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add isSuperAdmin field to Users collection with migration - Update API documentation with analytics examples - Add analytics implementation guide - Update TODO with completed tasks πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../ANALYTICS_IMPLEMENTATION_GUIDE.md | 963 ++ docs/anleitungen/API_ANLEITUNG.md | 352 +- docs/anleitungen/TODO.md | 30 +- src/collections/Users.ts | 12 +- ...02_081830_add_is_super_admin_to_users.json | 13294 ++++++++++++++++ ...1202_081830_add_is_super_admin_to_users.ts | 45 + src/migrations/index.ts | 8 +- src/payload.config.ts | 2 + 8 files changed, 14696 insertions(+), 10 deletions(-) create mode 100644 docs/anleitungen/ANALYTICS_IMPLEMENTATION_GUIDE.md create mode 100644 src/migrations/20251202_081830_add_is_super_admin_to_users.json create mode 100644 src/migrations/20251202_081830_add_is_super_admin_to_users.ts diff --git a/docs/anleitungen/ANALYTICS_IMPLEMENTATION_GUIDE.md b/docs/anleitungen/ANALYTICS_IMPLEMENTATION_GUIDE.md new file mode 100644 index 0000000..3704287 --- /dev/null +++ b/docs/anleitungen/ANALYTICS_IMPLEMENTATION_GUIDE.md @@ -0,0 +1,963 @@ +# ANALYTICS-LΓ–SUNG: ImplementierungsΓΌbersicht fΓΌr Payload CMS + +## Kontext + +Du entwickelst das Multi-Tenant Payload CMS Backend und Next.js Frontend fΓΌr 4 Websites. Diese Dokumentation beschreibt die implementierte Analytics-LΓΆsung, die du in das Frontend integrieren musst. + +--- + +## Architektur-Übersicht + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ANALYTICS ARCHITEKTUR β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ OHNE CONSENT (immer aktiv) β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ UMAMI ANALYTICS β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Server: sv-analytics (10.10.181.103:3000) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Dashboard: http://10.10.181.103:3000 β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Script: /custom.js (Anti-Adblock) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Endpoint: /api/send β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Features: β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Cookieless Tracking (DSGVO-konform ohne Einwilligung) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Pageviews, Sessions, Referrer, UTM-Parameter β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Custom Events (Newsletter, Formulare, CTAs, Downloads) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ 100% Erfassung aller Besucher β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ MIT CONSENT (Kategorie: "marketing") β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ GOOGLE ADS CONVERSION β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Client-Side (bei Consent): β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Google Ads Tag (gtag.js) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Conversion Tracking β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Remarketing Audiences β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Server-Side (immer, anonymisiert): β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Google Ads Conversion API β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ Enhanced Conversions (gehashte E-Mail) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ GCLID-basierte Attribution β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ GOOGLE CONSENT MODE v2 β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Integration mit bestehendem Orestbida Consent-Banner β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ Kategorie "marketing" steuert: β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ ad_storage β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ ad_user_data β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β€’ ad_personalization β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## Infrastruktur + +### Umami Server + +| Eigenschaft | Wert | +|-------------|------| +| **Server** | sv-analytics (LXC 703) | +| **IP** | 10.10.181.103 | +| **Port** | 3000 | +| **Dashboard** | http://10.10.181.103:3000 | +| **Tracking Script** | http://10.10.181.103:3000/custom.js | +| **API Endpoint** | http://10.10.181.103:3000/api/send | +| **Datenbank** | PostgreSQL auf sv-postgres (umami_analytics) | + +### Website-IDs (Multi-Tenant) + +Nach Umami-Setup werden diese IDs vergeben: + +```typescript +// src/config/analytics.ts + +export const UMAMI_WEBSITE_IDS: Record = { + 'porwoll.de': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', + 'complexcaresolutions.de': 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy', + 'gunshin.de': 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz', + 'zweitmeinu.ng': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', +} + +export const UMAMI_HOST = process.env.NEXT_PUBLIC_UMAMI_HOST || 'http://10.10.181.103:3000' +``` + +--- + +## Frontend-Integration + +### 1. Umami Script Komponente + +```typescript +// src/components/analytics/UmamiScript.tsx + +'use client' + +import Script from 'next/script' + +interface UmamiScriptProps { + websiteId: string + host?: string +} + +export function UmamiScript({ + websiteId, + host = 'http://10.10.181.103:3000' +}: UmamiScriptProps) { + if (!websiteId) return null + + return ( +