Files
fn_registry/docs/capabilities/seo.md
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

4.6 KiB

Capability: seo

SEO orientado a datos sobre Google Search Console (GSC): autenticar contra la Search Console API con una cuenta de servicio, extraer Search Analytics (impresiones, clicks, CTR, posición por query y página) y aterrizarlo en DuckDB (verdad acumulada) + Postgres (espejo para Metabase). Es la cadena de ingesta del proyecto seo_analytics.

La tesis del grupo: el SEO deja de hacerse a ciegas y se convierte en un problema de datos con loop medible — el dashboard señala la oportunidad (striking distance, CTR bajo, content decay), se aplica el cambio y se mide el impacto en la siguiente ingesta.

Funciones

ID Firma Qué hace
gsc_auth_py_infra gsc_auth(credentials_path="", subject="") -> service Autentica contra la Search Console API v1 con una service account JSON (scope webmasters.readonly). Fallback a env GSC_SA_JSON. Devuelve el service de googleapiclient listo para consultar.
pull_gsc_search_analytics_py_datascience pull_gsc_search_analytics(service, site_url, start_date, end_date, dimensions=None, row_limit=25000, max_total_rows=0, search_type="web") -> list[dict] Extrae Search Analytics paginando (startRow) hasta agotar. Aplana cada fila (keys → nombres de dimensión + clicks/impressions/ctr/position). dimensions por defecto ["query","page"].
ingest_gsc_search_analytics_py_pipelines ingest_gsc_search_analytics(site_url="", duckdb_path="", pg_dsn="", start_date="", end_date="", lookback_days=5, credentials_path="") -> dict Pipeline: auth → pull (dims date,query,page) → upsert idempotente en DuckDB → espejo a Postgres (mode=replace). Resuelve defaults de env (GSC_SITE_URL, SEO_DSN, GSC_SA_JSON). Lo invoca el DAG seo-gsc-daily.

Ejemplo canónico (end-to-end)

# Greenfield: ver projects/seo_analytics/docs/SETUP.md para crear la service account,
# verificar la propiedad en Search Console y darle acceso a la SA.

# 1. Variables (el .env del proyecto las agrupa)
export GSC_SITE_URL="sc-domain:ejemplo.com"
export SEO_DSN="postgresql://captacion:PASS@localhost:5433/seo"
export GSC_SA_JSON="$HOME/.config/seo/gsc-sa.json"

# 2. Ingesta diaria (auth + pull + DuckDB + espejo Postgres) — la corre el DAG seo-gsc-daily
python/.venv/bin/python3 python/functions/pipelines/ingest_gsc_search_analytics.py

# 3. Dashboards en Metabase (una vez): añade la DB seo + 4 cards + dashboard
SEO_PG_PASS=... METABASE_USER=... METABASE_PASS=... \
  python/.venv/bin/python3 projects/seo_analytics/setup_metabase.py

Uso desde Python, componiendo las tres:

import sys; sys.path.insert(0, "python/functions")
from infra import gsc_auth
from datascience import pull_gsc_search_analytics

svc = gsc_auth()  # lee GSC_SA_JSON
rows = pull_gsc_search_analytics(svc, "sc-domain:ejemplo.com",
                                 "2026-05-01", "2026-05-28",
                                 dimensions=["date", "query", "page"])
print(len(rows), rows[0])

Fronteras

  • NO hace keyword research ni rank tracking externo. GSC dice por qué keywords ya apareces en Google; descubrir keywords nuevas o medir SERP de competidores es otro trabajo (scrapers).
  • NO escribe los dashboards. Las cards/dashboard de Metabase los construye el script del proyecto setup_metabase.py componiendo el grupo metabase. Este grupo solo ingiere datos.
  • NO gestiona el scheduling. Eso es dag_engine (DAG seo-gsc-daily, grupo scheduler).
  • NO cubre Bing/otros buscadores. Solo Google Search Console.

Gotchas del grupo

  • Los datos de GSC llegan con ~2-3 días de lag. El pipeline pide hasta hoy menos 3 días.
  • Google anonimiza queries de baja frecuencia (privacy threshold): la suma por query no cuadra con el total del sitio. Es esperado, no un bug.
  • El formato de site_url importa: sc-domain:ejemplo.com (propiedad de dominio) vs URL completa con esquema (propiedad de prefijo).
  • La service account accede porque su email está añadido como usuario en Search Console (Settings > Users), no por domain-wide delegation. El JSON de la SA es un secreto.
  • DuckDB es la verdad (upsert idempotente, acumula histórico); Postgres es un espejo que se regenera por replace en cada sync. No acumular en Postgres directamente.

Prerequisitos

  • Sitio verificado en Search Console + service account con acceso (ver SETUP.md del proyecto).
  • Stack Postgres + Metabase del proyecto captacion_clientes (contenedores captacion-postgres :5433 y captacion-metabase :3030), con la DB seo creada.
  • Deps Python google-api-python-client + google-auth (ya en el venv del registry).