SteerAds
Google AdsTutorielOptimisation

AI Záporná klíčová slova: discovery a clustering

Manuální analýza search query reportu přehlédne 60 až 80 % skrytých negativních klíčových slov. Zde je reprodukovatelný AI pipeline: embeddings OpenAI nebo sentence-transformers, clustering DBSCAN, skórování intent + cost wasted, export CSV pro Google Ads Editor. Bonus: open-source Python repo.

Andrew
AndrewSmart Bidding & Automation Lead
···9 min čtení

Na účtech sledovaných v agregovaných benchmarcích Google Ads manuální analýza search query reportu přehlédne 60 až 80 % skrytých negativních klíčových slov po 30 minutách eyballingu zkušeným PPC manažerem. A náklady tohoto přehlédnutí jsou měřitelné: 14 až 28 % měsíčního spend končí u nerelevantních queries, které nikdo neuvidí v top 50 SQR (oficiální dokumentace Google Ads o negativních klíčových slovech). To je typicky přehlíženou pákou, která brzdí poměr CPA / Quality Score zralého účtu.

Diagnóza: člověk skenující SQR provádí vizuální pattern matching na prvních 200–500 řádcích seřazených podle nákladů. Přehlíží (1) queries z dlouhého ocasu, které váží jen 3 až 8 EUR každá, ale dohromady představují 18 až 26 % spend, (2) sémantické variace seskupitelné dohromady ('recenze', 'hodnocení', 'zkušenosti', 'názor' = stejný intent) a (3) clustery queries mimo komerční intent (práce, bezplatné vzdělávání, definice, nízkorozpočtové ceny), které Smart Bidding algoritmus neidentifikuje, pokud je sledování konverzí s fixní hodnotou.

Tento průvodce poskytuje reprodukovatelný AI pipeline: GAQL extrakce SQR, embeddings (OpenAI nebo sentence-transformers), clustering DBSCAN, skórování intent + cost wasted, export CSV pro Google Ads Editor. Veškerý kód je v Pythonu, funguje lokálně a veřejný repozitář github.com/steerads/google-ads-negatives-ai obsahuje Dockerfile a příklad n8n workflow. Pro základy match types, které podmínkují tento pipeline, viz náš průvodce match types 2026. Náš kalkulátor plýtvání rozpočtem odhaduje € spálené/měsíc při broad bez negativních klíčových slov nebo nadměrném bounce LP.

Problém: 60 až 80 % skrytých negativních klíčových slov v manuální analýze

Manuální analýza search query reportu (SQR) je jedním z nejčasově náročnějších úkolů PPC manažera. Na průměrném účtu (5 000 až 15 000 queries / 30 dní) je potřeba 45 minut až 2 hodiny pro pečlivý průchod. A i s tímto investovaným časem zůstává míra detekce relevantních negativních klíčových slov strukturálně omezena kognitivní únavou a tříděním podle sestupných nákladů.

Tři systematické slepé úhly v manuální analýze:

  1. Dlouhý ocas je neviditelný. Prvních 50 queries seřazených podle nákladů koncentruje 35 až 50 % spend. PPC manažer je vidí. Ale zbývajících 4 950 queries — každá s 1 až 8 EUR — koncentruje 50 až 65 % celkového spend a zůstává neprozkoumáno. V tomto ocasu se skrývají opakující se nerelevantní vzory.
  2. Vizuální pattern matching přehlíží sémantické variace. Člověk identifikuje 'recenze' jako kandidáta na negativní klíčové slovo. Ale 'hodnocení', 'zkušenosti', 'názor', 'zpětná vazba' sdílejí stejný intent a appear v různých queries. Bez embeddingů není možné je seskupit.
  3. Žádné skórování cost wasted. Query s náklady 25 EUR / 0 konverzí za 30 dní má větší dopad než query s náklady 4 EUR / 0 konverzí — i když se ta druhá vyskytuje 6krát častěji. Člověk třídí podle abecedy nebo hrubých nákladů, zřídka podle cost wasted (náklady / konverze).
Insight — poměr negativních klíčových slov / spend :

Na účtech sledovaných v agregovaných benchmarcích Google Ads se poměr zotavitelného spend pomocí AI clusteringu negativních klíčových slov konverguje k velmi reprodukovatelnému prahu: 12 až 22 % měsíčního spend po 60 dnech aktivního pipeline. Na rozpočtu 30 000 EUR/měsíc je to 3 600 až 6 600 EUR zotaveného spend každý měsíc — ne ke konkurentům, ale přesměrovaného k queries, které konvertují. ROI vs ušetřený čas PPC manažera je vyšší než 25× pro většinu ošetřených účtů.

Zde popsaný AI pipeline nahrazuje manuální průchod reprodukovatelným workflow. První spuštění trvá 30 až 45 minut (setup + spuštění + review). Následná spuštění trvají 5 až 15 minut (pouze review vzorku). Pro auditní základnu, která musí předcházet této automatizaci, přečtěte naši checklist auditu Google Ads.

AI pipeline v 5 krocích: query report na seznam negativních klíčových slov

Kompletní pipeline řetězí 5 deterministických kroků, každý testovatelný izolovaně. Záměrně jednoduchá architektura, bez těžkých ML závislostí nad rámec scikit-learn a sentence-transformers / openai. Finální výstup je CSV přímo importovatelný do Google Ads Editor.

Pre-processing search queries: krok, který se příliš často přeskakuje

Před embeddováním čehokoli pre-processing SQR podmínkuje 30 až 50 % konečné kvality clusteringu. Čtyři transformace k systematické aplikaci. První krok: normalizace Unicode a velikosti písmen. SQR Google Ads často obsahují fantomové duplicity: 'Nabídka Pojištění', 'nabídka pojištění', 'nabídka pojištění' (dvojitá mezera), 'nabídka-pojištění' se zobrazují jako 4 různé queries, přestože reprezentují totéž. Aplikování unicodedata.normalize('NFKC', s).strip().lower() plus regex \s+ -> ' ' seskupí tyto duplicity do jediného řádku s agregovanými náklady a kliknutími. Na průměrném CZ/SK účtu tento krok snižuje objem queries o 8 až 14 % bez ztráty informací.

Druhý krok: inteligentní deduplikace. Nad rámec jednoduché normalizace musí deduplikace zpracovávat morfologické varianty (singulár/plurál, rod, diakritika) podle potřeby. Pro clustering je obecně užitečnější ponechat surové varianty (embedding je mechanicky seskupí), ale pro finální export negativních klíčových slov deduplikace na representative_query clusteru zabraňuje navrhování stejného negativního klíčového slova 5krát. Třetí krok: filtrování one-shot queries s nízkými náklady. Query, která se vyskytuje jednou za 30 dní s náklady 1,20 EUR, si nezaslouží embedding (to je čistý šum). Filtrování předem na clicks >= 1 AND cost >= 1 zabraňuje znečištění clusteringu 25–40 % neredukovatelného šumu.

Čtvrtý krok: detekce PII a citlivých výrazů. Některé queries obsahují telefonní čísla, e-maily nebo vlastní jména uživatelů (zadaná omylem do vyhledávacího pole místo URL). Tyto queries nemají žádnou analytickou hodnotu a jejich zpracování přes OpenAI by bylo problematické z hlediska GDPR. Filtrujte předem přes regex a NIKDY neodesílejte na externí API. V agregovaných datech Google Ads 2025–2026 tento typ queries představuje 0,3 až 1,2 % SQR — malý objem, ale kritický z hlediska souladu.

[Google Ads API / CSV export]
    |
    v  Krok 1 — extrakce SQR (GAQL nebo CSV)
[search_terms.csv : query, clicks, cost, conv]
    |
    v  Krok 2 — embeddings (OpenAI nebo ST)
[embeddings.npy : matice 384/1536 dim]
    |
    v  Krok 3 — clustering DBSCAN nebo HDBSCAN
[queries_clustered.csv : query, cluster_id]
    |
    v  Krok 4 — skórování intent + cost wasted
[clusters_scored.csv : cluster, waste_score, intent_score]
    |
    v  Krok 5 — filtrování + match type + export
[negatives_export.csv : připraveno pro Google Ads Editor]

Zde je Python kostra hlavního runneru. Kompletní kód (se zpracováním chyb, logy, CLI parametry) je ve veřejném repozitáři.

# main.py — kompletní pipeline v 5 krocích
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"):
    # Krok 1 — načtení SQR
    df = pd.read_csv(sqr_path)
    df = df[df["clicks"] >= 1]  # filtrovat queries bez kliknutí
    print(f"Loaded {len(df)} queries")

    # Krok 2 — embeddings
    embeddings = embed_queries(df["search_term"].tolist(), backend=backend)
    print(f"Embeddings shape: {embeddings.shape}")

    # Krok 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")

    # Krok 4 — skórování
    clusters_scored = score_clusters(df, whitelist_path="whitelist.txt")

    # Krok 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",  # nebo "openai"
    )

Každý krok produkuje persistovaný artefakt (CSV nebo .npy). To usnadňuje debuggování: pokud clustering produkuje příliš mnoho šumu, lze iterovat na kroku 3 bez opětovného spuštění embeddingů (drahé API volání). Viz náš průvodce automatizací Google Ads API Python pro detailní nastavení OAuth a GAQL extrakci.

Embeddings: OpenAI text-embedding-3 vs sentence-transformers

Embedding je kritický krok. Vektorizovaná query umožňuje měřit sémantickou podobnost mezi 'nabídka pojištění auta' a 'cena pojištění vozidla' — i když nemají žádné společné slovo. Bez embeddingů clustering přepadá zpět na token matching a přehlíží 70 % relevantních seskupení.

Dva relevantní backendy v roce 2026: OpenAI text-embedding-3-small (hostované, 1536 dim, placené za použití) a sentence-transformers all-MiniLM-L6-v2 nebo multilingual-e5-base (lokální, 384 nebo 768 dim, zdarma). Výběr závisí na objemu a citlivosti dat.

Varianta OpenAI — production-ready, batch optimalizovaná:

# embeddings.py — backend OpenAI
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)

Varianta sentence-transformers — lokální, nulové náklady:

# embeddings.py — lokální backend sentence-transformers
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,  # důležité pro 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}")

Terénní referenční bod: na CZ/SK e-commerce účtu s 8 000 queries zůstává delta kvality clusterů mezi OpenAI a e5-base kolem 6 až 9 % přesnosti (měřeno: počet platných negativních klíčových slov / počet návrhů). U MiniLM v1 anglosaského vyhotovení delta stoupá na 12 až 18 % — odtud volba paraphrase-multilingual-MiniLM-L12-v2 pro česky/slovensky mluvící účty. Pro 100% českojazyčný účet je to nejlepší kompromis cena/kvalita. Oficiální dokumentace OpenAI embeddings.

text-embedding-3-large vs text-embedding-3-small: kdy large stojí za příplatek? Tři konkrétní případy, kdy text-embedding-3-large (3072 dim, 0,13 USD / 1M tokenů, tedy 6,5× dražší než small) ospravedlňuje investici. Případ 1: jemný intent v specializovaných technických oborech (medicína, právo, strojírenství), kde nuance mezi 'daňový poradce' a 'daňové poradenství' mění skórování intentu. Large zachytí o 4 až 7 % vyšší přesnost měřitelnou na validační kohortě. Případ 2: smíšená vícejazyčnost (CZ + SK + EN ve stejném účtu), kde robustnost cross-jazyk largu zabraňuje rozdělení pipeline na tři samostatné průchody. Případ 3: velmi vysoký objem (50 000+ queries za měsíc), kde marginální dodatečné náklady zůstávají pod 1 EUR na spuštění bez významného dopadu na P&L. Mimo tyto tři případy zůstává text-embedding-3-small správným výchozím nastavením pro mid-market účet.

Analýza nákladů OpenAI API na reálném případu. Pro účet zpracovávající 8 000 queries po 4 až 8 slovech každý týden (průměrně 32 tokenů na query, tedy 256 000 tokenů na spuštění) jsou náklady spuštění v small verzi 256 000 / 1 000 000 × 0,02 USD = 0,005 USD. Za 52 ročních spuštění přibližně 0,27 USD na účet za rok. V large verzi se náklady stávají 256 000 / 1 000 000 × 0,13 USD = 0,033 USD na spuštění, tedy přibližně 1,72 USD ročně. V obou případech jsou náklady API OpenAI marginální ve srovnání s ušetřeným časem PPC manažera. Klasická past: nechat běžet bez dávkování (1 query na volání místo 100 na batch), což náklady násobí 8 až 12× kvůli opakování pevných poplatků na požadavek. Vždy dávkujte minimálně 50–100 queries na volání.

Clustering DBSCAN: proč ne K-means

K-means je nejznámější clusteringový algoritmus, ale je to špatná volba pro Google Ads search queries. Tři technické důvody:

  1. K-means vyžaduje předem stanovit K. Kolik clusterů nerelevantních queries existuje ve vašem účtu? Nikdo to neví před analýzou. K-means nutí hádat — a špatné K produkuje buď příliš široké clustery (smíšené intenty) nebo příliš jemné (over-fragmentace).
  2. K-means přiřazuje všechny body do clusteru. Přitom 30 až 50 % queries je šum (jedinečné queries bez ekvivalentu). DBSCAN je identifikuje jako šum (cluster -1) místo jejich vynucení do fiktivního clusteru. Výsledek: čistější clustery.
  3. K-means předpokládá sférické clustery stejné hustoty. Clustery nerelevantních queries mají velmi proměnlivé hustoty (velmi hustý cluster 'zdarma' + difuzní cluster 'porovnání konkurentů'). DBSCAN tuto varianci zvládá, K-means nikoli.

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) přijímá dva parametry: eps (poloměr sousedství) a min_samples (min. počet bodů pro tvorbu clusteru). Identifikuje husté oblasti v prostoru embeddingů a seskupuje blízké body.

# 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:
    # Kosinusová vzdálenost pro normalizované embeddingy
    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 nepodporuje cosine přímo
        cluster_selection_method="eom",
    )
    labels = clustering.fit_predict(embeddings)
    return labels

Kalibrace parametru eps: je to práh kosinusové podobnosti, pod kterým jsou dvě queries považovány za sousední. Čím menší eps, tím jemnější clustery. Terénní referenční bod: začít s eps=0,15. Pokud více než 70 % queries vychází jako šum (cluster -1), zvýšit na 0,20. Pokud jsou clustery příliš široké (cluster 'služba' míchá B2B a B2C), snížit na 0,12.

HDBSCAN jako alternativa, pokud DBSCAN produkuje špatně kalibrované clustery. HDBSCAN auto-detekuje lokální hustotu a nepotřebuje eps. Robustnější na heterogenních datasetech, ale pomalejší a složitější na debuggování.

Tip — vizualizovat clustery před skórováním :

Před přechodem ke skórování vizualizujte získané clustery přes UMAP ve 2D. umap-learn redukuje embeddingy ze 384 dim na 2 dim pro čitelný scatter plot. Okamžitě vidíte, zda je clustering čistý (zřetelné a oddělené clustery) nebo zašuměný (překrývající se clustery). Pokud zašuměný, upravte eps před pokračováním. 5 minut investovaných zabraňuje 30 minutám zbytečného skórování.

Validace clusterů: tři metriky nad rámec vizualizace UMAP

Vizualizace UMAP je užitečná, ale subjektivní. Pro kvantitativní validaci kvality clusteringu tři objektivní metriky k systematickému výpočtu před přechodem ke skórování. Metrika 1: silhouette score. Implementováno v sklearn.metrics.silhouette_score, tato metrika měří, jak moc je každý bod blíže svému vlastnímu clusteru než ostatním clusterům. Skóre mezi -1 (katastrofální) a +1 (perfektní). Silhouette vyšší než 0,3 na celém datasetu indikuje exploitovatelný clustering; pod 0,15 je potřeba přeladit eps. Na účtech sledovaných v agregovaných benchmarcích Google Ads mid-size e-commerce účet typicky dosahuje 0,32 až 0,48 silhouette u sentence-transformers a 0,38 až 0,55 u OpenAI text-embedding-3-small.

Metrika 2: procento šumu. Spočítat poměr (labels == -1).mean(). Dobrý DBSCAN clustering na Google Ads SQR by měl mít 25 až 45 % šumu (nepřiřazené queries). Pod 25 % je eps příliš velký a clustery jsou over-fúzovány. Nad 60 % je eps příliš přísný a většina queries je odmítána. Tato metrika je zadarmo vypočítat a slouží jako bezpečnostní pojistka pro prevenci degenerativních konfigurací.

Metrika 3: mediánová velikost clusterů. Vypočítat np.median([size for _, size in clusters_size]). Exploitovatelný clustering produkuje clustery mediánové velikosti 4 až 12 queries. Nad 20 jsou clustery příliš široké a míchají různé intenty. Pod 4 jsou příliš jemné a skórování se stává nestabilní. Pokud je mediánová velikost mimo toto okno, upravte min_samples (DBSCAN) nebo min_cluster_size (HDBSCAN) před pokračováním pipeline. V produkčních iteracích sledování těchto tří metrik a logování jejich driftu umožňuje detekci tichých regresí pipeline (změna API embeddingů, drift ve zdrojových queries) dříve, než jsou navrhovaná negativní klíčová slova ovlivněna.

Skórování: relevance intent + cost wasted

Jakmile jsou queries clusterizovány, je potřeba ohodnotit každý cluster pro rozhodnutí, které jsou kandidáty na negativní klíčová slova. Skórování kombinuje dvě dimenze: (1) cost wasted (kolik spend bylo spáleno bez konverze) a (2) intent score (jak moc je cluster vzdálen od vašeho cílového komerčního intentu).

Cost wasted je triviální k výpočtu: součet nákladů / max(součet konverzí, 0,1) na cluster. Čím vyšší poměr, tím více je cluster kandidátem na negativní klíčové slovo.

Intent score je subtilnější. Porovnáváme průměrnou kosinusovou podobnost clusteru s whitelistem cílových klíčových slov (vaše brand klíčová slova + klíčové produkty + silné nákupní intenty). Pokud průměrná podobnost clusteru s whitelistem je vyšší než 0,65, je to pravděpodobně relevantní cluster (NEVYLUČOVAT). Pokud je nižší než 0,30, je to cluster vzdálený od komerčního intentu = silný kandidát na negativní klíčové slovo.

# scoring.py — skórování intent + cost wasted
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:
    # Načíst whitelist (1 klíčové slovo na řádek)
    with open(whitelist_path) as f:
        whitelist_keywords = [line.strip() for line in f if line.strip()]

    # Embeddovat whitelist
    from embeddings import embed_queries
    whitelist_emb = embed_queries(whitelist_keywords, backend="sentence-transformers")

    # Agregovat podle clusteru
    cluster_stats = []

    for cluster_id, group in df.groupby("cluster_id"):
        if cluster_id == -1:
            continue  # ignorovat šum

        cost = group["cost"].sum()
        conv = group["conversions"].sum()
        clicks = group["clicks"].sum()
        size = len(group)

        # waste_score: náklady na konverzi (floor 0,1 pro prevenci dělení nulou)
        waste_score = cost / max(conv, 0.1)

        # intent_score: průměrná kosinusová podobnost s whitelistem
        cluster_emb = np.stack(group["embedding"].values)
        sim_matrix = cosine_similarity(cluster_emb, whitelist_emb)
        intent_score = float(sim_matrix.max(axis=1).mean())

        # reprezentativní příklad (query nejblíže středu clusteru)
        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)

Výklad výstupní tabulky: seřadit podle waste_score sestupně, pak filtrovat na intent_score < 0,30 A size >= 3. Toto trio identifikuje clustery, které (1) spalují spend, (2) jsou vzdáleny od komerčního intentu a (3) mají dostatek queries pro hodnotné negativní klíčové slovo (ne one-shot).

Referenční hodnoty prahů:

  • waste_score >= 30 (minimálně 30 EUR nákladů bez konverze) — odpovídá prahu relevance pro většinu účtů.
  • intent_score < 0,30 (kosinusová podobnost s whitelistem pod 30 %) — nad tím je riziko falešného negativního klíčového slova.
  • size >= 3 (minimálně 3 queries v clusteru) — pod 3 je to šum nebo dlouhý ocas, zpracovat případ od případu.

Tyto prahy jsou výchozí body. Upravte podle zpětné vazby z manuálního vzorku po 2–3 iteracích.

Export CSV připravený pro Google Ads Editor

Finální výstup musí být přímo importovatelný do Google Ads Editor — jinak ztratíte 30 minut ručním přeformátováváním. Očekávaný formát: CSV UTF-8, specifické sloupce, jasný match type, explicitní akce ("Add" pro přidání).

# export.py — generování CSV pro Google Ads Editor
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:
    # Filtrovat kandidátní clustery
    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():
        # Určit match type podle rozptýlenosti clusteru
        # (v produkci parametrizovat jemněji: zde zjednodušení)
        match_type = "Phrase match" if cluster["size"] <= 8 else "Broad match"

        rows.append({
            "Action": "Add",
            "Campaign": "ALL",  # nebo cluster["campaign"] pokud dostupné
            "Ad group": "",  # prázdné = úroveň kampaně
            "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']} EUR | "
                       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}")

Postup importu do Google Ads Editor: Google Ads Editor > File > Import > From CSV. Nástroj detekuje sloupce, validuje formát match type a nabídne vizuální diff před odesláním. Zkontrolujte diff (vzorek 30–50 řádků), potvrďte a pak Post Changes. Pro oficiální dokumentaci Google Ads Editor viz support.google.com/google-ads/answer/2475106.

Match type — terénní heuristika:

  • Phrase match pro velmi homogenní clustery (velikost 3–8 queries, krátké a podobné výrazy). Přesná shoda, nízké riziko náhodného zablokování relevantní query.
  • Broad match pro široké koncepty (velikost nad 15, různorodé queries kolem stejného intentu). Širší, ale nezapomeňte monitorovat po push pro detekci nadměrného blokování.
  • Exact match zřídka relevantní jako AI negativní klíčové slovo — pracujeme spíše s koncepty než přesnými queries.
Upozornění — povinná review před uplodem :

NIKDY nenahrávat CSV přímo bez lidské review při prvním spuštění. Zkontrolovat vzorek 30–50 náhodných řádků, ověřit, že se nevyskytuje žádný brand výraz / klíčový produkt / cílové klíčové slovo, validovat match type. Pokud je více než 10 % vzorku falešně pozitivní, upravte prahy (min_waste_score výše, max_intent_score níže) a spusťte znovu. Jakmile je pipeline validován po 2–3 iteracích (míra chyb pod 5 %), lze automatizovat v automatickém režimu.

Typické ROI: kolik spend se zotaví

Praktická otázka: kolik tento AI pipeline přináší vs. manuální analýza? Odpověď v terénních číslech, měřených na účtech sledovaných v agregovaných benchmarcích Google Ads.

Výklad: AI pipeline není magický v přesnosti (pozorný člověk dosahuje stejně dobrých výsledků). Jeho výhoda je v recallu — identifikuje 75 až 88 % relevantních negativních klíčových slov vs. 20 až 35 % pro člověka za 30 minut. A čas PPC manažera klesá z 30 minut na 5–15 minut na spuštění po počátečním nastavení. Skutečný zisk je kumulativní: za 12 měsíců je to 4 až 6 ušetřených hodin PPC manažera A 12 až 22 % lépe využitého spend.

Číselný referenční bod: na účtu s 30 000 EUR/měsíc, zotavit 15 % spend = 4 500 EUR/měsíc přesměrovaných k queries, které konvertují. Při iso-CPA je to 4 500 / CPA dodatečných konverzí v bottom-funnel každý měsíc. Za 12 měsíců je to typicky 230 až 380 dodatečných konverzí bez zvýšení rozpočtu. ROI vs počáteční investice (45 min nastavení + API klíč embeddingů) je vyšší než 50×.

Klíčový poměr: recall děleno investovaným časem. Pro manuální analýzu 2 h je poměr přibližně 0,25 (50 % recall / 2 h). Pro AI pipeline je poměr přibližně 6 (80 % recall / 0,2 h po nastavení). To je 24× efektivnější na metrice, na které skutečně záleží — kolik wasted spend identifikujeme za hodinu investovaného PPC manažera. A tento poměr se dále zlepšuje v průběhu spuštění: při 5. iteraci se manuální vzorek redukuje na 15–25 negativních klíčových slov k reviewu (vs 60–80 při prvním spuštění), protože opakující se vzory jsou absorbovány předchozími clustery.

Praktické měření za 60 dní: účty, které aktivují pipeline v týdenním režimu, konvergují ke steady-state, kde většina nových negativních klíčových slov pochází z nových vzorů (stoupající konkurenti, sezónní queries, sémantické evoluce publika). Pipeline detekuje tyto novinky za méně než 7 dní od jejich výskytu vs. 30–60 dní v manuálním monitoringu — tedy okno 23–53 dní ušetřeného wasted spend na každý nový vzor. To je skutečný příkop automatizace na základě embeddingů: rychlost reakce, ne jen jednorázový recall.

Náš engine auto-optimalizace integruje tento pipeline v řízeném režimu: automatická extrakce GAQL, hostované embeddingy, clustering DBSCAN, skórování + filtrování a týdenní návrhy validovatelné 1 kliknutím. Pro účty, které chtějí industrializovat bez programování. Viz také náš průvodce 10 Google Ads skriptů pro automatizaci nativními skripty a náš průvodce n8n + Google Ads pro plánování pipeline v self-hosted workflow. Komplementarity mezi těmito třemi úhly — AI pipeline, nativní skripty, n8n self-hosted — jsou podrobně popsány v naší kolekci ChatGPT Google Ads promptů.

Běžné chyby k vyhnutí při industrializaci

Pět chyb se opakovaně vyskytuje při nasazení AI pipeline negativních klíčových slov Google Ads do produkce. Každá vytváří buď falešná negativní klíčová slova (špatně cílená, blokující relevantní provoz), nebo falešně pozitivní (přehlédnutá negativní klíčová slova). Diagnóza a přímá náprava.

1. Spustit pipeline bez whitelistu brand a cílových produktů. Diagnóza: pipeline navrhuje negativní klíčová slova obsahující vaše brand výrazy nebo názvy klíčových produktů, protože ty jsou sémanticky špatně odlišeny od nerelevantních queries. Náprava: udržovat whitelist.txt s minimálně variantami brand (jednoduchá + složená slova), 10 až 20 názvy cílových produktů a silnými komerčními výrazy. Tento whitelist slouží pro skórování intentu (intent_score) a blokuje export jakéhokoli clusteru, jehož representative_query částečně odpovídá whitelistu.

2. Zaměnit exact match a phrase match v exportu negativních klíčových slov. Diagnóza: export clusteru v exact match na representative_query blokuje pouze přesnou query (10–15 % clusteru), přičemž 85–90 % wasted cost pokračuje. Náprava: používat phrase match jako výchozí pro koherentní clustery a broad match pro široké koncepty. Testovat před push dotazem Keyword Planneru na navrhované negativní klíčové slovo: pokud odhadovaný objem je vyšší než 5× objem původního clusteru, match type je příliš široký.

3. Spouštět pipeline příliš často a generovat šum. Diagnóza: denní pipeline produkuje desítky návrhů denně, z nichž 60–70 % jsou přeformulování předchozích návrhů. Únava z validace tlačí tým k validaci všeho bez review. Náprava: spouštět týdně (v pondělí ráno), ne denně. Okno 7 dní stabilizuje vzory a zabraňuje předčasným rozhodnutím o one-shot queries. Pro účty s velmi vysokou frekvencí vývoje (silná sezónnost) přejít na bi-týdenní maximum, nikdy denní.

4. Ignorovat malé clustery s vysokým waste. Diagnóza: filtr min_cluster_size: 3 systematicky vylučuje clustery o 1–2 queries, které mohou nést vysoký waste (query s náklady 80 EUR bez konverze například). Tyto izolované vzory unikají radaru pipeline. Náprava: přidat druhý průchod, který navrhuje jednotlivé queries nad waste_score = 60 nezávisle na jejich příslušnosti ke clusteru. Tyto individuální návrhy jsou rizikovější pro auto-validaci, proto reviewovat manuálně před exportem.

5. Neměřit výkon po aplikaci. Diagnóza: negativní klíčová slova jsou nahrána, pipeline běží na autopilotu, ale nikdo neověřuje, zda se CPA a ROAS skutečně zlepšují. Náprava: sledovat indikátor zdraví pipeline: delta_cpa_30j_post_negativni_kl_slova (změna CPA za 30 dní po push N negativních klíčových slov). Pokud je změna nulová nebo záporná, navrhovaná negativní klíčová slova byla marginální. Upravit prahy min_waste_score a max_intent_score pro cílení clusterů s výraznějším dopadem. Na účtech sledovaných v agregovaných benchmarcích Google Ads se měřitelné zlepšení typicky projevuje v prvních 3 až 5 iteracích a pak se stabilizuje.

Pro účty, které chtějí industrializovat bez vlastního spouštění pipeline, náš modul Auto-optimalizace spouští pipeline embeddings + clustering každý týden na vašem účtu, navrhuje kandidátní negativní klíčová slova ověřená přes UI a aplikuje je po review. OAuth připojení za 2 minuty, první analýza za 5 minut. Veřejný repozitář github.com/steerads/google-ads-negatives-ai dostupný pro ty, kteří preferují self-hosting, s Dockerfile a příkladem n8n workflow.

Zdroje

Oficiální zdroje použité v tomto průvodci:

FAQ

Je nutné používat OpenAI nebo lze zůstat 100% open-source?

Můžete zůstat 100% open-source. sentence-transformers (model all-MiniLM-L6-v2 nebo multilingual-e5-base) běží lokálně na CPU, bez API klíče ani nákladů, s dostatečnou kvalitou pro clustering search queries. Pozorovatelný rozdíl vs OpenAI text-embedding-3-small: -8 až -14 % přesnosti u jemných clusterů (oddělení 'nabídka' komerční vs 'nabídka' právní), ale +nula eur nákladů API. Pro účty zpracovávající méně než 5 000 queries/měsíc je sentence-transformers dostatečný. Nad tuto hranici, nebo pokud zpracováváte vícejazyčný obsah s diakritikou, má text-embedding-3-small lepší poměr kvality/úsilí. Pipeline podporuje oba backendy přes proměnnou prostředí.

Jaký minimální objem search queries je potřeba pro spolehlivý clustering?

Praktická hranice: minimálně 500 queries v analyzovaném okně (typicky 30 dní). Pod touto hranicí nemá DBSCAN dostatečnou hustotu pro identifikaci stabilních clusterů a většina queries vychází jako šum. Optimální rozsah: 2 000 až 10 000 queries za 30 dní. Nad 10 000 rozdělte podle kampaně, abyste předešli míchání příliš odlišných intentů (B2B + B2C ve stejném clusteringu = šum). Pokud váš účet má méně než 500 queries/30 dní, rozšiřte okno na 60 nebo 90 dní.

DBSCAN nebo HDBSCAN: který zvolit v praxi?

HDBSCAN je obecně lepší pro Google Ads search queries: zvládá clustery s proměnlivou hustotou, což odpovídá realitě (velmi hustý cluster 'zdarma' + difuzní cluster 'konkurent'). DBSCAN vyžaduje nastavení jediného parametru eps pro celý dataset, což nutí ke kompromisům. DBSCAN ale zůstává jednodušší na parametrizaci a rychlejší na malých objemech (méně než 5 000 queries). Doporučení: začít s DBSCAN s eps kolem 0,15 a min_samples 5, pak přejít na HDBSCAN pokud se clustery zdají špatně kalibrovány. Pipeline podporuje oba přes konfigurační proměnnou.

Jak hodnotit kvalitu negativních klíčových slov navrhovaných pipelinem před uplodem?

Tři povinné kontroly před každým uploadem do Google Ads Editor. (1) Manuální vzorek: zkontrolovat 30 až 50 náhodných negativních klíčových slov, cílit na míru validace vyšší než 90 %. (2) Whitelist: ověřit, že v seznamu se nevyskytuje žádný brand výraz, klíčový produkt nebo cílové klíčové slovo (skript musí mít whitelist na vstupu). (3) Match type: ověřit, že exportovaný match type odpovídá záměru (phrase match pro přesné výrazy, broad match pro koncepty). Pokud je míra validace ve vzorku nižší než 90 %, upravte prahové hodnoty skórování (cost_min, cluster_size_min) místo přímého uploadu. Iterujte 2 až 3krát před cílením na automatický režim.

Lze tento pipeline automatizovat jako týdenní spuštění na n8n nebo Cloud Run?

Ano, a to je konečný cíl pro industrializaci. Python pipeline běží za méně než 3 minuty na 5 000 queries (lokální CPU) nebo méně než 60 sekund přes OpenAI batch embeddings + DBSCAN GPU. Lze naplánovat jako cron na Cloud Run, Lambda nebo v n8n workflow. Doporučený vzor: týdenní spuštění (v pondělí ráno), výstup do sdíleného Google Sheetu, lidská validace vzorku, upload přes Google Ads Editor (nebo přímo přes Google Ads API při vysoké důvěře v pipeline). Repozitář github.com/steerads/google-ads-negatives-ai obsahuje Dockerfile a příklad n8n workflow.

Ready to optimize your campaigns?

Start a free audit in 2 minutes and discover the ROI potential of your accounts.

Start my free audit

Free audit — no credit card required

Keep reading