SEO migration planning: URL mapping, redirect chain validation, backlink preservation, pre/post migration checklists. Triggers on: /seo migration, "migración", "cambio de dominio", "rediseño", "cambio de CMS", "nueva web", "redirect mapping", "301".
Site migrations are the #1 cause of catastrophic traffic loss. This skill prevents that.
| Type | Risk | Key concern |
|---|---|---|
| Domain change (old.com → new.com) | 🔴 VERY HIGH | All authority transfer depends on redirects |
| CMS change (WP → Shopify, etc.) | 🔴 HIGH | URL structure usually changes completely |
| HTTPS migration (http → https) | 🟡 MEDIUM | Must redirect ALL variants |
| Redesign (same CMS, new URLs) | 🟡 MEDIUM | Internal linking + URL structure |
| Subdomain change (blog.x → x/blog) | 🟠 HIGH | Google treats subdomains as separate sites |
| Consolidation (merge 2 sites) | 🔴 VERY HIGH | Content overlap, redirect complexity |
sources = [
# 1. Crawl data (most complete)
crawl_urls, # From /seo crawl
# 2. Sitemap URLs
sitemap_urls, # Parse XML sitemap
# 3. GSC indexed URLs (if available)
gsc_urls, # Pages with impressions
# 4. URLs with external backlinks
backlink_landing_pages, # From DataForSEO/Ahrefs
# 5. Analytics top pages
ga_top_pages, # High-traffic pages
]
# Union of all sources = master URL list
# This is CRITICAL: missing URLs = lost traffic
# For each old URL, determine new URL:
mapping = {
"https://old.com/servicios/seo/": "https://new.com/services/seo/",
"https://old.com/blog/post-1/": "https://new.com/blog/post-1/",
# ...
}
# Auto-mapping heuristics:
# 1. Exact slug match → likely same page
# 2. Similar title/H1 → content match
# 3. Same parent category → structural match
# 4. No match → needs manual mapping or 410 (Gone)
checks = [
# No old URL mapped to multiple new URLs
no_duplicate_targets(mapping),
# No redirect chains (A→B→C)
no_chains(mapping),
# No redirect loops (A→B→A)
no_loops(mapping),
# All high-traffic pages mapped
high_traffic_covered(mapping, gsc_data),
# All pages with backlinks mapped
backlinked_pages_covered(mapping, backlink_data),
# Homepage mapped
homepage_mapped(mapping),
# HTTP → HTTPS variants included
protocol_variants_included(mapping),
]
# Individual redirects
Redirect 301 /old-page/ https://new.com/new-page/
# Pattern-based
RedirectMatch 301 ^/blog/category/(.*)$ https://new.com/blog/$1
# Regex for complex patterns
RewriteRule ^servicios/(.*)$ https://new.com/services/$1 [R=301,L]
# Individual
rewrite ^/old-page/$ https://new.com/new-page/ permanent;
# Pattern
rewrite ^/blog/category/(.*)$ https://new.com/blog/$1 permanent;
The skill generates ready-to-use redirect rules from the mapping:
def generate_htaccess(mapping):
rules = []
for old_url, new_url in mapping.items():
old_path = urlparse(old_url).path
rules.append(f"Redirect 301 {old_path} {new_url}")
return "\n".join(rules)
Run these checks after the new site is live:
post_migration_checks = {
"redirects_working": {
# For each mapping entry: GET old URL
# Verify: final destination matches mapped new URL
# Verify: status code is 301 (not 302!)
# Verify: no chains (max 1 hop)
},
"new_urls_accessible": {
# GET each new URL
# Verify: returns 200
# Verify: canonical points to itself
# Verify: not blocked by robots.txt
},
"sitemap_updated": {
# New sitemap exists at new domain
# Contains new URLs, not old ones
# Submitted to GSC
},
"gsc_property_added": {
# New domain/property added to GSC
# Change of address filed (if domain change)
},
"internal_links_updated": {
# Crawl new site
# Check: no internal links pointing to old URLs
# Check: no internal links going through redirects
},
"canonical_tags": {
# All pages have canonical pointing to new URL (not old)
},
"hreflang_updated": {
# If multi-language: hreflang points to new URLs
},
"schema_updated": {
# JSON-LD @id, url, sameAs point to new domain
},
}
🔄 Plan de Migración: old.com → new.com
Tipo: Cambio de dominio + rediseño
Riesgo: 🔴 MUY ALTO
📊 INVENTARIO
├── URLs en crawl: 312
├── URLs en sitemap: 289
├── URLs con impresiones GSC: 198
├── URLs con backlinks externos: 87
├── Total URLs únicas: 334
└── URLs mapeadas: 312/334 (93%)
⚠️ URLs SIN MAPEAR (22):
├── /blog/post-antiguo-2019/ — 0 tráfico, 0 backlinks → 410 Gone
├── /tag/keyword/ — noindex, sin valor → no redirigir
└── ... (20 más — revisar manualmente)
🚨 URLS CRÍTICAS (deben mapearse PERFECTO):
├── / (homepage) — 45,000 imp/mes, 23 backlinks
│ → https://new.com/ ✅ Mapeada
├── /servicios/seo/ — 12,000 imp/mes, 15 backlinks
│ → https://new.com/services/seo/ ✅ Mapeada
└── ... (top 20 por impacto)
📄 ARCHIVOS GENERADOS:
├── redirect-map.csv (334 filas: old_url, new_url, priority)
├── .htaccess (reglas 301 listas para copiar)
└── post-migration-checklist.md
📋 CRONOGRAMA:
1. [PRE] Verificar mapping completo con el equipo
2. [PRE] Hacer crawl de referencia del sitio actual
3. [DÍA D] Implementar redirects + lanzar nueva web
4. [D+1] Ejecutar /seo migration validate old.com new.com
5. [D+1] Enviar sitemap nuevo a GSC + Change of Address
6. [D+7] Monitorizar tráfico GSC vs baseline
7. [D+30] Segundo check de indexación