Caso: poner cardonaseo.com en producción sin depender del panel
Por Carlos Alberto Cardona B. · publicado el
Este caso es este mismo sitio. Lo cuento porque una migración de dominio es la forma más rápida de desaparecer de Google, y porque todo lo que afirmo aquí lo puedes comprobar con un comando.
Es también el caso más parecido a lo que un equipo pide cuando dice «site migration, redirects, JavaScript rendering»: pasos medidos antes y después, y lo no medido escrito como pendiente.
Qué se buscaba solucionar
El 15 de septiembre por la mañana, cardonaseo.com no resolvía: la zona en Cloudflare tenía cero registros DNS. El único host vivo era la URL de la plataforma, y servía noindex, como debe.
Había algo peor que un dominio caído. Base44 entrega a los rastreadores una plantilla de unas 350 palabras que no es el contenido de la página, y su sitemap y su llms.txt incluían /gracias y /privacidad, dos páginas noindex. Dos ficheros del mismo sitio diciendo cosas distintas sobre las mismas URLs.
DNS: cero registros en la zona; www devolvía NXDOMAIN.
Renderizado: las 15 rutas servían el mismo cuerpo al rastreador; el contenido real solo aparecía en el DOM renderizado.
Sitemap y llms.txt: listaban páginas noindex y describían cada una con una plantilla («Blog Core Web Vitals page»).
Metadatos sociales: cero etiquetas Open Graph, así que un enlace compartido en LinkedIn salía sin título ni descripción.
Qué se hizo
Primero una fase de solo lectura: DNS, zona, cabeceras, HTML pedido con el agente de Googlebot, HTML crudo y DOM renderizado. Nada se cambió hasta tener el inventario. Después, los cambios, uno por uno y con su medición.
Confirmé por RDAP el registrador y la fecha de alta del dominio antes de tocar nada: el plan decía IONOS y el registro decía Cloudflare.
Desenlacé el dominio de la plataforma por la vía documentada (el panel), no por un endpoint sin documentar que podía borrar en vez de desenlazar.
Puse el Worker como dominio personalizado y no como ruta: con el origen en otra zona de Cloudflare, una ruta no funciona. Cerré workers.dev y las URLs de vista previa.
Prerender propio: el build genera un HTML por ruta desde los componentes reales y falla si un H1 no cuadra o si se cuela código. El Worker reescribe /ruta a /ruta/index.html sin cambiar la URL.
301 de www al apex y de las barras finales; 404 real para toda ruta fuera del manifiesto; sitemap y llms.txt derivados del mismo manifiesto, sin páginas noindex.
Open Graph y Twitter Card en el HTML servido, y datos estructurados con @id estables para que las páginas se referencien entre sí (commit del 17-sep).
$ curl -sI https://www.cardonaseo.com/ | grep -i locationlocation: https://cardonaseo.com/ (301)$ curl -sI https://cardonaseo.com/portafolio/ | grep -i locationlocation: https://cardonaseo.com/portafolio (301)$ curl -s -o /dev/null -w "%{http_code}" https://cardonaseo.com/no-existe-123404$ curl -s -A "Googlebot" https://cardonaseo.com/ | wc -w574 palabras visibles, 1 <h1>, 3 bloques JSON-LD
Cómo resultó tiempo después
Cuatro días después de indexarse no hay tráfico que mostrar, y no lo voy a maquillar. Lo que sí hay es salud del borde y el estado de cada discrepancia que dejé abierta el 15 de septiembre.
9.820
peticiones atendidas por el Worker del 15 al 19 de septiembre
Cloudflare GraphQL Analytics, Worker cardonaseo-edge-router
0
errores en esas peticiones
leído el 19-sep-2026
0,93 ms
CPU mediana por petición (p99: 3,65 ms)
14 días · Cloudflare
Peticiones diarias al Worker de cardonaseo.com desde la puesta en producción
Incluye rastreadores, navegadores y mis propias verificaciones. No es tráfico de personas: es la prueba de que el borde responde.
Fuente: Cloudflare GraphQL Analytics, Worker cardonaseo-edge-router · leído el 2026-09-19
Ver los valores del gráfico
| Semana del | Peticiones |
|---|---|
| 2026-09-15 | 1060 |
| 2026-09-16 | 1760 |
| 2026-09-17 | 1700 |
| 2026-09-18 | 3140 |
| 2026-09-19 | 2160 |
Las 7 discrepancias de la auditoría del 15-sep-2026 y su estado el 19-sep-2026
| Discrepancia | Lectura del 15-sep | Estado el 19-sep |
|---|---|---|
| Sitemap | Servido con 200; GSC decía «no se ha podido leer» | Servido con 200 y cabecera autoritativa (curl). Lectura en GSC: pendiente de confirmar en la interfaz |
| robots.txt | Servido con 200; GSC decía «no hay archivo» | Servido con 200 y la línea Sitemap correcta. Informe de GSC: pendiente |
| Indexación de la portada | API: «rastreada, sin indexar». Interfaz: «está en Google» | Confirmada: la portada tiene impresiones en la API de GSC desde el 15-sep |
| Beacon de analítica inyectado en el borde | Presente en lo servido, ausente en el origen | Pendiente: origen sin confirmar; afecta a la política de privacidad |
| Assets y API bajo el dominio | Googlebot los pidió al renderizar; sin medir | Pendiente de medir qué responde el Worker |
| noindex en la URL de la plataforma | Dos lecturas contradictorias el mismo día | Cerrada: histórica, sin impacto |
| Open Graph | Cero etiquetas en las 15 rutas (17-sep) | Resuelta: en el HTML servido desde el commit del 17-sep |
Google Search Console (API), propiedad de dominio · 20-ago a 17-sep-2026 · 10 impresiones y 1 clic en total · cuatro días desde la indexación
| Página | Clics | Impresiones | Posición media |
|---|---|---|---|
| / | 1 | 2 | 1,0 |
| /sobre-mi | 0 | 3 | 4,3 |
| /blog/core-web-vitals | 0 | 5 | 77,6 |
| /portafolio/seo-app-react-base44 | 0 | 1 | 5,0 |
| /portafolio/investigacion-de-keywords | 0 | 1 | 7,0 |
| /blog/mi-pagina-no-aparece-en-google | 0 | 1 | 7,0 |
| /auditoria-seo | 0 | 1 | 100,0 |
Lo que aprendí, incluidos mis errores
Una búsqueda de texto sobre un fichero de configuración devolvió en claro una clave de API en el registro de la sesión. Nadie la usó, pero quedó escrita: la regla nueva es buscar por nombre de servidor, nunca por fichero completo, y rotar la clave en vez de esperar.
Un script de la fase de lectura escribió cinco ficheros dentro del árbol del repositorio mientras el informe decía «no se cambió nada». Los datos no se vieron afectados, pero la frase era falsa. Ahora los temporales van fuera del repo, siempre.
Y un asistente afirmó que pulsar «Verificar» en la plataforma había recreado los registros DNS. Era falso: lo que escribió DNS fue enlazar el dominio, a otra hora. Lo que dice un panel, o un asistente, no es evidencia hasta que la API lo confirma.
Si quieres comprobarlo tú
Todo lo de arriba responde desde tu terminal. Si algo no coincide, escríbeme: prefiero enterarme por ti que por Search Console.
curl -sI https://www.cardonaseo.com/ | grep -iE 'HTTP|location'→ 301 hacia https://cardonaseo.com/curl -s https://cardonaseo.com/sitemap.xml | grep -c '<loc>'→ exactamente las páginas indexables, sin /gracias ni /privacidadcurl -s -A "Googlebot" https://cardonaseo.com/portafolio | grep -c "<h2"→ los encabezados reales, no una plantilla
El mismo método, aplicado al sitio de un cliente, está en el caso de la app en React que Google recibía vacía.
Cómo decidí qué vender antes de publicar este sitio: la investigación de keywords.
Esto es lo primero que reviso en la auditoría SEO técnica.
Qué no puedo afirmar
No afirmo tráfico: son 10 impresiones en cuatro días. No sé quién escribió los registros DNS que aparecieron en la zona la madrugada del 15 de septiembre: el token no tenía acceso al registro de auditoría de Cloudflare, y lo dejé escrito en vez de suponerlo.
Tampoco afirmo que el sitemap ya esté leído por Google: el servidor lo entrega bien, pero el informe de Search Console se relee en la interfaz, que la API no expone.
Próxima medición
Las fechas van escritas antes de tener el dato. Si en esa fecha no actualizo esta página, reclámamelo.
| Fecha | Qué se mide |
|---|---|
| Releer las 7 discrepancias; impresiones de 30 días; informe de sitemap y robots en la interfaz de GSC |