Über die in öffentlichen Google-Ads-Benchmarks beobachteten Konten hinweg übersieht die manuelle Analyse eines Suchanfragenberichts 60 bis 80 % der versteckten Negatives nach 30 Minuten Eyeballing durch einen erfahrenen PPC Manager. Und die Kosten dieses Übersehens sind messbar: 14 bis 28 % des monatlichen Spends landen in irrelevanten Anfragen, die niemand in den SQR-Top-50 sieht (offizielle Google-Ads-Dokumentation zu Negatives). Es ist typischerweise der vernachlässigte Hebel, der das CPA-/Quality-Score-Verhältnis eines reifen Kontos drückt.
Hier ist die Diagnose: Ein Mensch, der einen SQR scannt, macht visuelles Pattern Matching auf den Top-200-500-Zeilen, sortiert nach Kosten. Er übersieht (1) Long-Tail-Anfragen mit nur $3 bis $9 jeweils, die kumulativ aber 18 bis 26 % des Spends ausmachen, (2) gruppierbare semantische Variationen ('reviews', 'opinion', 'feedback', 'testimonial' = gleicher Intent) und (3) Cluster von Anfragen außerhalb kommerziellen Intents (Job, kostenloses Training, Definition, Niedrigpreis), die der Smart-Bidding-Algo nicht identifiziert, wenn das Conversion Tracking nach festem Wert läuft.
Dieser Guide liefert die reproduzierbare KI-Pipeline: GAQL-Extraktion des SQR, Embeddings (OpenAI oder sentence-transformers), DBSCAN Clustering, Intent- + Cost-Wasted-Scoring, CSV-Export für Google Ads Editor. Der gesamte Code ist in Python, läuft lokal, und das öffentliche Repo github.com/steerads/google-ads-negatives-ai enthält ein Dockerfile und einen Beispiel-n8n-Workflow. Für die Match-Types-Grundlage, die diese Pipeline konditioniert, siehe unseren Match-Types-Guide 2026. Unser Wasted Ad Spend Calculator schätzt das pro Monat verbrannte $-Volumen aus Broad-ohne-Negatives oder übermäßiger LP-Bounce.
Das Problem: 60 bis 80 % der Negatives in der manuellen Analyse versteckt
Die manuelle Analyse eines Suchanfragenberichts (SQR) ist eine der zeitintensivsten Aufgaben des PPC Managers. Auf einem Durchschnittskonto (5.000 bis 15.000 Anfragen / 30 Tage) rechnen Sie mit 45 Minuten bis 2 Stunden für einen sauberen Durchgang. Und selbst mit dieser investierten Zeit bleibt die Erkennungsrate relevanter Negatives strukturell durch kognitive Ermüdung und absteigende Kostensortierung begrenzt.
Drei systematische Blind Spots in der manuellen Analyse:
- Der Long Tail ist unsichtbar. Die ersten 50 Anfragen, sortiert nach Kosten, konzentrieren 35 bis 50 % des Spends. Der PPC Manager sieht sie. Aber die verbleibenden 4.950 Anfragen — jede zu $1 bis $9 — konzentrieren 50 bis 65 % des Gesamt-Spends und bleiben unerforscht. Da verstecken sich die wiederkehrenden irrelevanten Muster.
- Visuelles Pattern Matching übersieht semantische Variationen. Ein Mensch identifiziert 'reviews' als Negatives-Kandidat. Aber 'opinion', 'testimonial', 'feedback', 'review' teilen denselben Intent und erscheinen in verschiedenen Anfragen. Ohne Embedding ist das Gruppieren unmöglich.
- Kein Cost-Wasted-Scoring. Eine Anfrage mit $27 Kosten / 0 Conversion über 30 Tage hat größere Auswirkung als eine Anfrage mit $4 Kosten / 0 Conversion — selbst wenn die zweite 6-mal häufiger erscheint. Menschen sortieren alphabetisch oder nach Rohkosten, selten nach Cost Wasted (cost / conversions).
Über die in öffentlichen Google-Ads-Benchmarks beobachteten Konten hinweg konvergiert das Verhältnis des durch KI-Clustering von Negatives wiedergewinnbaren Spends zu einem sehr reproduzierbaren Schwellenwert: 12 bis 22 % des monatlichen Spends nach 60 Tagen aktiver Pipeline. Auf einem Budget von $33.000/Monat sind das zwischen $4.000 und $7.300 zurückgewonnener Spend jeden Monat — nicht zurück zu Wettbewerbern, sondern wieder injiziert in konvertierende Anfragen. ROI vs. eingesparte PPC-Manager-Zeit übersteigt 25× für die Mehrheit der verarbeiteten Konten.
Die hier beschriebene KI-Pipeline ersetzt den manuellen Durchgang durch einen reproduzierbaren Workflow. Die erste Ausführung dauert 30 bis 45 Minuten (Setup + Run + Review). Folgende Ausführungen dauern 5 bis 15 Minuten (nur Sample-Review). Für die Audit-Basis, die dieser Automatisierung vorausgehen sollte, lesen Sie unsere Google Ads Audit-Checkliste.
5-Schritt-KI-Pipeline: vom Suchanfragenbericht zur Negatives-Liste
Die vollständige Pipeline verkettet 5 deterministische Schritte, jeder isoliert testbar. Architektur bewusst einfach, keine schwere ML-Abhängigkeit jenseits von scikit-learn und sentence-transformers / openai. Der finale Output ist ein CSV, der direkt in Google Ads Editor importierbar ist.
Suchanfragen-Pre-Processing: der zu oft übersprungene Schritt
Bevor irgendetwas embedded wird, konditioniert das SQR-Pre-Processing 30 bis 50 % der finalen Clustering-Qualität. Vier Transformationen, systematisch anzuwenden. Erster Schritt: Unicode- und Case-Normalisierung. Google Ads SQRs enthalten oft Phantom-Duplikate: 'Auto Quote', 'auto quote', 'auto quote' (Doppelleerzeichen), 'auto-quote' erscheinen als 4 verschiedene Anfragen, obwohl es dasselbe ist. Wenden Sie unicodedata.normalize('NFKC', s).strip().lower() plus eine Regex \s+ -> ' ' an, um diese Duplikate in eine einzige Zeile mit aggregierten Kosten und Klicks zusammenzuführen. Auf einem durchschnittlichen US-Konto reduziert dieser Schritt das Anfragenvolumen um 8 bis 14 % ohne Informationsverlust.
Zweiter Schritt: intelligente Deduplizierung. Über die einfache Normalisierung hinaus sollte die Deduplizierung morphologische Varianten (Singular/Plural, Maskulin/Feminin, Akzente) bei Bedarf behandeln. Für das Clustering ist das Behalten roher Varianten meist nützlicher (das Embedding gruppiert sie mechanisch), aber für den finalen Negativ-Export vermeidet die Deduplizierung auf der representative_query des Clusters, dasselbe Negativ 5-mal vorzuschlagen. Dritter Schritt: Filtern von One-Shot-Anfragen mit niedrigen Kosten. Eine Anfrage, die einmal über 30 Tage mit $1,30 Kosten erscheint, verdient kein Embedding (es ist reines Rauschen). Eine Vorfilterung auf clicks >= 1 AND cost >= 1 vermeidet die Verschmutzung des Clusterings mit 25-40 % unreduzierbarem Rauschen.
Vierter Schritt: PII- und Sensitive-Term-Erkennung. Einige Anfragen enthalten Telefonnummern, E-Mails oder Eigennamen von Nutzern (versehentlich in die Suchleiste statt in die URL eingegeben). Diese Anfragen haben kein analytisches Interesse, und ihre Verarbeitung über OpenAI würde DSGVO-Probleme aufwerfen. Vorfiltern via Regex und NIEMALS an eine externe API senden. Auf den aggregierten Google-Ads-Daten 2025-2026 machen diese Anfragen 0,3 bis 1,2 % des SQR aus — niedrig im Volumen, aber kritisch in der Compliance.
[Google Ads API / CSV export]
|
v Step 1 — SQR extraction (GAQL or CSV)
[search_terms.csv : query, clicks, cost, conv]
|
v Step 2 — embeddings (OpenAI or ST)
[embeddings.npy : 384/1536 dim matrix]
|
v Step 3 — DBSCAN or HDBSCAN clustering
[queries_clustered.csv : query, cluster_id]
|
v Step 4 — intent + cost wasted scoring
[clusters_scored.csv : cluster, waste_score, intent_score]
|
v Step 5 — filtering + match type + export
[negatives_export.csv : ready for Google Ads Editor]
Hier ist das Python-Skelett des Haupt-Runners. Der vollständige Code (mit Error Handling, Logs, CLI-Parametern) ist im öffentlichen Repo.
# main.py — full pipeline in 5 steps
import pandas as pd
import numpy as np
from embeddings import embed_queries
from clustering import cluster_dbscan
from scoring import score_clusters
from export import export_negatives_csv
def main(sqr_path: str, output_path: str, backend: str = "sentence-transformers"):
# Step 1 — SQR loading
df = pd.read_csv(sqr_path)
df = df[df["clicks"] >= 1] # filter queries with no click
print(f"Loaded {len(df)} queries")
# Step 2 — embeddings
embeddings = embed_queries(df["search_term"].tolist(), backend=backend)
print(f"Embeddings shape: {embeddings.shape}")
# Step 3 — clustering
df["cluster_id"] = cluster_dbscan(embeddings, eps=0.15, min_samples=5)
n_clusters = df["cluster_id"].nunique() - (1 if -1 in df["cluster_id"].values else 0)
print(f"Found {n_clusters} clusters")
# Step 4 — scoring
clusters_scored = score_clusters(df, whitelist_path="whitelist.txt")
# Step 5 — export
export_negatives_csv(clusters_scored, output_path,
min_cluster_size=3, min_waste_score=30)
print(f"Exported negatives to {output_path}")
if __name__ == "__main__":
main(
sqr_path="data/search_terms.csv",
output_path="output/negatives_export.csv",
backend="sentence-transformers", # or "openai"
)
Jeder Schritt produziert ein persistiertes Artefakt (CSV oder .npy). Das erleichtert das Debug: Wenn das Clustering zu viel Rauschen produziert, können Sie auf Schritt 3 iterieren, ohne Embeddings neu auszuführen (teuer in API-Calls). Vgl. unseren Python Google Ads API Automation Guide für OAuth-Setup und detaillierte GAQL-Extraktion.
Embeddings: OpenAI text-embedding-3 vs. sentence-transformers
Embedding ist der kritische Schritt. Eine vektorisierte Anfrage erlaubt das Messen der semantischen Ähnlichkeit zwischen 'auto insurance quote' und 'car insurance rate' — selbst bei null gemeinsamen Wörtern. Ohne Embedding fällt das Clustering auf Token Matching zurück und übersieht 70 % der relevanten Gruppierungen.
Zwei relevante Backends 2026: OpenAI text-embedding-3-small (gehostet, 1536 Dim, kostenpflichtig pro Nutzung) und sentence-transformers all-MiniLM-L6-v2 oder multilingual-e5-base (lokal, 384 oder 768 Dim, kostenlos). Die Wahl hängt von Volumen und Datensensibilität ab.
OpenAI-Variante — produktionsreif, batch-optimiert:
# embeddings.py — OpenAI backend
from openai import OpenAI
import numpy as np
import os
def embed_queries_openai(queries: list[str], batch_size: int = 100) -> np.ndarray:
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
all_embeddings = []
for i in range(0, len(queries), batch_size):
batch = queries[i : i + batch_size]
response = client.embeddings.create(
model="text-embedding-3-small",
input=batch,
encoding_format="float",
)
embeddings = [item.embedding for item in response.data]
all_embeddings.extend(embeddings)
return np.array(all_embeddings, dtype=np.float32)
sentence-transformers-Variante — lokal, null Kosten:
# embeddings.py — local sentence-transformers backend
from sentence_transformers import SentenceTransformer
import numpy as np
def embed_queries_st(queries: list[str], model_name: str = "all-MiniLM-L6-v2") -> np.ndarray:
model = SentenceTransformer(model_name)
embeddings = model.encode(
queries,
batch_size=64,
show_progress_bar=True,
normalize_embeddings=True, # important for cosine
)
return embeddings.astype(np.float32)
def embed_queries(queries: list[str], backend: str = "sentence-transformers") -> np.ndarray:
if backend == "openai":
return embed_queries_openai(queries)
elif backend == "sentence-transformers":
return embed_queries_st(queries, model_name="paraphrase-multilingual-MiniLM-L12-v2")
else:
raise ValueError(f"Unknown backend: {backend}")
Feld-Benchmark: Auf einem US-E-Commerce-Konto mit 8.000 Anfragen liegt das Cluster-Qualitäts-Delta zwischen OpenAI und e5-base bei 6 bis 9 % Präzision (Messung: # gültige Negatives / # Vorschläge). Auf English-only MiniLM v1 steigt das Delta auf 12 bis 18 % — daher die Wahl von paraphrase-multilingual-MiniLM-L12-v2 für Nicht-EN. Für ein EN-only-Konto ist das der beste Kosten/Qualitäts-Kompromiss. Offizielle Dokumentation zu OpenAI Embeddings.
text-embedding-3-large vs. text-embedding-3-small: wann rechtfertigt large den Aufpreis? Drei konkrete Fälle, in denen text-embedding-3-large (3072 Dim, $0,13 / 1M Token, 6,5-mal teurer als small) die Investition rechtfertigt. Fall 1: feiner Intent in spezialisierten Fachsektoren (medizinisch, juristisch, Engineering), wo die Nuance zwischen 'tax attorney' und 'tax-efficient attorney' das Intent-Scoring verändert. Das large-Modell erfasst 4 bis 7 % zusätzliche messbare Präzision auf der Validierungs-Kohorte. Fall 2: gemischt mehrsprachig (EN + ES + FR im selben Konto), wo die Cross-Language-Robustheit von large vermeidet, die Pipeline in drei separate Pässe zu splitten. Fall 3: sehr hohes Volumen (50.000+ Anfragen pro Monat), wo zusätzliche marginale Kosten unter $1 pro Lauf bleiben, ohne signifikante P&L-Auswirkung. Außerhalb dieser drei Fälle bleibt text-embedding-3-small der richtige Default für ein US-Mid-Market-Konto.
OpenAI-API-Kostenanalyse an einem realen Fall. Für ein Konto, das 8.000 Anfragen mit 4 bis 8 Wörtern jeweils wöchentlich verarbeitet (Durchschnitt 32 Token pro Anfrage, also 256.000 Token pro Lauf), beträgt der small-Run-Cost 256.000 / 1.000.000 x $0,02 = $0,005. Über 52 jährliche Läufe ergibt das etwa $0,27 pro Konto pro Jahr. Bei large werden die Kosten zu 256.000 / 1.000.000 x $0,13 = $0,033 pro Lauf, etwa $1,72 jährlich. In beiden Fällen ist der OpenAI-API-Cost marginal vs. eingesparter PPC-Manager-Zeit. Klassische Falle: Lauf ohne Batching (1 Anfrage pro Call statt 100 pro Batch), was die Kosten um Faktor 8 bis 12 multipliziert aufgrund wiederholter fixer Per-Request-Gebühren. Immer mindestens 50-100 Anfragen pro Call batchen.
DBSCAN Clustering: warum nicht K-means
K-means ist der bekannteste Clustering-Algorithmus, aber für Google-Ads-Suchanfragen die falsche Wahl. Drei technische Gründe:
- K-means erfordert das Festlegen von K im Voraus. Wie viele irrelevante Anfrage-Cluster existieren in Ihrem Konto? Niemand weiß es vor der Analyse. K-means erzwingt das Raten — und ein schlechtes K produziert entweder zu breite Cluster (gemischte Intents) oder zu feine (Über-Fragmentierung).
- K-means weist jeden Punkt einem Cluster zu. Aber 30 bis 50 % der Anfragen sind Rauschen (eindeutige Anfragen ohne Äquivalent). DBSCAN identifiziert sie als Rauschen (Cluster -1), anstatt sie in einen fiktiven Cluster zu zwingen. Ergebnis: sauberere Cluster.
- K-means nimmt sphärische Cluster mit gleicher Dichte an. Irrelevante Anfrage-Cluster haben sehr variable Dichten (ein sehr dichter 'kostenlos'-Cluster + ein diffuser 'Wettbewerbervergleich'-Cluster). DBSCAN behandelt diese Varianz, K-means nicht.
DBSCAN (Density-Based Spatial Clustering of Applications with Noise) nimmt zwei Parameter: eps (Nachbarschaftsradius) und min_samples (min. Punkte zum Bilden eines Clusters). Es identifiziert dichte Zonen im Embedding-Raum und gruppiert nahe Punkte.
# clustering.py — DBSCAN
from sklearn.cluster import DBSCAN
import numpy as np
def cluster_dbscan(embeddings: np.ndarray, eps: float = 0.15, min_samples: int = 5) -> np.ndarray:
# Cosine distance for normalized embeddings
clustering = DBSCAN(
eps=eps,
min_samples=min_samples,
metric="cosine",
n_jobs=-1,
)
labels = clustering.fit_predict(embeddings)
return labels
def cluster_hdbscan(embeddings: np.ndarray, min_cluster_size: int = 5) -> np.ndarray:
import hdbscan
clustering = hdbscan.HDBSCAN(
min_cluster_size=min_cluster_size,
metric="euclidean", # HDBSCAN doesn't support direct cosine
cluster_selection_method="eom",
)
labels = clustering.fit_predict(embeddings)
return labels
Kalibrierung des eps-Parameters: Das ist der Cosine-Similarity-Schwellenwert, unter dem zwei Anfragen als Nachbarn betrachtet werden. Kleinerer eps = feinere Cluster. Feld-Benchmark: bei eps=0.15 starten. Wenn mehr als 70 % der Anfragen als Rauschen (Cluster -1) herauskommen, auf 0,20 erhöhen. Wenn Cluster zu breit sind ('Service'-Cluster, der B2B und B2C mischt), auf 0,12 senken.
HDBSCAN als Alternative, falls DBSCAN schlecht kalibrierte Cluster produziert. HDBSCAN erkennt automatisch lokale Dichte und benötigt kein eps. Robuster auf heterogenen Datensätzen, aber langsamer und schwerer zu debuggen.
Vor dem Scoring die erhaltenen Cluster mit UMAP in 2D visualisieren. umap-learn reduziert Embeddings von 384 Dim auf 2 Dim für einen lesbaren Scatter Plot. Sie sehen sofort, ob das Clustering sauber ist (klare, getrennte Cluster) oder verrauscht (überlappende Cluster). Wenn verrauscht, eps tunen, bevor Sie fortfahren. 5 Minuten investiert sparen 30 Minuten unnützes Scoring.
Cluster-Validierung: drei Metriken jenseits der UMAP-Visualisierung
Die UMAP-Visualisierung ist nützlich, aber subjektiv. Um die Clustering-Qualität quantitativ zu validieren, drei objektive Metriken, vor dem Scoring systematisch zu berechnen. Metrik 1: Silhouette-Score. Implementiert in sklearn.metrics.silhouette_score, misst diese Metrik, wie viel jeder Punkt näher an seinem eigenen Cluster ist als an anderen Clustern. Score zwischen -1 (katastrophal) und +1 (perfekt). Silhouette über 0,3 auf dem vollständigen Datensatz indiziert ausnutzbares Clustering; unter 0,15 muss eps neu getunt werden. Über die in öffentlichen Google-Ads-Benchmarks beobachteten Konten hinweg erreicht ein US-Mid-Size-E-Commerce-Konto typischerweise 0,32 bis 0,48 Silhouette in sentence-transformers und 0,38 bis 0,55 in OpenAI text-embedding-3-small.
Metrik 2: Rauschprozentsatz. Verhältnis (labels == -1).mean() zählen. Ein gutes DBSCAN-Clustering auf Google-Ads-SQRs sollte zwischen 25 und 45 % Rauschen haben (Anfragen, nicht einem Cluster zugeordnet). Unter 25 % ist eps zu breit und Cluster sind über-merged. Über 60 % ist eps zu strikt und die Mehrheit der Anfragen wird abgelehnt. Diese Metrik ist kostenlos zu berechnen und dient als Guardrail gegen degenerierte Konfigurationen.
Metrik 3: Mediane Cluster-Größe. np.median([size for _, size in clusters_size]) berechnen. Ein ausnutzbares Clustering produziert mediane Cluster-Größen zwischen 4 und 12 Anfragen. Über 20 sind Cluster zu breit und mischen unterschiedliche Intents. Unter 4 sind sie zu fein und das Scoring wird instabil. Wenn die mediane Größe außerhalb dieses Fensters liegt, min_samples (DBSCAN) oder min_cluster_size (HDBSCAN) anpassen, bevor Sie die Pipeline fortsetzen. Auf Produktions-Iterationen erkennt das Monitoring dieser drei Metriken und das Loggen ihres Drifts stille Pipeline-Regressionen (eine Embedding-API-Änderung, Drift in Quell-Anfragen), bevor vorgeschlagene Negatives beeinträchtigt werden.
Scoring: Intent-Relevanz + Cost Wasted
Sobald die Anfragen geclustert sind, müssen Sie jeden Cluster scoren, um zu entscheiden, welche Negatives-Kandidaten sind. Das Scoring kombiniert zwei Dimensionen: (1) Cost Wasted (wie viel Spend ohne Conversion verbrannt wurde) und (2) Intent-Score (wie weit der Cluster von Ihrem kommerziellen Ziel-Intent entfernt ist).
Cost Wasted ist trivial zu berechnen: Kostensumme / max(Conversion-Summe, 0,1) pro Cluster. Je höher das Verhältnis, desto stärker der Negatives-Kandidat.
Intent-Score ist subtiler. Wir vergleichen die mittlere Cosine-Similarity des Clusters mit einer Whitelist von Ziel-Keywords (Ihre Markenbegriffe + Flagship-Produkte + starke Kaufintents). Wenn die mittlere Similarity des Clusters zur Whitelist über 0,65 liegt, ist es wahrscheinlich ein relevanter Cluster (NICHT auszuschließen). Wenn unter 0,30, ist es ein Cluster fern vom kommerziellen Intent = starker Negatives-Kandidat.
# scoring.py — intent + cost wasted scoring
import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def score_clusters(df: pd.DataFrame, whitelist_path: str) -> pd.DataFrame:
# Load whitelist (1 keyword per line)
with open(whitelist_path) as f:
whitelist_keywords = [line.strip() for line in f if line.strip()]
# Embed the whitelist
from embeddings import embed_queries
whitelist_emb = embed_queries(whitelist_keywords, backend="sentence-transformers")
# Aggregate by cluster
cluster_stats = []
for cluster_id, group in df.groupby("cluster_id"):
if cluster_id == -1:
continue # ignore noise
cost = group["cost"].sum()
conv = group["conversions"].sum()
clicks = group["clicks"].sum()
size = len(group)
# waste_score: cost per conversion (0.1 floor to avoid division by 0)
waste_score = cost / max(conv, 0.1)
# intent_score: mean cosine similarity with whitelist
cluster_emb = np.stack(group["embedding"].values)
sim_matrix = cosine_similarity(cluster_emb, whitelist_emb)
intent_score = float(sim_matrix.max(axis=1).mean())
# representative example (most central query in cluster)
centroid = cluster_emb.mean(axis=0)
distances = np.linalg.norm(cluster_emb - centroid, axis=1)
representative_idx = distances.argmin()
representative_query = group.iloc[representative_idx]["search_term"]
cluster_stats.append({
"cluster_id": cluster_id,
"size": size,
"cost": round(cost, 2),
"conversions": round(conv, 2),
"clicks": clicks,
"waste_score": round(waste_score, 2),
"intent_score": round(intent_score, 3),
"representative_query": representative_query,
"negative_candidate": waste_score > 30 and intent_score < 0.30,
})
result = pd.DataFrame(cluster_stats)
return result.sort_values("waste_score", ascending=False)
Lesart der Output-Tabelle: nach waste_score absteigend sortieren, dann auf intent_score < 0.30 UND size >= 3 filtern. Dieses Trio identifiziert Cluster, die (1) Spend verbrennen, (2) fern vom kommerziellen Intent sind und (3) genug Anfragen haben, um ein Negativ zu rechtfertigen (kein One-Shot).
Schwellenwert-Benchmarks:
waste_score >= 30(mindestens $32 Kosten ohne Conversion) — entspricht dem Relevanz-Schwellenwert auf der Mehrheit der Konten.intent_score < 0.30(Cosine-Similarity mit Whitelist unter 30 %) — darüber Risiko falsch-negativ.size >= 3(mindestens 3 Anfragen im Cluster) — unter 3 ist es Rauschen oder Long Tail, Fall für Fall behandeln.
Diese Schwellenwerte sind Ausgangspunkte. Anpassen basierend auf Ihrem manuellen Sample-Feedback nach 2-3 Iterationen.
CSV-Export bereit für Google Ads Editor
Der finale Output muss direkt in Google Ads Editor importierbar sein — sonst verlieren Sie 30 Minuten beim manuellen Reformatieren. Erwartetes Format: UTF-8-CSV, spezifische Spalten, klarer Match Type, expliziter Action ("Add" für Hinzufügung).
# export.py — Google Ads Editor CSV generation
import pandas as pd
def export_negatives_csv(
clusters_scored: pd.DataFrame,
output_path: str,
min_cluster_size: int = 3,
min_waste_score: float = 30,
max_intent_score: float = 0.30,
) -> None:
# Filter candidate clusters
candidates = clusters_scored[
(clusters_scored["size"] >= min_cluster_size)
& (clusters_scored["waste_score"] >= min_waste_score)
& (clusters_scored["intent_score"] < max_intent_score)
]
rows = []
for _, cluster in candidates.iterrows():
# Determine match type based on cluster dispersion
# (parameterize more finely in prod: simplification here)
match_type = "Phrase match" if cluster["size"] <= 8 else "Broad match"
rows.append({
"Action": "Add",
"Campaign": "ALL", # or cluster["campaign"] if available
"Ad group": "", # empty = campaign level
"Keyword": cluster["representative_query"],
"Match type": match_type,
"Status": "Enabled",
"Comment": f"AI cluster #{cluster['cluster_id']} | "
f"size={cluster['size']} | "
f"waste=${cluster['waste_score']} | "
f"intent={cluster['intent_score']}",
})
out_df = pd.DataFrame(rows)
out_df.to_csv(output_path, index=False, encoding="utf-8")
print(f"Wrote {len(out_df)} negative candidates to {output_path}")
Google Ads Editor Importprozedur: Google Ads Editor > File > Import > From CSV. Das Tool erkennt Spalten, validiert das Match-Type-Format und schlägt einen visuellen Diff vor dem Push vor. Diff prüfen (Sample 30-50 Zeilen), validieren, dann Post Changes. Für offizielle Google Ads Editor Dokumentation siehe support.google.com/google-ads/answer/2475106.
Match Type — Feldheuristik:
- Phrase Match für sehr homogene Cluster (Größe 3-8 Anfragen, kurze ähnliche Ausdrücke). Präziser Match, geringes Risiko, versehentlich eine relevante Anfrage zu blockieren.
- Broad Match für breite Konzepte (Größe über 15, variierte Anfragen rund um einen einzigen Intent). Breiter, aber vergessen Sie nicht, nach dem Push zu überwachen, um exzessive Blockierungen zu erkennen.
- Exact Match selten relevant bei AI-Negatives — wir behandeln eher Konzepte als exakte Anfragen.
Laden Sie das CSV NIEMALS direkt ohne Human Review beim ersten Lauf hoch. Sample 30-50 zufällige Zeilen, prüfen Sie, dass kein Marken- / Flagship-Produkt / Ziel-Keyword erscheint, validieren Sie den Match Type. Wenn mehr als 10 % des Samples falsch positiv sind, Schwellenwerte anpassen (min_waste_score höher, max_intent_score niedriger) und neu ausführen. Sobald die Pipeline über 2-3 Iterationen validiert ist (Fehlerrate unter 5 %), im Auto-Modus automatisierbar.
Typischer ROI: wie viel Spend Sie zurückgewinnen
Praktische Frage: Wie viel zahlt diese KI-Pipeline vs. manueller Analyse zurück? Antwort in Feldzahlen, gemessen über die in öffentlichen Google-Ads-Benchmarks beobachteten Konten.
Lesart: Die KI-Pipeline ist nicht magisch bei der Präzision (ein aufmerksamer Mensch ist genauso gut). Ihr Vorteil liegt im Recall — sie identifiziert 75 bis 88 % der relevanten Negatives vs. 20 bis 35 % für einen Menschen in 30 Minuten. Und die PPC-Manager-Zeit sinkt nach dem initialen Setup von 30 Min auf 5-15 Min pro Ausführung. Der echte Gewinn ist kumulativ: über 12 Monate sind das 4 bis 6 Stunden eingesparte PPC-Manager-Zeit UND 12 bis 22 % besser genutzten Spends.
Quantifizierter Benchmark: Auf einem Konto von $33.000/Monat ergibt das Zurückgewinnen von 15 % des Spends = $5.000/Monat umgeleitet zu konvertierenden Anfragen. Bei iso-CPA sind das 5.000 / CPA zusätzliche Bottom-Funnel-Conversions jeden Monat. Über 12 Monate typischerweise zwischen 230 und 380 zusätzliche Conversions ohne Budgeterhöhung. ROI vs. initialer Investition (45 Min Setup + Embedding API-Key) übersteigt 50×.
Das Schlüsselverhältnis: Recall geteilt durch investierte Zeit. Für 2 h manuelle Analyse beträgt das Verhältnis etwa 0,25 (50 % Recall / 2 h). Für die KI-Pipeline beträgt das Verhältnis etwa 6 (80 % Recall / 0,2 h nach Setup). Das ist 24-mal effizienter auf der Metrik, die wirklich zählt — wie viel verschwendeter Spend Sie pro investierter PPC-Manager-Stunde identifizieren. Und dieses Verhältnis verbessert sich über Ausführungen weiter: Bei der 5. Iteration schrumpft das manuelle Sample auf 15-25 zu prüfende Negatives (vs. 60-80 beim ersten Lauf), weil wiederkehrende Muster von vorherigen Clustern absorbiert werden.
Praktische 60-Tage-Messung: Konten, die die Pipeline wöchentlich ausführen, konvergieren zu einem Steady State, in dem die Mehrheit der neuen Negatives aus neuen Mustern kommt (aufkommende Wettbewerber, saisonale Anfragen, semantische Audience-Verschiebungen). Die Pipeline erkennt diese neuen Muster innerhalb von 7 Tagen nach Erscheinen, vs. 30-60 Tage im manuellen Monitoring — was ein 23-53-Tage-Fenster verschwendeten Spends bei jedem aufkommenden Muster spart. Das ist der echte Moat von Embedding-basierter Automatisierung: Reaktionsgeschwindigkeit, nicht nur One-Shot-Recall.
Unsere Auto-Optimization-Engine bettet diese Pipeline im Managed-Modus ein: automatische GAQL-Extraktion, gehostete Embeddings, DBSCAN-Clustering, Scoring + Filterung und wöchentliche Vorschläge, die mit 1 Klick validierbar sind. Für Konten, die ohne Coding industrialisieren möchten. Siehe auch unsere 10 Google Ads Scripts für native Skript-Automatisierung und unseren n8n + Google Ads Guide, um die Pipeline als self-hosted Workflow zu planen. Die Komplementaritäten zwischen diesen drei Winkeln — KI-Pipeline, native Skripte, self-hosted n8n — sind in unserer Sammlung von ChatGPT Google Ads Prompts detailliert.
Häufige Fehler bei der Industrialisierung
Fünf Fehler wiederholen sich beim Produktivsetzen von KI-Negatives-Google-Ads-Pipelines. Jeder erzeugt entweder falsche Negatives (schlecht targetierte Negatives, die relevanten Traffic blockieren) oder falsche Positive (übersehene Negatives). Diagnose und direkter Fix.
1. Pipeline ohne Marken- und Ziel-Produkt-Whitelist ausführen. Diagnose: Die Pipeline schlägt Negatives vor, die Ihre Markenbegriffe oder Ihre Flagship-Produktnamen enthalten, weil sie semantisch schlecht von irrelevanten Anfragen differenziert sind. Fix: eine whitelist.txt mit mindestens Markenvarianten (einfach + zusammengesetzte Wörter), 10 bis 20 Ziel-Produktnamen und starken kommerziellen Begriffen pflegen. Diese Whitelist dient dem Intent-Scoring (intent_score) und blockiert den Export jedes Clusters, dessen representative_query partiell mit der Whitelist übereinstimmt.
2. Exact Match und Phrase Match im Negativ-Export verwechseln. Diagnose: Den Cluster als Exact Match auf der representative_query zu exportieren, blockiert nur die exakte Anfrage (10-15 % des Clusters) und lässt 85-90 % des Cost Wasted weiterlaufen. Fix: Phrase Match als Default für kohärente Cluster verwenden und Broad Match für breite Konzepte. Vor dem Push testen, indem Sie den Keyword Planner auf das vorgeschlagene Negativ abfragen: Wenn das geschätzte Volumen das des Original-Clusters um Faktor 5 übersteigt, ist der Match Type zu breit.
3. Pipeline zu häufig ausführen und Rauschen erzeugen. Diagnose: Eine tägliche Pipeline produziert dutzende Vorschläge pro Tag, von denen 60-70 % Reformulierungen vorheriger Vorschläge sind. Validierungsmüdigkeit drängt das Team, alles ohne Review zu validieren. Fix: wöchentlich (Montagmorgen) ausführen, nicht täglich. Das 7-Tage-Fenster stabilisiert Muster und vermeidet vorzeitige Entscheidungen über One-Shot-Anfragen. Für Konten mit sehr hoher Veränderungsfrequenz (starke Saisonalität) maximal zweiwöchentlich, niemals täglich.
4. Kleine Cluster mit hohem Waste ignorieren. Diagnose: Der Filter min_cluster_size: 3 schließt systematisch 1-2-Anfragen-Cluster aus, die hohen Waste tragen können (eine Anfrage mit $86 ohne Conversion, zum Beispiel). Diese isolierten Muster rutschen unter dem Pipeline-Radar durch. Fix: einen zweiten Pass hinzufügen, der individuelle Anfragen über waste_score = 60 unabhängig von der Cluster-Mitgliedschaft vorschlägt. Diese individuellen Vorschläge sind riskanter zur Auto-Validierung, also vor dem Export manuell prüfen.
5. Performance nach Anwendung nicht messen. Diagnose: Negatives werden hochgeladen, die Pipeline läuft auf Autopilot, aber niemand prüft, ob CPA und ROAS sich tatsächlich verbessern. Fix: einen Pipeline-Health-Indikator tracken: delta_cpa_30d_post_negatives (CPA-Variation in den 30 Tagen nach dem Push von N Negatives). Wenn die Variation null oder negativ ist, waren die vorgeschlagenen Negatives marginal. Schwellenwerte min_waste_score und max_intent_score anpassen, um Cluster mit höherem Impact zu targetieren. Über die in öffentlichen Google-Ads-Benchmarks beobachteten Konten hinweg erscheint eine messbare Verbesserung typischerweise in den ersten 3 bis 5 Iterationen und stabilisiert sich dann.
Für Konten, die ohne eigene Pipeline-Ausführung industrialisieren möchten, läuft unser Auto-Optimization-Modul die Embeddings + Clustering Pipeline wöchentlich auf Ihrem Konto, schlägt gültige Kandidaten-Negatives via UI vor und wendet sie nach Review an. OAuth-Verbindung in 2 Minuten, erste Analyse in 5 Minuten. Öffentliches Repo github.com/steerads/google-ads-negatives-ai verfügbar für diejenigen, die Self-Hosting bevorzugen, mit Dockerfile und Beispiel-n8n-Workflow.
Quellen
Offizielle Quellen für diesen Leitfaden:
FAQ
Muss ich OpenAI verwenden oder kann ich 100 % Open-Source bleiben?
Sie können 100 % Open-Source bleiben. sentence-transformers (all-MiniLM-L6-v2 oder multilingual-e5-base Modell) läuft lokal auf CPU, ohne API-Key oder Kosten, mit ausreichender Qualität, um Suchanfragen zu clustern. Der beobachtbare Unterschied vs. OpenAI text-embedding-3-small: -8 bis -14 % Präzision auf feinen Clustern (Trennung von kommerziellem 'Angebot' vs. juristischem 'Angebot'), aber $0 API-Kosten. Für Konten mit weniger als 5.000 Anfragen/Monat reicht sentence-transformers aus. Darüber hinaus oder wenn Sie mehrsprachige Inhalte mit Akzenten verarbeiten, bietet text-embedding-3-small ein besseres Qualität-/Aufwandsverhältnis. Die Pipeline unterstützt beide Backends via einer Umgebungsvariablen.
Wie viel Anfragen-Volumen ist mindestens nötig für zuverlässiges Clustering?
Praktischer Schwellenwert: minimum 500 Anfragen im Analysefenster (typischerweise 30 Tage). Darunter hat DBSCAN nicht genug Dichte, um stabile Cluster zu identifizieren, und die meisten Anfragen kommen als Rauschen heraus. Sweet Spot: 2.000 bis 10.000 Anfragen über 30 Tage. Über 10.000 nach Kampagne aufteilen, um zu vermeiden, dass zu unterschiedliche Intents gemischt werden (B2B + B2C im selben Clustering = Rauschen). Wenn Ihr Konto weniger als 500 Anfragen/30 T hat, das Fenster auf 60 oder 90 Tage verlängern.
DBSCAN oder HDBSCAN: was in der Praxis wählen?
HDBSCAN ist im Allgemeinen für Google Ads Suchanfragen überlegen: Es behandelt Cluster mit variabler Dichte, was der Realität entspricht (ein sehr dichter 'kostenlos'-Cluster + ein diffuser 'Wettbewerber'-Cluster). DBSCAN erfordert das Festlegen eines einzigen eps-Parameters für den gesamten Datensatz, was Kompromisse erzwingt. DBSCAN bleibt jedoch einfacher zu parametrieren und schneller bei kleinen Volumina (unter 5.000 Anfragen). Empfehlung: mit DBSCAN bei eps um 0,15 und min_samples 5 starten, dann zu HDBSCAN wechseln, wenn Cluster schlecht kalibriert aussehen. Die Pipeline unterstützt beide via einer Config-Variable.
Wie bewerte ich die Qualität der von der Pipeline vorgeschlagenen Negatives vor dem Upload?
Drei obligatorische Checks vor jedem Google Ads Editor Upload. (1) Manuelles Sample: 30 bis 50 zufällige Negatives prüfen, Validierungsrate über 90 % anstreben. (2) Whitelist: prüfen, dass kein Markenbegriff, Flagship-Produkt oder Ziel-Keyword in der Liste erscheint (das Skript muss eine Whitelist als Input nehmen). (3) Match Type: prüfen, dass der exportierte Match Type zum Intent passt (Phrase Match für genaue Ausdrücke, Broad Match für Konzepte). Wenn weniger als 90 % Validierung im manuellen Sample, Scoring-Schwellenwerte (cost_min, cluster_size_min) anpassen, anstatt as-is hochzuladen. 2 bis 3 Mal iterieren, bevor Sie Auto-Mode anstreben.
Kann diese Pipeline wöchentlich auf n8n oder Cloud Run automatisiert werden?
Ja, und das ist das Endziel der Industrialisierung. Die Python-Pipeline läuft in unter 3 Minuten auf 5.000 Anfragen (lokale CPU) oder unter 60 Sekunden via OpenAI Batch Embeddings + GPU DBSCAN. Sie können sie als Cron auf Cloud Run, Lambda oder als n8n-Workflow planen. Empfohlenes Muster: wöchentlicher Lauf (Montagmorgen), Output zu einem geteilten Google Sheet, manuelle Sample-Validierung, Upload via Google Ads Editor (oder via Google Ads API direkt, wenn Pipeline-Confidence hoch ist). Das Repo github.com/steerads/google-ads-negatives-ai enthält ein Dockerfile und einen Beispiel-n8n-Workflow.