Files
chemavx-seo-tools/MANUAL-GSC.md
T
ChemaVX 33b24f33c7 seo_gsc: nombre real de la propiedad ES y qué histórico hay de verdad
Estreno con credencial. Dos cosas que solo se ven con la API delante:

La propiedad ES no es de dominio sino de prefijo de URL
(https://zonadeexclusion.com/), así que sc-domain:zonadeexclusion.com no
existía y el canario lo cazó en el paso 4. Queda anotado que ese tipo de
propiedad no ve www ni http.

Y el histórico no es de 16 meses: las dos propiedades se dieron de alta en
mayo de 2026 y el dato más antiguo es del 2026-05-09. El manual prometía
comparar contra el año pasado y eso no va a existir nunca.
2026-07-28 06:04:20 +00:00

132 lines
5.6 KiB
Markdown

# El marcador — Search Console (`seo_gsc.py`)
Lo que faltaba en toda la caja de herramientas: **datos de resultado**. El
resto mira hacia dentro (enlaces, sitemap, reglas de metas); esto mira lo único
que decide si el trabajo sirvió — cuánta gente nos encuentra y cuánta pincha.
Es de **solo lectura**. No escribe en los blogs ni en Search Console.
## Puesta en marcha (cuatro pasos de navegador, una sola vez)
La API es gratis. Hace falta una **cuenta de servicio**, no OAuth: en esta
máquina no hay navegador y el flujo interactivo no funciona headless — la misma
piedra con la que ya tropezamos en Gemini.
1. **Proyecto y API.** En <https://console.cloud.google.com> crea un proyecto
(o reutiliza uno) y activa **Google Search Console API** en
*APIs y servicios → Biblioteca*.
2. **Cuenta de servicio.** *IAM y administración → Cuentas de servicio → Crear*.
No necesita ningún rol de IAM: el permiso que importa se da en el paso 4.
Luego *Claves → Añadir clave → Crear nueva → JSON* y descarga el fichero.
3. **La clave, en su sitio.** En esta máquina:
```bash
mkdir -p ~/.config/gsc
mv ~/Descargas/EL-FICHERO.json ~/.config/gsc/service-account.json
chmod 600 ~/.config/gsc/service-account.json
```
La herramienta **se niega a arrancar** si el fichero es legible por otros.
Está fuera de cualquier repo; no la metas en git.
4. **Permiso en Search Console.** Este es el paso que se olvida. Para **cada
una de las dos propiedades** (`theexclusionzone.com` y
`zonadeexclusion.com`): *Configuración → Usuarios y permisos → Añadir
usuario* → pega el `client_email` de la credencial (algo como
`nombre@proyecto.iam.gserviceaccount.com`) → permiso **Restringido**, que
basta para leer.
⚠️ Si `zonadeexclusion.com` no está dada de alta en Search Console, hay que
verificarla antes. Del blog ES no había ni una sola exportación, así que es
probable que ni exista la propiedad.
5. **Arrancar el vigilante.** El timer se instala **parado a propósito**: sin
credencial fallaría cada lunes, y un timer que falla siempre enseña a
ignorar los avisos. Se enciende cuando el canario pasa:
```bash
seo-gsc comprueba && sudo systemctl enable --now seo-gsc-watch.timer
```
Comprobación:
```bash
seo-gsc sitios # tienen que salir las dos propiedades
seo-gsc comprueba # canario: recorre el camino real eslabón por eslabón
```
Si el nombre que devuelve `sitios` no coincide con el configurado (puede ser
`sc-domain:x.com` o `https://www.x.com/`, con barra final), corrige el
diccionario `SITIOS` en `seo_gsc.py` con el nombre exacto.
Es lo que pasó al estrenarlo: las dos propiedades **no son del mismo tipo**. EN
es de dominio y ES es de prefijo de URL (`https://zonadeexclusion.com/`), que
solo ve lo que cuelga de ese prefijo exacto — ni `www`, ni `http`. Sirve porque
el canónico del ES es el apex, pero si algún día se publica bajo `www` no
aparecería aquí. Darla de alta como propiedad de dominio lo arreglaría de raíz.
## Uso diario
```bash
seo-gsc pull # descarga y acumula en SQLite (idempotente)
seo-gsc # sin argumentos = informe de 28 días
seo-gsc informe --dias 7
```
La primera descarga pide **16 meses**, que es todo lo que Google guarda, pero
lo que llega es lo que haya. Medido el 2026-07-28: el dato más antiguo es del
**2026-05-09** en las dos propiedades, porque se dieron de alta entonces. Google
no guarda nada de antes de que exista la propiedad, así que **no hay histórico
anterior a mayo de 2026 y nunca lo habrá**. Cuidado con leer «16 meses» y creer
que se puede comparar contra el año pasado.
### La pregunta pendiente
El remate de metas fue el **23 de junio** y los únicos datos que había eran del
17. En cuanto haya credencial:
```bash
seo-gsc antes-despues --corte 2026-06-23 --dias 28
```
## Qué mira el informe
- **Movimiento** de clics, impresiones y CTR contra el periodo anterior.
- **Páginas que posicionan y no se pinchan.** Es la lista que importa: si algo
está en posición 6 con 2.400 impresiones y 0,16% de CTR, no tiene un problema
de posicionamiento, tiene un problema de titular. Cada línea estima los clics
que faltan si el CTR fuese el normal de esa posición.
- **Consultas con impresiones y cero clics**, que son temas donde ya salimos y
no convencemos.
El CTR "normal" sale de una curva de referencia del sector, no de una medición
nuestra: **sirve para ordenar candidatas, no para prometer tráfico**. Solo se
avisa por encima de 150 impresiones, porque por debajo el CTR es ruido.
## Automático
`seo-gsc-watch.timer` — lunes 06:15 UTC: descarga y manda el informe por
Telegram, pero **solo si hay páginas desperdiciadas y el informe ha cambiado**
desde el último aviso. Misma disciplina que `seo-watch`: si no hay nada que
decir, se calla.
```bash
systemctl status seo-gsc-watch.timer
journalctl -u seo-gsc-watch -n 40
```
## Notas de implementación
- **Sin librerías de Google.** El JWT se firma con PyJWT y se canjea a mano.
Son treinta líneas y evita arrastrar media docena de dependencias para tres
peticiones.
- **Los datos tardan 2-3 días en consolidarse.** Todo termina 3 días atrás y se
pide `dataState=final`; pedir "ayer" devuelve cifras que luego cambian solas.
- **La posición se pondera por impresiones.** Promediar posiciones a pelo da el
mismo peso a un día de 2 impresiones que a uno de 500.
- **La API pagina de 25.000 en 25.000** y no avisa de que quedan más filas.
- El almacén es SQLite en `~/.local/state/seo-gsc/gsc.db`; `pull` es idempotente
y resolapa un día por si el último se consolidó después.