API Setup Guide v1.0
// Multi-Client Setup · GSC + GA4 + Ads + AI Visibility

Google API
Intelligence Layer
für Agency-Clients

Einmalig einrichten, dauerhaft nutzen. Alle vier Datenquellen in einem Projektverzeichnis – cross-referenzierbar per Claude Code oder direkt im Terminal.

01Google Cloud
02Verzeichnis
03GSC + GA4
04Google Ads
05AI Visibility
06Config + Run
0

// VorbereitungVoraussetzungen prüfen

Software
  • Python 3.9+ installiert
  • pip (kommt mit Python)
  • Terminal / iTerm2 (Mac) oder WSL (Windows)
  • Cursor oder VS Code
Zugänge
  • Google-Account mit GSC-Zugriff auf Client-Properties
  • GA4-Properties der Clients
  • Google Ads MCC oder einzelne Accounts
  • DataForSEO Account (kostenloser Test reicht zunächst)

Python prüfen:

python3 --version  # sollte 3.9+ zeigen
pip3 --version
1

// Google Cloud ConsoleService Account einrichten

Ein Service Account deckt GSC + GA4 für alle Clients ab. Einmal erstellt, nur noch per E-Mail zu jeder Property hinzufügen.

1.1 · Google Cloud Projekt erstellen

Schritt für Schritt
  • console.cloud.google.com öffnen
  • Oben links: „Projekt auswählen" → „Neues Projekt"
  • Name: z.B. seybold-agency-apis
  • Projekt erstellen und warten bis aktiv

1.2 · APIs aktivieren

Navigation: APIs & Dienste → Bibliothek
  • Suche: „Search Console API" → Aktivieren
  • Suche: „Google Analytics Data API" → Aktivieren

1.3 · Service Account erstellen

Navigation: IAM & Verwaltung → Dienstkonten
  • „+ Dienstkonto erstellen" klicken
  • Name: seybold-reporting (o.ä.)
  • Beschreibung: „Agency Reporting GSC + GA4"
  • Rollen: nicht nötig → „Fertig"
  • In der Liste auf den neuen Account klicken → Tab „Schlüssel"
  • „Schlüssel hinzufügen" → JSON → herunterladen
Die heruntergeladene JSON-Datei ist dein Master-Key. Nie in Git committen. Sicher ablegen, z.B. in ~/.credentials/seybold-service-account.json. Auf diese Datei zeigen alle Fetcher.

Die Service-Account-E-Mail sieht so aus:
[email protected]

Diese E-Mail-Adresse wird bei jedem Client als Nutzer eingetragen (nächster Schritt).

2

// ProjektstrukturVerzeichnis anlegen

mkdir -p ~/seybold-intel/{fetchers,data/{gsc,ga4,ads,ai-visibility},reports,clients}
cd ~/seybold-intel

Finale Struktur:

seybold-intel/
├── fetchers/
│ ├── fetch_gsc.py # Search Console Fetcher
│ ├── fetch_ga4.py # Analytics 4 Fetcher
│ ├── fetch_ads.py # Google Ads Fetcher
│ └── fetch_ai.py # DataForSEO AI Visibility
├── clients/
│ ├── coca-cola.json # Config pro Client
│ └── example-client.json
├── data/ # JSON-Output (gitignore)
│ ├── gsc/
│ ├── ga4/
│ ├── ads/
│ └── ai-visibility/
├── reports/ # Generierte Analysen
├── run_fetch.py # Haupt-Runner
└── .env # Credentials (gitignore)

Python-Abhängigkeiten installieren

pip3 install google-api-python-client google-auth \
             google-analytics-data google-ads \
             requests python-dotenv

.env Datei anlegen

# ~/seybold-intel/.env
SERVICE_ACCOUNT_KEY=/Users/dein-name/.credentials/seybold-service-account.json
DATAFORSEO_LOGIN=[email protected]
DATAFORSEO_PASSWORD=dein-passwort
# .gitignore anlegen (falls Git genutzt wird)
echo ".env\ndata/\n*.json\n!clients/*.json" > .gitignore
3

// GSC + GA4Service Account zu Client-Properties hinzufügen

3.1 · Search Console

Pro Client wiederholen
  • search.google.com/search-console → Property öffnen
  • Einstellungen → Nutzer und Berechtigungen
  • „Nutzer hinzufügen" → Service-Account-E-Mail eintragen
  • Berechtigung: Eingeschränkt (reicht aus)

3.2 · Google Analytics 4

Pro Client wiederholen
  • analytics.google.com → Admin → Property-Zugriffsverwaltung
  • „+" → Nutzer hinzufügen → Service-Account-E-Mail
  • Rolle: Leser

3.3 · GSC Fetcher

# fetchers/fetch_gsc.py
import os, json
from dotenv import load_dotenv
from google.oauth2 import service_account
from googleapiclient.discovery import build
from datetime import date, timedelta

load_dotenv()

SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']

def get_service():
    creds = service_account.Credentials.from_service_account_file(
        os.getenv('SERVICE_ACCOUNT_KEY'), scopes=SCOPES
    )
    return build('searchconsole', 'v1', credentials=creds)

def fetch_queries(site_url, days=90):
    service = get_service()
    end = date.today()
    start = end - timedelta(days=days)
    response = service.searchanalytics().query(
        siteUrl=site_url,
        body={
            'startDate': str(start),
            'endDate': str(end),
            'dimensions': ['query', 'page'],
            'rowLimit': 5000
        }
    ).execute()
    return response.get('rows', [])

def save(data, client_name):
    path = f"data/gsc/{client_name}_queries.json"
    with open(path, 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    print(f"✓ GSC: {len(data)} Zeilen → {path}")

3.4 · GA4 Fetcher

# fetchers/fetch_ga4.py
import os, json
from dotenv import load_dotenv
from google.oauth2 import service_account
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import (
    RunReportRequest, DateRange, Metric, Dimension
)
from datetime import date, timedelta

load_dotenv()

def get_client():
    creds = service_account.Credentials.from_service_account_file(
        os.getenv('SERVICE_ACCOUNT_KEY'),
        scopes=['https://www.googleapis.com/auth/analytics.readonly']
    )
    return BetaAnalyticsDataClient(credentials=creds)

def fetch_traffic(property_id, days=90):
    client = get_client()
    end = date.today()
    start = end - timedelta(days=days)
    req = RunReportRequest(
        property=f"properties/{property_id}",
        date_ranges=[DateRange(start_date=str(start), end_date=str(end))],
        dimensions=[
            Dimension(name="sessionDefaultChannelGroup"),
            Dimension(name="landingPagePlusQueryString")
        ],
        metrics=[
            Metric(name="sessions"),
            Metric(name="totalUsers"),
            Metric(name="bounceRate"),
            Metric(name="averageSessionDuration")
        ]
    )
    response = client.run_report(req)
    rows = []
    for row in response.rows:
        rows.append({
            "channel": row.dimension_values[0].value,
            "page": row.dimension_values[1].value,
            "sessions": row.metric_values[0].value,
            "users": row.metric_values[1].value,
            "bounce_rate": row.metric_values[2].value,
            "avg_duration": row.metric_values[3].value
        })
    return rows

def save(data, client_name):
    path = f"data/ga4/{client_name}_traffic.json"
    with open(path, 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    print(f"✓ GA4: {len(data)} Zeilen → {path}")
4

// Google AdsOAuth + Developer Token

Google Ads braucht separates OAuth – kein Service Account. Dauer: ~30–60 Min + 24–48 Std Wartezeit für Developer Token-Genehmigung.

4.1 · Developer Token beantragen

Im Google Ads Manager Account (MCC)
  • Ads-Konto öffnen → Tools & Einstellungen → API Center
  • Developer Token beantragen
  • Anwendungsbeschreibung: „Automated reporting for digital marketing agency clients. Internal use only."
  • Genehmigung: meist 24–48 Stunden per E-Mail

4.2 · OAuth Client erstellen

Google Cloud Console → APIs → Anmeldedaten
  • „Anmeldedaten erstellen" → OAuth-Client-ID
  • Anwendungstyp: Desktop-App
  • Client-ID und Client-Secret notieren
  • JSON herunterladen als oauth-client.json

4.3 · Refresh Token generieren (einmalig)

# pip3 install google-auth-oauthlib
from google_auth_oauthlib.flow import InstalledAppFlow

flow = InstalledAppFlow.from_client_secrets_file(
    'oauth-client.json',
    scopes=['https://www.googleapis.com/auth/adwords']
)
creds = flow.run_local_server(port=0)
print("Refresh Token:", creds.refresh_token)

Den Refresh Token in die google-ads.yaml eintragen:

# google-ads.yaml (NICHT in Git!)
developer_token: DEIN_DEVELOPER_TOKEN
client_id: DEIN_CLIENT_ID.apps.googleusercontent.com
client_secret: DEIN_CLIENT_SECRET
refresh_token: DEIN_REFRESH_TOKEN
login_customer_id: DEIN_MCC_ID  # ohne Bindestriche

4.4 · Ads Fetcher

# fetchers/fetch_ads.py
import json
from google.ads.googleads.client import GoogleAdsClient

def fetch_search_terms(customer_id, days=30):
    client = GoogleAdsClient.load_from_storage("google-ads.yaml")
    ga_service = client.get_service("GoogleAdsService")

    query = f"""
        SELECT
            search_term_view.search_term,
            campaign.name,
            ad_group.name,
            segments.keyword.info.match_type,
            metrics.impressions,
            metrics.clicks,
            metrics.cost_micros,
            metrics.conversions,
            metrics.ctr
        FROM search_term_view
        WHERE segments.date DURING LAST_{days}_DAYS
          AND metrics.impressions > 0
        ORDER BY metrics.clicks DESC
        LIMIT 5000
    """

    rows = []
    response = ga_service.search(customer_id=customer_id.replace('-',''), query=query)
    for row in response:
        rows.append({
            "search_term": row.search_term_view.search_term,
            "campaign": row.campaign.name,
            "ad_group": row.ad_group.name,
            "match_type": row.segments.keyword.info.match_type.name,
            "impressions": row.metrics.impressions,
            "clicks": row.metrics.clicks,
            "cost_eur": row.metrics.cost_micros / 1_000_000,
            "conversions": row.metrics.conversions,
            "ctr": row.metrics.ctr
        })
    return rows

def save(data, client_name):
    path = f"data/ads/{client_name}_search_terms.json"
    with open(path, 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    print(f"✓ Ads: {len(data)} Zeilen → {path}")
💡
Fallback ohne API: Search Terms als CSV aus Google Ads UI herunterladen (90 Tage), in data/ads/ ablegen. Claude Code kann CSV-Dateien genauso auswerten.
5

// DataForSEO + BingAI Visibility Tracking

5.1 · DataForSEO Account

Einrichtung
  • app.dataforseo.com → Registrieren (kostenloser Test)
  • Mindestguthaben: $50 (Pay-as-you-go, ca. $0.01/Query)
  • Login + Passwort in .env eintragen

5.2 · AI Visibility Fetcher

# fetchers/fetch_ai.py
import os, json, requests
from dotenv import load_dotenv

load_dotenv()

BASE_URL = "https://api.dataforseo.com/v3"
AUTH = (
    os.getenv('DATAFORSEO_LOGIN'),
    os.getenv('DATAFORSEO_PASSWORD')
)

def fetch_ai_overviews(keywords, location_code=2276):
    # location_code 2276 = Deutschland
    payload = [
        {"keyword": kw, "location_code": location_code, "language_code": "de"}
        for kw in keywords
    ]
    response = requests.post(
        f"{BASE_URL}/serp/google/ai_overview/live/advanced",
        auth=AUTH, json=payload
    )
    return response.json()

def fetch_llm_mentions(brand, location_code=2276):
    # Prüft Brand-Erwähnungen in LLM-Antworten
    payload = [{"brand": brand, "location_code": location_code}]
    response = requests.post(
        f"{BASE_URL}/content_analysis/summary/live",
        auth=AUTH, json=payload
    )
    return response.json()

def save(data, client_name, source="ai_overviews"):
    path = f"data/ai-visibility/{client_name}_{source}.json"
    with open(path, 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    print(f"✓ AI: → {path}")

5.3 · Bing Webmaster Tools (kostenlos)

Erster AI-Datenpunkt ohne Kosten
  • bing.com/webmasters → Property für Client hinzufügen
  • „Copilot" Tab: zeigt Seiten, die als Quelle in Copilot-Antworten erscheinen
  • CSV-Export → in data/ai-visibility/ ablegen
  • Kein API nötig – monatlich manuell exportieren
ToolKostenPlattformenEmpfehlung
DataForSEO~$0.01/QueryGoogle AI Overview✓ Start hier
Bing WebmasterKostenlosCopilot / Bing AI✓ Immer nutzen
Peec.aiauf AnfrageMulti-LLM DACHEnterprise
SerpApiab $75/MonatGoogle SERP + AIOWenn Budget
6

// Client Config + RunAlles zusammenführen

6.1 · Client-Config-Datei

// clients/coca-cola.json
{
  "name": "Coca-Cola",
  "slug": "coca-cola",
  "domain": "coca-cola.com",
  "gsc_property": "https://www.coca-cola.com/",
  "ga4_property_id": "XXXXXXXXX",
  "google_ads_customer_id": "XXXX-XXXX-XXXX",
  "industry": "Getränke / FMCG",
  "brand_terms": ["Coca-Cola", "Coke", "Cola"],
  "ai_keywords": [
    "cola kaufen online",
    "erfrischungsgetränke marken vergleich",
    "coca cola zero zucker inhaltsstoffe"
  ],
  "competitors": [
    "pepsi.com", "redbull.com", "monster.com"
  ]
}

6.2 · Haupt-Runner

# run_fetch.py
import json, argparse, sys
from fetchers import fetch_gsc, fetch_ga4, fetch_ads, fetch_ai
from pathlib import Path

def load_client(slug):
    path = Path(f"clients/{slug}.json")
    if not path.exists():
        print(f"❌ Client '{slug}' nicht gefunden in clients/")
        sys.exit(1)
    return json.loads(path.read_text())

def run(client_slug, sources):
    cfg = load_client(client_slug)
    slug = cfg["slug"]
    print(f"\n→ Fetching: {cfg['name']} | Sources: {', '.join(sources)}\n")

    if "gsc" in sources:
        data = fetch_gsc.fetch_queries(cfg["gsc_property"])
        fetch_gsc.save(data, slug)

    if "ga4" in sources:
        data = fetch_ga4.fetch_traffic(cfg["ga4_property_id"])
        fetch_ga4.save(data, slug)

    if "ads" in sources:
        data = fetch_ads.fetch_search_terms(cfg["google_ads_customer_id"])
        fetch_ads.save(data, slug)

    if "ai" in sources:
        data = fetch_ai.fetch_ai_overviews(cfg["ai_keywords"])
        fetch_ai.save(data, slug, "ai_overviews")

    print(f"\n✅ Fertig. Daten in data/ → Claude Code kann jetzt loslegen.\n")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--client", required=True)
    parser.add_argument("--sources", default="gsc,ga4,ads,ai")
    args = parser.parse_args()
    run(args.client, args.sources.split(","))

6.3 · Ausführen

# Alle Quellen für Coca-Cola
python3 run_fetch.py --client coca-cola

# Nur GSC + GA4 (kein Ads)
python3 run_fetch.py --client coca-cola --sources gsc,ga4

# Anderer Client
python3 run_fetch.py --client example-client
7

// Claude Code PromptsCross-Source-Analysen

Cursor im Projektverzeichnis öffnen. Claude Code hat jetzt Zugriff auf alle JSON-Dateien. Diese Prompts direkt eingeben:

Paid-Organic Gap (wichtigste Analyse)

„Vergleiche die GSC-Queries aus data/gsc/coca-cola_queries.json mit den Google Ads Search Terms aus data/ads/coca-cola_search_terms.json. Finde: (1) Keywords wo wir Ads schalten, aber bereits stark organisch ranken – Einsparpotenzial. (2) Keywords mit Ads-Spend aber null organische Sichtbarkeit – Content-Gaps. (3) Organisch starke Queries ohne Ads-Unterstützung – Amplifikationschancen."

CTR-Optimizer

„Welche Seiten haben laut GSC viele Impressionen aber unterdurchschnittlichen CTR (unter 2%)? Vergleiche mit den GA4-Bounce-Rates für dieselben URLs. Sortiere nach Optimierungspotenzial."

AI Sichtbarkeits-Check

„Analysiere data/ai-visibility/coca-cola_ai_overviews.json. Welche unserer URLs werden in AI Overviews zitiert? Welche Competitor-Domains erscheinen häufiger? Was sind die häufigsten Themen in AI-Antworten wo wir NICHT zitiert werden?"

Content-Priorisierung

„Gruppiere die GSC-Queries nach Themen-Clustern. Zeige pro Cluster: Gesamtimpressionen, durchschnittliche Position, Klicks. Welche Cluster haben hohe Impressionen aber Position > 10? Das sind die Content-Investitionsprioritäten."

// ZusammenfassungZeitaufwand realistisch

PhaseEinmaligPro neuer ClientMonatlich
Google Cloud Setup~30 Min
Google Ads OAuth~30 Min + 48h Wartezeit
Python + Scripts~20 Min
Client Config + Properties~10 Min
Daten holen~5 Min
Analyse mit Claude Code~15–30 Min
Empfohlene Reihenfolge: Erst GSC allein testen → GA4 dazu → dann Ads → dann AI Visibility. Jede Stufe liefert bereits eigenständig Wert.