// Client Report Generator · GSC + GA4 + Google Ads → Claude API

Monatsreport
automatisch generieren

CSV-Exporte aus den drei wichtigsten Datenquellen, ein Python-Skript, ein Claude API Key — fertig ist der professionelle Kundenbericht.

// Was Kunden monatlich wirklich interessiert
GSC Sichtbarkeit & Reichweite
GA4 Traffic & Conversions
Google Ads Budget & Performance
Schritt 01

Google Search Console exportieren

Sichtbarkeit, Klicks, Positionen und Top-Keywords als CSV

1.1 Leistungsbericht öffnen & Zeitraum setzen

Oben rechts auf den Datumsbereich-Filter klicken und „Letzter Monat" auswählen. Sicherstellen, dass alle vier Messwerte aktiv sind:

Gesamtklicks Gesamtimpressionen Durchschn. CTR Durchschn. Position
Tipp: Falls du Vormonat-Vergleiche im Report willst, aktiviere zusätzlich den Vergleichszeitraum (Vorheriger Zeitraum).
1.2 Export 1: Top-Seiten (Pages)

Im Tab „Seiten" unten links auf die Anzahl der Zeilen klicken und 500 auswählen. Dann oben rechts:

Datei umbenennen in: gsc_pages.csv

Seite (URL) Klicks Impressionen CTR Position
1.3 Export 2: Top-Keywords (Queries)

Gleicher Vorgang wie bei Seiten — Tab wechseln auf „Suchanfragen", sortieren nach Klicks, 500 Zeilen, exportieren.

Datei umbenennen in: gsc_queries.csv

Achtung: GSC zeigt aus Datenschutzgründen nur Keywords mit ausreichend Impressionen. Keywords unter dem Schwellenwert werden aggregiert als „other" ausgewiesen — das ist normal.

Schritt 02

Google Analytics 4 exportieren

Sessions, Nutzer, Kanäle, Top-Seiten und Conversions

2.1 Traffic-Übersicht: Kanal-Aufschlüsselung

Datumsbereich oben rechts auf den gewünschten Vormonat setzen. Die Tabelle zeigt die Aufschlüsselung nach Kanal (Organic, Direct, Paid, Referral etc.).

Unten rechts auf „Zeilen pro Seite" → 25, dann oben rechts:

Datei umbenennen in: ga4_channels.csv

Standardkanal-Gruppierung Sitzungen Nutzer Engagement Rate Conversions
2.2 Top-Seiten: Seiten und Bildschirme

Gleichen Datumsbereich setzen. Tabelle sortieren nach Aufrufe (absteigend), Zeilen auf 25 setzen, als CSV exportieren.

Datei umbenennen in: ga4_pages.csv

Seitenpfad + Abfragestring Aufrufe Nutzer Engagement Rate Ø Engagement-Zeit
2.3 Conversions-Report

Listet alle definierten Conversion-Ereignisse. Gleichen Zeitraum setzen, als CSV exportieren.

Datei umbenennen in: ga4_conversions.csv

Hinweis: Falls keine Conversions konfiguriert sind, reicht der Channels-Export. Der Report-Generator erkennt automatisch, welche Dateien vorhanden sind.
Ereignisname Conversions Gesamtumsatz (falls vorhanden)

Schritt 03

Google Ads exportieren

Kampagnen, Budget, Klicks, Conversions und CPA

3.1 Kampagnenübersicht exportieren

Datumsbereich oben rechts auf letzten Monat setzen. Spalten prüfen — folgende müssen sichtbar sein:

Kampagne Status Budget Kosten Klicks Impressionen CTR Ø CPC Conversions Kosten/Conversion Conv.-Rate

Falls Spalten fehlen: oben rechts auf „Spalten"„Spalten ändern" → entsprechende Messwerte hinzufügen.

Datei umbenennen in: ads_campaigns.csv

3.2 Anzeigengruppen-Detail (optional)

Datei umbenennen in: ads_adgroups.csvoptional, der Report-Generator nutzt diese Datei für detailliertere Kampagnenanalysen, falls vorhanden.

Pflichtdatei ist nur ads_campaigns.csv. Alle anderen Ads-Exporte sind optional.

Schritt 04

Ordnerstruktur anlegen

Alle CSV-Dateien an den richtigen Ort legen

Einen neuen Ordner anlegen, z.B. monatsreport-2025-05/. Alle exportierten Dateien hineinlegen:

monatsreport-2025-05/ ├── gsc_pages.csv # GSC Top-Seiten ├── gsc_queries.csv # GSC Top-Keywords ├── ga4_channels.csv # GA4 Kanal-Übersicht ├── ga4_pages.csv # GA4 Top-Seiten ├── ga4_conversions.csv # GA4 Conversions (optional) ├── ads_campaigns.csv # Google Ads Kampagnen └── ads_adgroups.csv # Ads Anzeigengruppen (optional)

Das Python-Skript liest automatisch alle vorhandenen Dateien ein und passt den Report-Inhalt entsprechend an — fehlende Dateien werden übersprungen.

Python erforderlich: Python 3.9+ muss installiert sein. Prüfen mit python --version oder python3 --version. Falls nicht vorhanden: python.org/downloads

Schritt 05

Claude API Key eintragen

Der Key wird nur lokal ins Script eingebettet — er verlässt deinen Browser nicht

Claude API Key

Den Key findest du unter console.anthropic.com → API Keys. Er wird direkt in das Python-Skript unten eingetragen.

Modell:
Kosten pro Report: Bei claude-sonnet-4-6 ca. $0.05–0.20 pro Report-Generierung, je nach Datenmenge. Bei Opus entsprechend mehr.

Schritt 06

Python-Skript speichern & ausführen

Skript kopieren → in den Report-Ordner legen → ausführen

Das Skript in den Ordner mit den CSV-Dateien speichern als generate_report.py. Dann im Terminal:

#!/usr/bin/env python3 # ============================================================= # SEYBOLD ONE – Monatsreport Generator # Liest GSC, GA4 und Google Ads CSV-Exporte und erstellt # einen HTML-Monatsreport via Claude API. # ============================================================= import os, sys, json, pathlib from datetime import datetime import pandas as pd import anthropic # ── KONFIGURATION ────────────────────────────────────────── API_KEY = "DEIN_API_KEY_HIER" # ← wird automatisch ersetzt MODEL = "claude-sonnet-4-6" MONAT = datetime.now().strftime("%B %Y") # z.B. "Mai 2025" CLIENT = "KUNDENNAME" # ← hier anpassen DOMAIN = "domain.de" # ← hier anpassen FOLDER = pathlib.Path(".") # CSV-Dateien im gleichen Ordner OUTPUT = f"report_{datetime.now().strftime('%Y-%m')}.html" # ── CSV LOADER ───────────────────────────────────────────── def load_csv(filename, skip_rows=0): path = FOLDER / filename if not path.exists(): return None try: df = pd.read_csv(path, skiprows=skip_rows) df.columns = [c.strip() for c in df.columns] return df except Exception as e: print(f" ⚠ Fehler beim Laden von {filename}: {e}") return None def df_to_text(df, max_rows=20, title=""): if df is None or df.empty: return "" lines = [f"## {title}"] if title else [] lines.append(df.head(max_rows).to_csv(index=False, sep=";")) return "\n".join(lines) # ── DATEN LADEN ──────────────────────────────────────────── print(f"\n📊 SEYBOLD ONE – Monatsreport Generator") print(f" Kunde: {CLIENT} | Monat: {MONAT}\n") gsc_pages = load_csv("gsc_pages.csv") gsc_queries = load_csv("gsc_queries.csv") ga4_channels = load_csv("ga4_channels.csv", skip_rows=9) # GA4 hat 9 Header-Zeilen ga4_pages = load_csv("ga4_pages.csv", skip_rows=9) ga4_conv = load_csv("ga4_conversions.csv", skip_rows=9) ads_camp = load_csv("ads_campaigns.csv", skip_rows=2) # Ads hat 2 Header-Zeilen ads_adg = load_csv("ads_adgroups.csv", skip_rows=2) # ── DATEN ZUSAMMENSTELLEN ────────────────────────────────── data_sections = [] if gsc_pages is not None: data_sections.append(df_to_text(gsc_pages.sort_values( gsc_pages.columns[1], ascending=False), 25, "GSC: Top-Seiten nach Klicks")) print(f" ✓ gsc_pages.csv ({len(gsc_pages)} Zeilen)") if gsc_queries is not None: data_sections.append(df_to_text(gsc_queries.sort_values( gsc_queries.columns[1], ascending=False), 30, "GSC: Top-Keywords nach Klicks")) print(f" ✓ gsc_queries.csv ({len(gsc_queries)} Zeilen)") if ga4_channels is not None: data_sections.append(df_to_text(ga4_channels, 15, "GA4: Traffic-Kanäle")) print(f" ✓ ga4_channels.csv ({len(ga4_channels)} Zeilen)") if ga4_pages is not None: data_sections.append(df_to_text(ga4_pages, 20, "GA4: Top-Seiten")) print(f" ✓ ga4_pages.csv ({len(ga4_pages)} Zeilen)") if ga4_conv is not None: data_sections.append(df_to_text(ga4_conv, 15, "GA4: Conversions")) print(f" ✓ ga4_conversions.csv ({len(ga4_conv)} Zeilen)") if ads_camp is not None: data_sections.append(df_to_text(ads_camp, 20, "Google Ads: Kampagnen")) print(f" ✓ ads_campaigns.csv ({len(ads_camp)} Zeilen)") if ads_adg is not None: data_sections.append(df_to_text(ads_adg, 15, "Google Ads: Anzeigengruppen")) print(f" ✓ ads_adgroups.csv ({len(ads_adg)} Zeilen)") if not data_sections: print("\n❌ Keine CSV-Dateien gefunden. Bitte Dateien in den gleichen Ordner legen.") sys.exit(1) all_data = "\n\n".join(filter(None, data_sections)) # ── CLAUDE API PROMPT ────────────────────────────────────── system_prompt = """Du bist ein erfahrener SEO- und Performance-Marketing-Analyst. Du erstellst professionelle Monatsberichte für Kunden auf Basis von GSC-, GA4- und Google-Ads-Daten. Deine Berichte sind klar strukturiert, datenbasiert und handlungsorientiert – jede Erkenntnis endet mit einer konkreten Empfehlung.""" user_prompt = f"""Erstelle einen vollständigen, professionellen HTML-Monatsreport für: Kunde: {CLIENT} Domain: {DOMAIN} Berichtszeitraum: {MONAT} === ROHDATEN === {all_data} === ANWEISUNGEN === Erstelle einen vollständigen, eigenständigen HTML-Report mit: 1. EXECUTIVE SUMMARY (3–5 Sätze: wichtigste Erkenntnisse auf einen Blick) 2. GSC-ANALYSE (falls Daten vorhanden): - Gesamtklicks & Impressionen mit Bewertung - Durchschnittliche CTR und Position - Top 5 Seiten nach Klicks (Tabelle) - Top 10 Keywords nach Klicks (Tabelle) - Auffälligkeiten & Handlungsempfehlungen 3. GA4-ANALYSE (falls Daten vorhanden): - Sessions, Nutzer, Engagement Rate (Tabelle) - Kanal-Aufschlüsselung (Tabelle mit Anteil in %) - Top 5 Seiten nach Aufrufen (Tabelle) - Conversion-Performance (falls Daten vorhanden) - Bewertung und Empfehlungen 4. GOOGLE ADS-ANALYSE (falls Daten vorhanden): - Budget-Überblick: Ausgaben, Klicks, Impressionen - Kampagnen-Performance Tabelle (sortiert nach Kosten) - Bewertung CPC, CPA, Conversion Rate - Konkrete Optimierungsempfehlungen 5. PRIORITÄTEN FÜR DEN NÄCHSTEN MONAT - 3 konkrete, priorisierte Handlungsempfehlungen === HTML-DESIGN-VORGABEN === Erstelle das HTML mit diesem exakten Design-System: - Hintergrund: #0d0f0a (sehr dunkles Grün-Schwarz) - Surface-Farbe für Karten: #1e2410 - Border-Farbe: #2e3818 - Akzentfarbe: #739a2d (Grün) - Helle Akzentfarbe: #8fb83a - Text: #d8e0c0 - Text-gedimmt: #7a8a5a - Schrift: Poppins (Google Fonts) für Überschriften, DM Mono für Labels/Code - Tabellen: dunkle Hintergrundfarben, grüne Header-Linie oben, 1px Border - Alle Abschnitte als Karten mit border-radius: 8px und border: 1px solid #2e3818 - Branding oben: "SEYBOLD ONE" in Rockwell/Serif + "Monatsreport {MONAT}" - Footer: "Erstellt mit SEYBOLD ONE Report Generator · ai.seybold.de" Das HTML muss vollständig und eigenständig sein (alle Styles inline oder im ), keine externen Abhängigkeiten außer Google Fonts. Gib NUR den HTML-Code zurück, ohne Erklärungen oder Markdown-Backticks.""" # ── API CALL ─────────────────────────────────────────────── print(f"\n🤖 Sende Daten an Claude ({MODEL})…") client = anthropic.Anthropic(api_key=API_KEY) try: message = client.messages.create( model=MODEL, max_tokens=8192, system=system_prompt, messages=[{"role": "user", "content": user_prompt}] ) html_output = message.content[0].text # Markdown-Backticks entfernen falls vorhanden if html_output.startswith("```"): html_output = html_output.split("\n", 1)[1] html_output = html_output.rsplit("```", 1)[0] # Report speichern output_path = FOLDER / OUTPUT output_path.write_text(html_output, encoding="utf-8") tokens_in = message.usage.input_tokens tokens_out = message.usage.output_tokens cost_est = round((tokens_in / 1_000_000) * 3.0 + (tokens_out / 1_000_000) * 15.0, 4) print(f"\n✅ Report erstellt: {OUTPUT}") print(f" Tokens: {tokens_in:,} In / {tokens_out:,} Out") print(f" Geschätzte Kosten: ~${cost_est}") print(f"\n🌐 Im Browser öffnen:\n {output_path.resolve()}\n") except anthropic.AuthenticationError: print("\n❌ API Key ungültig. Bitte in Zeile 15 prüfen.") sys.exit(1) except anthropic.RateLimitError: print("\n❌ Rate Limit erreicht. Kurz warten und erneut versuchen.") sys.exit(1) except Exception as e: print(f"\n❌ Fehler: {e}") sys.exit(1)
Ausgabe: Das Skript erstellt eine Datei report_2025-05.html im gleichen Ordner. Diese kann direkt im Browser geöffnet oder dem Kunden als Datei zugeschickt werden.

Schritt 07

Anpassen & wiederverwenden

Kundenname, Domain und weitere Einstellungen

Für jeden Kunden oder jeden Monat nur diese Zeilen im Skript anpassen:

Variable Beschreibung Beispiel
CLIENT Name des Kunden — erscheint im Report-Header "Kundenname GmbH"
DOMAIN Domain des Kunden — für Kontext im Prompt "domain.de"
MONAT Wird automatisch gesetzt, kann überschrieben werden "April 2025"
MODEL Claude-Modell — Sonnet für Standard, Opus für maximale Tiefe "claude-opus-4-6"
FOLDER Pfad zum CSV-Ordner, falls Skript woanders liegt Path("../daten/mai25")
Tipp Mehrere Kunden automatisieren

Für mehrere Kunden empfiehlt sich eine clients.json Konfigurationsdatei:

{ "clients": [ { "name": "Kunde A GmbH", "domain": "kunde-a.de", "folder": "./kunde-a/2025-05/" }, { "name": "Kunde B AG", "domain": "kunde-b.de", "folder": "./kunde-b/2025-05/" } ] }

Das Skript kann dann mit einem Loop über alle Kunden laufen und für jeden einen Report erstellen.

Tipp Report als PDF speichern

Den HTML-Report im Chrome-Browser öffnen, dann:

Alternativ mit pip install weasyprint direkt aus Python als PDF exportieren.