7.6 KiB
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ürrequireAdminim 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>
);
}
3. Tel-Links mit data-source-element versehen
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.tsx → EXCLUDED_PATHS |
| Datenaufbewahrung (13 Monate) | Supabase Cron: DELETE FROM page_views WHERE timestamp < now() - interval '13 months' |
| Bot-Filter-Pattern | lib/analytics.ts → BOT_PATTERNS Array |
| Dashboard-Zeiträume | app/admin/analytics/page.tsx → Filter-Buttons |
| Geo-Lookup aktivieren | app/api/analytics/track-phone-click/route.ts → GEO_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.