MBO-Tech-IT-Webseite/modules/03-analytics/TEMPLATE.md

7.6 KiB
Raw Blame History

Modul: Analytics (Seitenaufrufe + Phone-Click-Tracking)

DSGVO-konformes Tracking ohne externe Dienste: Seitenaufrufe mit Verweildauer, Browser/OS/Gerät-Erkennung, anonymisierte IP (letztes IPv4-Oktett → 0). Zusätzlich automatisches Tracking aller tel:-Link-Klicks nach Quelle/Element. Admin-Dashboard mit KPI-Cards, Zeitreihen und Top-Seiten.


Enthaltene Dateien

Ziel im neuen Projekt Inhalt
lib/analytics.ts Bot-Filter, IP-Anonymisierung, Device/Browser/OS-Parser
components/analytics/PageTracker.tsx Client-Komponente: Seitenaufruf + Verweildauer + Phone-Click-Tracking
app/api/analytics/track/route.ts POST: Seitenaufruf speichern (öffentlich, kein Auth)
app/api/analytics/track-phone-click/route.ts POST: Telefon-Click speichern (öffentlich)
app/api/admin/analytics/phone-calls/route.ts GET: Aggregierte Phone-Click-Daten (requireAdmin)
app/admin/analytics/page.tsx Admin-Dashboard mit Tabs: Seitenaufrufe + Phone-Calls
migrations/MIGRATIONS_PAGE_VIEWS.sql Tabelle page_views
migrations/MIGRATIONS_PHONE_CLICKS.sql Tabelle phone_clicks

Voraussetzungen

Keine zusätzlichen npm-Pakete. Benötigt:

  • lib/supabase.ts (Service Client)
  • lib/admin-auth.ts (für requireAdmin im Admin-Endpunkt, aus Modul 02)

Umgebungsvariablen

Keine zusätzlichen. Nutzt bestehende Supabase-Variablen.


Datenbank-Migrationen (Supabase)

migrations/MIGRATIONS_PAGE_VIEWS.sql   → Tabelle page_views
migrations/MIGRATIONS_PHONE_CLICKS.sql → Tabelle phone_clicks

Tabellen-Übersicht:

page_views:    path, timestamp, ip_anon, device_type, browser, os, referrer, session_id, duration_ms, is_bot
phone_clicks:  phone_number, source_page, source_element, session_id, ip_anonymized, device_type, browser, os, timestamp

Supabase-Typen (lib/supabase.ts) ergänzen:

page_views: { Row: { id: string; path: string; timestamp: string; ip_anon: string | null; device_type: string | null; browser: string | null; os: string | null; referrer: string | null; session_id: string; duration_ms: number | null; is_bot: boolean } }
phone_clicks: { Row: { id: number; phone_number: string; source_page: string; source_element: string; session_id: string | null; ip_anonymized: string | null; device_type: string | null; browser: string | null; os: string | null; timestamp: string } }

Einbindung Schritt für Schritt

1. Dateien kopieren

2. PageTracker in Root-Layout einbinden (app/layout.tsx)

import { PageTracker } from "@/components/analytics/PageTracker";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <PageTracker />
        {children}
      </body>
    </html>
  );
}

Der PageTracker hört automatisch auf Klicks von <a href="tel:...">. Damit die Quelle erfasst wird, muss das Attribut gesetzt sein:

<a href="tel:+49123456789" data-source-element="header">Anrufen</a>

Empfohlene Element-Namen (Konvention: lowercase, kebab-case):

  • header, footer, hero, cta-banner, kontakt-form, sidebar

4. Admin-Dashboard verlinken

// In Admin-Navigation
<Link href="/admin/analytics">Analytics</Link>

5. Admin-Routen aus Tracking ausschließen

PageTracker.tsx filtert bereits /admin/* und /api/* keine Anpassung nötig.


Anpassungspunkte

Was Wo
Ausgeschlossene Pfade components/analytics/PageTracker.tsxEXCLUDED_PATHS
Datenaufbewahrung (13 Monate) Supabase Cron: DELETE FROM page_views WHERE timestamp < now() - interval '13 months'
Bot-Filter-Pattern lib/analytics.tsBOT_PATTERNS Array
Dashboard-Zeiträume app/admin/analytics/page.tsx → Filter-Buttons
Geo-Lookup aktivieren app/api/analytics/track-phone-click/route.tsGEO_LOOKUP_ENABLED env var

Integrations-Prompt

Kopiere diesen Prompt in eine neue KI-Konversation, nachdem du die files/ in dein Projekt kopiert hast. Ersetze alle [PLATZHALTER].

Ich integriere das Analytics-Modul (DSGVO-konforme Seitenaufrufe + Phone-Click-Tracking) in mein Next.js/Supabase-Projekt.

PROJEKT-KONTEXT:
- Admin-Auth-Modul (02) ist bereits integriert (requireAdmin verfügbar)
- lib/supabase.ts mit Service Client vorhanden
- Admin-Bereich unter /admin

BEREITS KOPIERTE DATEIEN (aus modules/03-analytics/files/):
- lib/analytics.ts
- components/analytics/PageTracker.tsx
- app/api/analytics/track/route.ts
- app/api/analytics/track-phone-click/route.ts
- app/api/admin/analytics/phone-calls/route.ts
- app/admin/analytics/page.tsx

AUFGABEN  führe sie der Reihe nach aus:

1. SUPABASE-MIGRATIONEN: Führe diese SQLs im Supabase SQL-Editor aus:

   -- Aus migrations/MIGRATIONS_PAGE_VIEWS.sql:
   CREATE TABLE IF NOT EXISTS page_views (
     id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
     path text NOT NULL, timestamp timestamptz NOT NULL DEFAULT now(),
     ip_anon text, device_type text CHECK (device_type IN ('desktop','tablet','mobile')),
     browser text, os text, referrer text,
     session_id text NOT NULL, duration_ms int, is_bot boolean NOT NULL DEFAULT false
   );
   CREATE INDEX IF NOT EXISTS idx_pv_timestamp ON page_views (timestamp DESC);
   CREATE INDEX IF NOT EXISTS idx_pv_path ON page_views (path);
   CREATE INDEX IF NOT EXISTS idx_pv_session ON page_views (session_id);
   ALTER TABLE page_views ENABLE ROW LEVEL SECURITY;
   CREATE POLICY "Service-Role Vollzugriff" ON page_views USING (true) WITH CHECK (true);

   -- Aus migrations/MIGRATIONS_PHONE_CLICKS.sql:
   CREATE TABLE IF NOT EXISTS phone_clicks (
     id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
     phone_number TEXT NOT NULL, source_page TEXT NOT NULL,
     source_element TEXT NOT NULL, session_id TEXT, ip_anonymized TEXT,
     device_type TEXT, browser TEXT, os TEXT, timestamp TIMESTAMPTZ DEFAULT now()
   );
   CREATE INDEX IF NOT EXISTS idx_phone_clicks_timestamp ON phone_clicks(timestamp DESC);
   ALTER TABLE phone_clicks DISABLE ROW LEVEL SECURITY;

2. SUPABASE-TYPEN: Lies lib/supabase.ts und ergänze in Database.public.Tables:
   page_views: { Row: { id: string; path: string; timestamp: string; ip_anon: string | null; device_type: string | null; browser: string | null; os: string | null; referrer: string | null; session_id: string; duration_ms: number | null; is_bot: boolean } }
   phone_clicks: { Row: { id: number; phone_number: string; source_page: string; source_element: string; session_id: string | null; ip_anonymized: string | null; device_type: string | null; browser: string | null; os: string | null; timestamp: string } }

3. PAGE-TRACKER einbinden: Lies app/layout.tsx.
   Füge den Import und die Komponente im <body> hinzu (vor {children}):
   import { PageTracker } from "@/components/analytics/PageTracker";
   // Im JSX:
   <PageTracker />

4. TEL-LINKS mit Tracking versehen: Suche im gesamten Projekt nach href="tel:
   Füge bei jedem gefundenen Link das Attribut data-source-element="[ELEMENT_NAME]" hinzu.
   Konvention für [ELEMENT_NAME]: header, footer, hero, cta-banner, kontakt-form (lowercase, kebab-case)

5. ADMIN-NAV ergänzen: Lies die Admin-Navigations-Datei (meist components/admin/AdminNav.tsx).
   Füge einen Link zu /admin/analytics hinzu.

6. TEST:
   a) Dev-Server starten, /kontakt oder eine andere Seite aufrufen
   b) Supabase → Table page_views → neuer Eintrag sollte erscheinen
   c) Auf eine Telefonnummer klicken → Supabase → Table phone_clicks → neuer Eintrag
   d) /admin/analytics aufrufen → KPI-Cards sollten Daten zeigen

Lies jede Datei vor dem Bearbeiten. Melde wenn alle Schritte abgeschlossen sind.