SteerAds
Google AdsTutorielOptimisation

IA Palabras clave negativas: discovery y clustering

El análisis manual de un search query report omite entre el 60 y el 80% de los negativos ocultos. Aquí tiene un pipeline IA reproducible: embeddings OpenAI o sentence-transformers, clustering DBSCAN, scoring intención + cost wasted, exportación CSV para Google Ads Editor. Repo Python open-source de bonus.

Andrew
AndrewSmart Bidding & Automation Lead
···9 min de lectura

En las cuentas observadas en los benchmarks públicos de Google Ads, el análisis manual de un search query report omite entre el 60 y el 80% de los negativos ocultos tras 30 minutos de revisión a ojo por un PPC manager con experiencia. Y el coste de esa omisión es medible: entre el 14 y el 28% del gasto mensual termina en queries irrelevantes que nadie verá en el top 50 del SQR (documentación oficial Google Ads sobre negativos). Es típicamente la palanca descuidada que arrastra la ratio CPA / Quality Score de una cuenta madura.

Este es el diagnóstico: un humano que escanea un SQR hace pattern matching visual sobre las primeras 200-500 líneas ordenadas por coste. Omite (1) las queries de cola larga que pesan solo $3 a $9 cada una pero acumulan entre el 18 y el 26% del gasto, (2) las variaciones semánticas agrupables ('reseñas', 'opinión', 'feedback', 'testimonio' = misma intención), y (3) los clusters de queries fuera de intención comercial (empleo, formación gratuita, definición, precio low-end) que el algoritmo Smart Bidding no identifica si el conversion tracking se hace por valor fijo.

Esta guía da el pipeline IA reproducible: extracción GAQL del SQR, embeddings (OpenAI o sentence-transformers), clustering DBSCAN, scoring intención + cost wasted, exportación CSV para Google Ads Editor. Todo el código está en Python, corre localmente, y el repo público github.com/steerads/google-ads-negatives-ai contiene un Dockerfile y un workflow n8n de ejemplo. Para los fundamentos de match types que condicionan este pipeline, vea nuestra guía de match types 2026. Nuestra calculadora de wasted ad spend estima los $ quemados/mes por broad sin negativos o por exceso de bounce en LP.

El problema: del 60 al 80% de los negativos ocultos en el análisis manual

El análisis manual de un search query report (SQR) es una de las tareas del PPC manager más consumidoras de tiempo. En una cuenta media (5.000 a 15.000 queries / 30 días), prevea 45 minutos a 2 horas para una pasada limpia. E incluso con ese tiempo invertido, la tasa de detección de negativos relevantes se mantiene estructuralmente limitada por la fatiga cognitiva y la ordenación por coste descendente.

Tres puntos ciegos sistemáticos en el análisis manual:

  1. La cola larga es invisible. Las primeras 50 queries ordenadas por coste concentran del 35 al 50% del gasto. El PPC manager las ve. Pero las 4.950 queries restantes — cada una entre $1 y $9 — concentran del 50 al 65% del gasto total y se quedan sin explorar. Es ahí donde se ocultan los patrones recurrentes de irrelevancia.
  2. El pattern matching visual omite las variantes semánticas. Un humano identifica 'reseñas' como negativo candidato. Pero 'opinión', 'testimonio', 'feedback', 'review' comparten la misma intención y aparecen en queries distintas. Sin embedding, imposible agruparlas.
  3. Sin scoring de cost wasted. Una query de $27 de coste / 0 conversión en 30 días es más impactante que una query de $4 de coste / 0 conversión — aunque la segunda aparezca 6x más a menudo. El humano ordena alfabéticamente o por coste bruto, rara vez por cost wasted (cost / conversions).
Insight — ratio negativos / gasto :

En las cuentas observadas en los benchmarks públicos de Google Ads, la ratio de gasto recuperable vía clustering IA de negativos converge a un umbral muy reproducible: del 12 al 22% del gasto mensual tras 60 días de pipeline activo. En un presupuesto de $33.000/mes, son entre $4.000 y $7.300 de gasto recuperado cada mes — no devuelto a los competidores, sino reinyectado en queries que convierten. El ROI vs el tiempo del PPC manager ahorrado supera el 25x para la mayoría de las cuentas tratadas.

El pipeline IA descrito aquí reemplaza la pasada manual por un workflow reproducible. La primera ejecución toma de 30 a 45 minutos (setup + ejecución + revisión). Las ejecuciones siguientes toman de 5 a 15 minutos (revisión del sample solo). Para la base de auditoría que debería preceder a esta automatización, lea nuestra checklist de auditoría Google Ads.

Pipeline IA en 5 pasos: del query report a la lista de negativos

El pipeline completo encadena 5 pasos deterministas, cada uno testable de forma aislada. Arquitectura deliberadamente simple, sin dependencia ML pesada más allá de scikit-learn y sentence-transformers / openai. El output final es un CSV directamente importable en Google Ads Editor.

Pre-procesamiento de las queries: el paso demasiado a menudo saltado

Antes de embeddear lo que sea, el pre-procesamiento del SQR condiciona del 30 al 50% de la calidad final del clustering. Cuatro transformaciones a aplicar sistemáticamente. Primer paso: normalización Unicode y de mayúsculas/minúsculas. Los SQR de Google Ads contienen a menudo duplicados fantasma: 'Presupuesto Auto', 'presupuesto auto', 'presupuesto auto' (doble espacio), 'presupuesto-auto' aparecen como 4 queries distintas cuando se trata de la misma cosa. Aplique unicodedata.normalize('NFKC', s).strip().lower() más una regex \s+ -> ' ' para fusionar estos duplicados en una sola línea con coste y clics agregados. En una cuenta US media, este paso reduce el volumen de queries entre un 8 y un 14% sin pérdida de información.

Segundo paso: deduplicación inteligente. Más allá de la normalización simple, la deduplicación debe gestionar las variantes morfológicas (singular/plural, masculino/femenino, acentos) según necesidad. Para el clustering, conservar las variantes brutas suele ser más útil (el embedding las agrupa mecánicamente), pero para el export final de los negativos, deduplicar sobre el representative_query del cluster evita proponer 5 veces el mismo negativo. Tercer paso: filtrado de las queries one-shot de bajo coste. Una query que aparece una sola vez en 30 días con $1,30 de coste no merece embedding (es ruido puro). Pre-filtrar sobre clicks >= 1 AND cost >= 1 evita contaminar el clustering con un 25-40% de ruido irreductible.

Cuarto paso: detección de PII y términos sensibles. Algunas queries contienen números de teléfono, emails o nombres propios de usuarios (tecleados por error en la barra de búsqueda en lugar de la URL). Esas queries no tienen interés analítico y procesarlas vía OpenAI plantearía problemas de RGPD. Pre-filtre vía regex y NO las envíe NUNCA a una API externa. En los datos agregados de Google Ads 2025-2026, esas queries representan del 0,3 al 1,2% del SQR — bajo en volumen pero crítico en compliance.

[Google Ads API / export CSV]
    |
    v  Paso 1 — Extracción SQR (GAQL o CSV)
[search_terms.csv : query, clicks, cost, conv]
    |
    v  Paso 2 — embeddings (OpenAI o ST)
[embeddings.npy : matriz 384/1536 dim]
    |
    v  Paso 3 — Clustering DBSCAN o HDBSCAN
[queries_clustered.csv : query, cluster_id]
    |
    v  Paso 4 — scoring intención + cost wasted
[clusters_scored.csv : cluster, waste_score, intent_score]
    |
    v  Paso 5 — filtrado + match type + export
[negatives_export.csv : listo para Google Ads Editor]

He aquí el esqueleto Python del runner principal. El código completo (con manejo de errores, logs, parámetros CLI) está en el repo público.

# main.py — pipeline completo en 5 pasos
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"):
    # Paso 1 — carga del SQR
    df = pd.read_csv(sqr_path)
    df = df[df["clicks"] >= 1]  # filtra las queries sin clic
    print(f"Loaded {len(df)} queries")

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

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

    # Paso 4 — scoring
    clusters_scored = score_clusters(df, whitelist_path="whitelist.txt")

    # Paso 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",  # o "openai"
    )

Cada paso produce un artefacto persistido (CSV o .npy). Esto facilita el debug: si el clustering produce demasiado ruido, puede iterar sobre el paso 3 sin re-ejecutar los embeddings (caros en llamadas API). Vea nuestra guía de automatización Python Google Ads API para el setup OAuth y la extracción GAQL detallada.

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

El embedding es el paso crítico. Una query vectorizada permite medir la similitud semántica entre 'presupuesto seguro auto' y 'tarifa seguro coche' — incluso con cero palabras compartidas. Sin embedding, el clustering vuelve a un token matching y omite el 70% de las agrupaciones relevantes.

Dos backends relevantes en 2026: OpenAI text-embedding-3-small (hosted, 1536 dim, de pago por uso) y sentence-transformers all-MiniLM-L6-v2 o multilingual-e5-base (local, 384 o 768 dim, gratuito). La elección depende del volumen y de la sensibilidad de los datos.

Variante OpenAI — production-ready, optimizada batch:

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

Variante sentence-transformers — local, coste cero:

# embeddings.py — backend sentence-transformers local
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,  # importante para coseno
    )
    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}")

Benchmark de campo: en una cuenta e-commerce US de 8.000 queries, el delta de calidad de cluster entre OpenAI y e5-base se sitúa en torno al 6-9% de precisión (medida: # negativos válidos / # propuestos). En MiniLM v1 EN-only, el delta sube al 12-18% — de ahí la elección de paraphrase-multilingual-MiniLM-L12-v2 para non-EN. Para una cuenta EN-only es el mejor compromiso coste/calidad. Documentación oficial sobre embeddings OpenAI.

text-embedding-3-large vs text-embedding-3-small: ¿cuándo el large justifica el sobrecoste? Tres casos concretos en los que text-embedding-3-large (3072 dim, $0,13 / 1M tokens, 6,5x más caro que small) justifica la inversión. Caso 1: intención fina en sectores técnicos especializados (médico, jurídico, ingeniería) en los que el matiz entre 'abogado fiscal' y 'abogado fiscalmente eficiente' cambia el scoring de intención. El modelo large capta entre un 4 y un 7% de precisión adicional medible en la cohorte de validación. Caso 2: multi-idioma mixto (EN + ES + FR en la misma cuenta) en el que la robustez cross-language del large evita partir el pipeline en tres pasadas distintas. Caso 3: muy alto volumen (más de 50.000 queries por mes) en el que el coste marginal adicional se mantiene por debajo de $1 por ejecución sin impacto P&L significativo. Fuera de estos tres casos, text-embedding-3-small sigue siendo el buen default para una cuenta US mid-market.

Análisis del coste de la API OpenAI en un caso real. Para una cuenta que procesa 8.000 queries de 4 a 8 palabras cada semana (media de 32 tokens por query, es decir, 256.000 tokens por ejecución), el coste de ejecución en small es 256.000 / 1.000.000 x $0,02 = $0,005. En 52 ejecuciones anuales, alrededor de $0,27 por cuenta y año. En large, el coste pasa a 256.000 / 1.000.000 x $0,13 = $0,033 por ejecución, alrededor de $1,72 al año. En ambos casos, el coste de la API OpenAI es marginal frente al tiempo de PPC manager ahorrado. Trampa clásica: ejecutar sin batching (1 query por llamada en lugar de 100 por batch), lo que multiplica el coste por 8 a 12 debido a tarifas fijas por petición repetidas. Bachée siempre 50-100 queries mínimo por llamada.

Clustering DBSCAN: por qué no K-means

K-means es el algoritmo de clustering más conocido, pero es la mala elección para queries de Google Ads. Tres razones técnicas:

  1. K-means exige fijar K por adelantado. ¿Cuántos clusters de queries irrelevantes existen en su cuenta? Nadie lo sabe antes del análisis. K-means obliga a adivinar — y un mal K produce o bien clusters demasiado amplios (intenciones mezcladas), o demasiado finos (sobre-fragmentación).
  2. K-means asigna cada punto a un cluster. Pero entre el 30 y el 50% de las queries son ruido (queries únicas sin equivalente). DBSCAN las identifica como noise (cluster -1) en lugar de meterlas a la fuerza en un cluster ficticio. Resultado: clusters más limpios.
  3. K-means asume clusters esféricos de densidad igual. Los clusters de queries irrelevantes tienen densidades muy variables (un cluster muy denso 'gratuito' + un cluster difuso 'comparativa de competidores'). DBSCAN gestiona esta varianza, K-means no.

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) toma dos parámetros: eps (radio de vecindad) y min_samples (puntos mínimos para formar un cluster). Identifica zonas densas en el espacio de embeddings y agrupa los puntos cercanos.

# 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:
    # Distancia coseno para embeddings normalizados
    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 no soporta el coseno directo
        cluster_selection_method="eom",
    )
    labels = clustering.fit_predict(embeddings)
    return labels

Calibrado del parámetro eps: es el umbral de similitud coseno por debajo del cual dos queries se consideran vecinas. eps más pequeño = clusters más finos. Benchmark de campo: empiece en eps=0.15. Si más del 70% de las queries salen como ruido (cluster -1), suba a 0,20. Si los clusters son demasiado amplios (cluster 'servicio' que mezcla B2B y B2C), baje a 0,12.

HDBSCAN como alternativa, si DBSCAN produce clusters mal calibrados. HDBSCAN auto-detecta la densidad local y no necesita eps. Más robusto en datasets heterogéneos pero más lento y más difícil de depurar.

Tip — visualice los clusters antes del scoring :

Antes de puntuar, visualice los clusters obtenidos con UMAP en 2D. umap-learn reduce los embeddings de 384 dim a 2 dim para un scatter plot legible. Vea instantáneamente si el clustering es limpio (clusters claros, separados) o ruidoso (clusters que se solapan). Si es ruidoso, ajuste eps antes de continuar. 5 minutos invertidos ahorran 30 minutos de scoring inútil.

Validación de clusters: tres métricas más allá del visual UMAP

La visualización UMAP es útil pero subjetiva. Para validar cuantitativamente la calidad del clustering, tres métricas objetivas a calcular sistemáticamente antes del scoring. Métrica 1: silhouette score. Implementada en sklearn.metrics.silhouette_score, mide cuánto cada punto está más cerca de su propio cluster que de los demás. Score entre -1 (catastrófico) y +1 (perfecto). Una silhouette superior a 0,3 sobre el conjunto del dataset indica un clustering explotable; por debajo de 0,15, hay que recalibrar eps. En las cuentas observadas en los benchmarks públicos de Google Ads, una cuenta e-commerce US mediana alcanza típicamente entre 0,32 y 0,48 de silhouette en sentence-transformers y entre 0,38 y 0,55 en OpenAI text-embedding-3-small.

Métrica 2: porcentaje de noise. Cuente la ratio (labels == -1).mean(). Un buen clustering DBSCAN sobre SQR Google Ads debe tener entre el 25 y el 45% de noise (queries no asignadas a un cluster). Por debajo del 25%, eps es demasiado amplio y los clusters están sobre-fusionados. Por encima del 60%, eps es demasiado estricto y la mayoría de las queries son rechazadas. Esta métrica es gratuita de calcular y sirve de guardrail contra configuraciones degeneradas.

Métrica 3: tamaño mediano de los clusters. Calcule np.median([size for _, size in clusters_size]). Un clustering explotable produce clusters de tamaño mediano entre 4 y 12 queries. Por encima de 20, los clusters son demasiado amplios y mezclan intenciones distintas. Por debajo de 4, son demasiado finos y el scoring se vuelve inestable. Si el tamaño mediano se sale de esta ventana, ajuste min_samples (DBSCAN) o min_cluster_size (HDBSCAN) antes de continuar el pipeline. En iteraciones de producción, monitorizar estas tres métricas y loguear su deriva permite detectar regresiones silenciosas del pipeline (un cambio de la API de embedding, una deriva de las queries fuente) antes de que los negativos propuestos se vean impactados.

Scoring: relevancia de intención + cost wasted

Una vez clusterizadas las queries, hay que puntuar cada cluster para decidir cuáles son candidatos a negativos. El scoring combina dos dimensiones: (1) cost wasted (cuánto gasto se ha quemado sin conversión) y (2) intent score (cuán lejos está el cluster de su intención comercial objetivo).

El cost wasted es trivial de calcular: suma de cost / max(suma de conversion, 0,1) por cluster. Cuanto más alta la ratio, más fuerte el candidato a negativo.

El intent score es más sutil. Comparamos la similitud coseno media del cluster con una whitelist de keywords objetivo (sus keywords de marca + productos estrella + intenciones de compra fuertes). Si la similitud media del cluster con la whitelist está por encima de 0,65, probablemente sea un cluster relevante (NO excluir). Si está por debajo de 0,30, es un cluster lejano de la intención comercial = candidato fuerte a negativo.

# scoring.py — scoring intención + 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:
    # Carga de la whitelist (1 keyword por línea)
    with open(whitelist_path) as f:
        whitelist_keywords = [line.strip() for line in f if line.strip()]

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

    # Agregación por cluster
    cluster_stats = []

    for cluster_id, group in df.groupby("cluster_id"):
        if cluster_id == -1:
            continue  # ignorar el ruido

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

        # waste_score: coste por conversión (suelo de 0,1 para evitar la división por 0)
        waste_score = cost / max(conv, 0.1)

        # intent_score: similitud coseno media con la 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())

        # ejemplo representativo (la query más central del 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)

Lectura de la tabla de output: ordene por waste_score descendente, luego filtre por intent_score < 0.30 Y size >= 3. Este trío identifica los clusters que (1) queman gasto, (2) están lejos de la intención comercial, y (3) tienen suficientes queries como para justificar un negativo (no un one-shot).

Benchmarks de umbrales:

  • waste_score >= 30 (al menos $32 de coste sin conversión) — corresponde al umbral de relevancia en la mayoría de las cuentas.
  • intent_score < 0.30 (similitud coseno con la whitelist por debajo del 30%) — por encima, riesgo de falso negativo.
  • size >= 3 (al menos 3 queries en el cluster) — por debajo de 3, es ruido o cola larga, tratar caso por caso.

Estos umbrales son puntos de partida. Ajústelos en función del feedback del sample manual tras 2-3 iteraciones.

Exportación CSV lista para Google Ads Editor

El output final debe ser directamente importable en Google Ads Editor — si no, pierde 30 minutos en reformatear manualmente. Formato esperado: CSV UTF-8, columnas específicas, match type claro, action explícita ("Add" para añadir).

# export.py — generación de CSV 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:
    # Filtrado de los clusters candidatos
    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():
        # Determinación del match type según la dispersión del cluster
        # (parametrizar más finamente en producción: simplificación aquí)
        match_type = "Phrase match" if cluster["size"] <= 8 else "Broad match"

        rows.append({
            "Action": "Add",
            "Campaign": "ALL",  # o cluster["campaign"] si está disponible
            "Ad group": "",  # vacío = nivel campaña
            "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}")

Procedimiento de importación en Google Ads Editor: Google Ads Editor > File > Import > From CSV. La herramienta detecta las columnas, valida el formato del match type y propone un diff visual antes de hacer push. Revise el diff (sample de 30-50 líneas), valide, y luego Post Changes. Para la documentación oficial de Google Ads Editor, vea support.google.com/google-ads/answer/2475106.

Match type — heurística de campo:

  • Phrase match para clusters muy homogéneos (size 3-8 queries, expresiones cortas similares). Match preciso, bajo riesgo de bloquear accidentalmente una query relevante.
  • Broad match para conceptos amplios (size superior a 15, queries variadas alrededor de una sola intención). Más amplio, pero no olvide monitorizar tras el push para detectar bloqueos excesivos.
  • Exact match rara vez relevante en negativos IA — tratamos conceptos más que queries exactas.
Atención — revisión obligatoria antes de la subida :

No suba NUNCA el CSV directamente sin revisión humana en la primera ejecución. Saquee 30-50 líneas al azar, verifique que ningún término marca / producto estrella / keyword objetivo aparece, valide el match type. Si más del 10% del sample es falso positivo, ajuste los umbrales (min_waste_score más alto, max_intent_score más bajo) y re-ejecute. Una vez validado el pipeline en 2-3 iteraciones (tasa de error por debajo del 5%), automatizable en modo auto.

ROI típico: cuánto gasto recupera

Pregunta práctica: ¿cuánto rinde este pipeline IA frente al análisis manual? Respuesta en cifras de campo, medidas en las cuentas observadas en los benchmarks públicos de Google Ads.

Lectura: el pipeline IA no es mágico en precisión (un humano atento es igual de bueno). Su ventaja está en el recall — identifica del 75 al 88% de los negativos relevantes vs el 20-35% de un humano en 30 minutos. Y el tiempo del PPC manager pasa de 30 min a 5-15 min por ejecución una vez hecho el setup inicial. La ganancia real es acumulativa: en 12 meses, son entre 4 y 6 horas de PPC manager ahorradas Y entre el 12 y el 22% del gasto mejor utilizado.

Benchmark cuantificado: en una cuenta de $33.000/mes, recuperar el 15% del gasto = $5.000/mes redirigidos hacia queries que convierten. A iso-CPA, son 5.000 / CPA conversiones bottom-funnel adicionales cada mes. En 12 meses, típicamente entre 230 y 380 conversiones adicionales, sin aumento de presupuesto. El ROI vs la inversión inicial (45 min de setup + clave API embedding) supera el 50x.

La ratio clave: el recall dividido por el tiempo invertido. Para un análisis manual de 2h, la ratio es de unos 0,25 (50% de recall / 2h). Para el pipeline IA, la ratio es de unos 6 (80% de recall / 0,2h tras setup). Es 24 veces más eficaz en la métrica que cuenta realmente — cuánto wasted spend identifica por hora de PPC manager invertida. Y esta ratio mejora aún más entre ejecuciones: en la 5.ª iteración, el sample manual se reduce a 15-25 negativos a revisar (frente a 60-80 en la primera ejecución), porque los patrones recurrentes están absorbidos por los clusters anteriores.

Medición práctica a 60 días: las cuentas que ejecutan el pipeline semanalmente convergen a un régimen estable en el que la mayoría de los negativos nuevos provienen de patrones nuevos (competidores en alza, queries estacionales, deslizamientos semánticos de la audiencia). El pipeline detecta esos patrones nuevos en los 7 días siguientes a su aparición, frente a 30-60 días en monitoreo manual — eso ahorra una ventana de 23 a 53 días de wasted spend en cada patrón emergente. Es el verdadero moat de la automatización por embeddings: velocidad de reacción, no solo recall one-shot.

Nuestro motor de auto-optimización embebe este pipeline en modo gestionado: extracción GAQL automática, embeddings hosted, clustering DBSCAN, scoring + filtrado y propuestas semanales validables en 1 clic. Para las cuentas que quieran industrializar sin programar. Vea también nuestra guía de 10 Google Ads scripts para automatización en script nativo, y nuestra guía n8n + Google Ads para planificar el pipeline como workflow self-hosted. Las complementariedades entre estos tres ángulos — pipeline IA, scripts nativos, n8n self-hosted — están detalladas en nuestra colección de prompts ChatGPT Google Ads.

Errores frecuentes a evitar al industrializar

Cinco errores se repiten al pasar a producción los pipelines IA de negativos Google Ads. Cada uno crea o bien falsos negativos (negativos mal targetizados que bloquean tráfico relevante), o bien falsos positivos (negativos no detectados). Diagnóstico y fix directo.

1. Ejecutar el pipeline sin whitelist de marca y de productos objetivo. Diagnóstico: el pipeline propone negativos que contienen sus términos de marca o nombres de sus productos estrella, porque están mal diferenciados semánticamente de las queries irrelevantes. Fix: mantenga un whitelist.txt con como mínimo las variantes de marca (palabra simple + compuestas), 10 a 20 nombres de productos objetivo, y términos comerciales fuertes. Esta whitelist sirve para el scoring de intención (intent_score) y bloquea la exportación de cualquier cluster cuya representative_query haga match parcial con la whitelist.

2. Confundir exact match y phrase match en el export de negativos. Diagnóstico: exportar un cluster en exact match sobre la representative_query bloquea solo la query exacta (10-15% del cluster), dejando que el 85-90% del cost wasted continúe. Fix: use phrase match por defecto para los clusters coherentes, y broad match para los conceptos amplios. Teste antes de hacer push haciendo query al Keyword Planner sobre el negativo propuesto: si el volumen estimado supera en 5x el volumen del cluster original, el match type es demasiado amplio.

3. Ejecutar el pipeline con demasiada frecuencia y generar ruido. Diagnóstico: un pipeline diario produce decenas de propuestas al día, de las cuales el 60-70% son reformulaciones de propuestas anteriores. La fatiga de validación empuja al equipo a validar todo sin revisión. Fix: ejecute semanalmente (lunes por la mañana), no a diario. La ventana de 7 días estabiliza los patrones y evita decisiones prematuras sobre queries one-shot. Para cuentas con frecuencia de evolución muy alta (estacionalidad fuerte), suba a bi-semanal máximo, nunca a diario.

4. Ignorar los clusters pequeños pero con waste alto. Diagnóstico: el filtro min_cluster_size: 3 excluye sistemáticamente los clusters de 1-2 queries que pueden cargar un waste alto (una query de $86 sin conversión, por ejemplo). Esos patrones aislados pasan por debajo del radar del pipeline. Fix: añada una segunda pasada que proponga las queries individuales por encima del waste_score = 60 independientemente de la pertenencia a un cluster. Estas propuestas individuales son más arriesgadas de validar en auto, así que revise manualmente antes de exportar.

5. No medir el rendimiento post-aplicación. Diagnóstico: los negativos se suben, el pipeline corre en autopilot, pero nadie verifica si el CPA y el ROAS mejoran realmente. Fix: trackee un indicador de health del pipeline: delta_cpa_30d_post_negatives (variación del CPA en los 30 días siguientes al push de N negativos). Si la variación es nula o negativa, los negativos propuestos eran marginales. Ajuste los umbrales min_waste_score y max_intent_score para apuntar a clusters de mayor impacto. En las cuentas observadas en los benchmarks públicos de Google Ads, la mejora medible aparece típicamente en las primeras 3 a 5 iteraciones y luego se estabiliza.

Para cuentas que quieran industrializar sin ejecutar el pipeline ellas mismas, nuestro módulo Auto-optimización ejecuta semanalmente el pipeline embeddings + clustering en su cuenta, propone los negativos candidatos válidos vía la UI y los aplica tras revisión. Conexión OAuth en 2 minutos, primer análisis en 5 minutos. Repo público github.com/steerads/google-ads-negatives-ai disponible para los que prefieran self-hosting, con Dockerfile y workflow n8n de ejemplo.

Fuentes

Fuentes oficiales consultadas para esta guía:

FAQ

¿Tengo que usar OpenAI o puedo quedarme 100% open-source?

Puede quedarse 100% open-source. sentence-transformers (modelo all-MiniLM-L6-v2 o multilingual-e5-base) corre localmente sobre CPU, sin clave API ni coste, con calidad suficiente para clusterizar las queries de búsqueda. La diferencia observable frente a OpenAI text-embedding-3-small: -8 a -14% de precisión en los clusters finos (separar 'presupuesto' comercial vs 'presupuesto' jurídico), pero con coste API de $0. Para cuentas que procesan menos de 5.000 queries/mes, sentence-transformers basta. Más allá, o si procesa contenido multi-idioma con acentos, text-embedding-3-small ofrece una mejor ratio calidad/esfuerzo. El pipeline soporta ambos backends vía variable de entorno.

¿Cuál es el volumen mínimo de queries para un clustering fiable?

Umbral práctico: 500 queries mínimo en la ventana de análisis (típicamente 30 días). Por debajo, DBSCAN no tiene densidad suficiente para identificar clusters estables y la mayoría de las queries salen como ruido. Sweet spot: de 2.000 a 10.000 queries en 30 días. Por encima de 10.000, divida por campaña para evitar mezclar intenciones demasiado distintas (B2B + B2C en el mismo clustering = ruido). Si su cuenta tiene menos de 500 queries/30d, alargue la ventana a 60 o 90 días.

¿DBSCAN o HDBSCAN: cuál elegir en la práctica?

HDBSCAN es generalmente superior para las queries de Google Ads: gestiona clusters de densidad variable, lo que casa con la realidad (un cluster muy denso 'gratis' + un cluster difuso 'comparativa de competidores'). DBSCAN exige fijar un único parámetro eps para todo el dataset, lo que obliga a compromisos. Sin embargo, DBSCAN sigue siendo más sencillo de parametrizar y más rápido en pequeños volúmenes (por debajo de 5.000 queries). Recomendación: empiece con DBSCAN con eps en torno a 0,15 y min_samples de 5, luego pase a HDBSCAN si los clusters parecen mal calibrados. El pipeline soporta ambos vía variable de configuración.

¿Cómo evaluar la calidad de los negativos propuestos por el pipeline antes de subir?

Tres verificaciones obligatorias antes de cualquier subida a Google Ads Editor. (1) Sample manual: revise 30-50 negativos al azar, apunte a una tasa de validación superior al 90%. (2) Whitelist: verifique que ningún término de marca, producto estrella o keyword objetivo aparece en la lista (el script debe tomar una whitelist como input). (3) Match type: verifique que el match type exportado se corresponde con la intención (phrase match para expresiones exactas, broad match para conceptos). Si menos del 90% de validación en el sample manual, ajuste los umbrales de scoring (cost_min, cluster_size_min) en lugar de subir tal cual. Itere 2-3 veces antes de apuntar al modo auto.

¿Se puede automatizar este pipeline semanalmente en n8n o Cloud Run?

Sí, y es el objetivo final para industrializar. El pipeline Python corre en menos de 3 minutos sobre 5.000 queries (CPU local) o en menos de 60 segundos vía OpenAI batch embeddings + GPU DBSCAN. Puede planificarlo en cron en Cloud Run, Lambda o como workflow n8n. Patrón recomendado: ejecución semanal (lunes por la mañana), output a un Google Sheet compartido, validación humana del sample, subida vía Google Ads Editor (o vía Google Ads API directamente si la confianza en el pipeline es alta). El repo github.com/steerads/google-ads-negatives-ai incluye un Dockerfile y un workflow n8n de ejemplo.

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