// 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.csv — optional, 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.