seo: quién enlaza HACIA un post, que es lo que decide si Google lo encuentra
Toda la caja miraba los enlaces en un solo sentido — a quién enlazo yo — y
esa es la pregunta del lector, no la de Google. Dos posts de EN publicados
el 21-jul seguían siendo «URL is unknown to Google» una semana después:
tenían enlaces entrantes, pero solo desde artículos con 8 y 12 impresiones
de por vida, páginas que Google casi no visita.
seo_semantic gana dos subcomandos: `padrinos <slug>`, que ordena candidatos
por tráfico REAL del origen (Search Console) en vez de por similitud, y
`descubrimiento`, que lista los publicados a los que no llega ni un enlace
desde el tercio fuerte del sitio. Salen 21 de 32 en EN y 21 de 31 en ES.
Ambos descartan los posts con canonical_url propio: Ghost los excluye del
sitemap por consolidados, así que apadrinar desde ahí no sirve de nada — el
de Grusch de mayo tiene 1.728 impresiones y habría encabezado la lista.
seo_gsc gana `inspecciona`, que pregunta el veredicto a Google en vez de
deducirlo. Es lo que separa «posiciona mal» de «no lo ha visto nunca», que
son problemas opuestos y se arreglan al revés.
Y el checklist del remate incorpora el paso 3b: el informe tiene que traer
el comando de enlace entrante listo para copiar. No lo aplica el agente
porque eso es editar otro post publicado, y eso sigue prohibido.
⚠️ Anotado en el docstring: contar enlaces internos desde el HTML público da
«cero huérfanos», porque el tema mete navegación y feed de relacionados que
parecen enlaces del cuerpo. La verdad está en el html del CLI de Ghost.
This commit is contained in:
+46
@@ -41,6 +41,11 @@ Subcomandos:
|
||||
Compara la misma ventana antes y después de una fecha. Escrito para
|
||||
responder de una vez si el remate de metas del 23-jun sirvió de algo.
|
||||
|
||||
seo_gsc.py inspecciona <slug…> --site en|es
|
||||
El veredicto de Google sobre una URL: indexada, rastreada cuándo, y a
|
||||
qué canoniza. Distingue «posiciona mal» de «no lo ha visto nunca», que
|
||||
son problemas opuestos. Sale con código 1 si alguna no está indexada.
|
||||
|
||||
seo_gsc.py comprueba
|
||||
Canario: recorre el camino REAL (credencial → firma → token → API) y
|
||||
dice en qué eslabón exacto se rompe. No simula nada.
|
||||
@@ -449,6 +454,42 @@ def cmd_antes_despues(a):
|
||||
|
||||
# ──────────────────────────────── utilidades ────────────────────────────────
|
||||
|
||||
def cmd_inspecciona(a):
|
||||
"""¿Conoce Google esta URL? Veredicto suyo, no deducción nuestra.
|
||||
|
||||
Es la única forma de distinguir «posiciona mal» de «no lo ha visto». El
|
||||
2026-07-28 dos posts de EN publicados una semana antes salieron con «URL is
|
||||
unknown to Google»: nunca rastreados. Sin esto se habría confundido con un
|
||||
problema de contenido y se habrían reescrito titulares para nada.
|
||||
"""
|
||||
import requests
|
||||
tok = token(carga_credencial())
|
||||
prop = SITIOS[a.site]["propiedad"]
|
||||
base = ("https://www.theexclusionzone.com/" if a.site == "en"
|
||||
else "https://zonadeexclusion.com/")
|
||||
malas = 0
|
||||
for slug in a.slugs:
|
||||
url = slug if slug.startswith("http") else f"{base}{slug.strip('/')}/"
|
||||
r = requests.post(
|
||||
"https://searchconsole.googleapis.com/v1/urlInspection/index:inspect",
|
||||
headers={"Authorization": f"Bearer {tok}"}, timeout=60,
|
||||
json={"inspectionUrl": url, "siteUrl": prop})
|
||||
if r.status_code != 200:
|
||||
print(f" ✗ {r.status_code} {url}\n {r.text[:200]}")
|
||||
malas += 1
|
||||
continue
|
||||
i = r.json()["inspectionResult"]["indexStatusResult"]
|
||||
ok = i.get("verdict") == "PASS"
|
||||
malas += 0 if ok else 1
|
||||
print(f" {'✓' if ok else '⚠'} {i.get('coverageState', '?')}")
|
||||
print(f" rastreo {i.get('lastCrawlTime', '—')[:10]} "
|
||||
f"robots {i.get('robotsTxtState', '?')}")
|
||||
if i.get("googleCanonical") and i["googleCanonical"] != url:
|
||||
print(f" ⚠ Google canoniza a: {i['googleCanonical']}")
|
||||
print(f" {url}")
|
||||
return 1 if malas else 0
|
||||
|
||||
|
||||
def cmd_sitios(a):
|
||||
sa = carga_credencial()
|
||||
print(f"cuenta de servicio: {sa['client_email']}")
|
||||
@@ -555,6 +596,11 @@ def main():
|
||||
p.add_argument("--site", choices=("en", "es", "todos"), default="todos")
|
||||
p.set_defaults(func=cmd_antes_despues)
|
||||
|
||||
p = sub.add_parser("inspecciona", help="¿conoce Google estas URLs?")
|
||||
p.add_argument("slugs", nargs="+", help="slugs o URLs completas")
|
||||
p.add_argument("--site", choices=("en", "es"), required=True)
|
||||
p.set_defaults(func=cmd_inspecciona)
|
||||
|
||||
p = sub.add_parser("comprueba", help="canario del camino real")
|
||||
p.set_defaults(func=cmd_comprueba)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user