Site Migrations
Domain, platform, HTTPS, redesign, restructure migrations. Pre-migration audits, URL mapping, redirect implementation, the Change of Address tool, and recovery playbooks.
A site migration is the highest-stakes operation in SEO. The expected traffic outcome at a competent migration is a 2–6 week dip of 10–25% recovering to baseline at week 8–12; an incompetent one drops 60–90% and may never recover. The difference between the two outcomes is rarely the framework choice, the design, or the platform — it is the URL mapping spreadsheet, the redirect strategy, and the post-launch monitoring discipline. This module is the migration playbook ordered by what kills sites most often.
TL;DR
- The URL mapping spreadsheet is the migration. Every other decision flows from it. Build it before you write a line of new code.
- 301 every old URL to the most relevant new URL — never to the homepage. Bulk-redirecting to the homepage is the single most common cause of catastrophic migration loss.
- Two GSC properties for at least 90 days post-launch. Old and new domains both monitored, both submitting sitemaps, both watching index coverage.
The mental model
A site migration is like moving a library to a new building. Books are URLs; the catalogue is your sitemap; the shelves are your IA; readers are users; the librarian is Google. A successful move means every reader who walks into the old address is escorted to the same book in the new address — a 301 to the equivalent. A failed move means the library reopens with all the books in storage and a sign on the door saying “we moved — find what you want yourself.”
Three forces decide the outcome:
- URL continuity. Every old URL must reach a new URL with equivalent content via a 301. Volume isn’t the problem; correctness is. A 50,000-URL migration with 49,500 perfect mappings and 500 wrong ones loses signal proportional to the wrong ones.
- Content continuity. The destination of each redirect should contain content substantively equivalent to the source. Redirecting
/blog/article-xto/blog/(a category) is technically a 301 but counts as a soft 404 — Google detects it and drops the old URL’s signal. - Crawl re-discovery. Google has to crawl every old URL to see the 301, then crawl the new URL to absorb the signal. For big sites this takes weeks. Accelerating re-discovery is the single highest-leverage post-launch task.
Deep dive: the 2026 reality
Migration types and their relative risk:
| Type | Example | Risk | Typical recovery |
|---|---|---|---|
| HTTPS migration | http:// → https:// | Low if done in 2026 (most are already done) | 2–4 weeks |
| Redesign without URL change | New theme, same URLs | Low | 2–4 weeks (Page Experience can shift) |
| Platform migration with same URLs | WordPress → Astro, identical paths | Medium | 4–8 weeks |
| URL restructure | /products/widgets/ → /widgets/ | High | 6–12 weeks |
| Domain migration | oldbrand.com → newbrand.com | High | 8–16 weeks |
| Combined (domain + platform + URL restructure + redesign) | The “we did everything at once” disaster | Extreme | 12+ weeks if at all |
Rule one of safe migrations: never combine more than two changes. Domain change alone — fine. Platform change alone — fine. Domain + platform + URL restructure — you’ve stacked the failure modes and the recovery, if it happens, takes a year.
Pre-migration audit (4–6 weeks before launch)
The five lists you must produce:
- All current URLs that earned at least one organic click in the last 90 days. Pull from Google Search Console (90-day Performance export) and Bing Webmaster Tools. This is the floor of URLs that must redirect cleanly.
- All current URLs with at least one referring domain. Pull from Ahrefs (
Best by linksorBacklinksreport) or Majestic. These carry inbound link equity; losing them is permanent equity loss. - All current URLs in the XML sitemap. Submit the current sitemap to Screaming Frog → Mode → List and crawl it.
- All current URLs that exist but rank for nothing. Crawl the site with Screaming Frog, subtract lists 1–3. These are candidates for
410 Gonerather than redirect — pruning is healthy at migration time. - All current URLs returning 4xx or 5xx today. Fix or 410 these before migration; carrying them forward as redirects amplifies the noise.
URL mapping
# Generate a master URL inventory
# Combine GSC export, Ahrefs export, and Screaming Frog crawl
cat gsc-90d.csv ahrefs-backlinks.csv sf-crawl.csv \
| awk -F',' '{print $1}' \
| sort -u > all-old-urls.txt
wc -l all-old-urls.txt # Your migration scope
For each old URL, the spreadsheet must specify:
| Old URL | New URL | Mapping confidence | Equivalence | Notes |
|---|---|---|---|---|
/blog/seo-guide-2024 | /guides/seo | High | Same content, refreshed | Manual review |
/products/widget-x100 | /widgets/x100 | High | Same product | Pattern-mapped |
/category/pdf-tools | /tools/pdf | High | Same category, deeper IA | Pattern-mapped |
/blog/discontinued-feature | 410 Gone | High | Content removed deliberately | Explicit prune |
/old-thing | ? | Low | No new equivalent | Manual decision required |
Every “Low confidence” row needs a human decision before launch. Bulk-mapping low-confidence rows to the homepage is the failure mode that destroys migrations. The right call is usually one of: map to nearest equivalent, map to relevant category, or 410.
301 implementation
The 301 chain rule: never redirect through more than one hop. A → B → C becomes A → C directly. Long chains lose signal at each hop, and Google may stop following at the third.
# Bulk redirects in nginx using a map for performance
map $request_uri $new_uri {
default "";
~^/blog/seo-guide-2024/?$ /guides/seo/;
~^/products/widget-(.+)/?$ /widgets/$1/;
~^/category/pdf-tools/?$ /tools/pdf/;
~^/old-feature/?$ 410;
}
server {
listen 443 ssl http2;
server_name newbrand.com;
if ($new_uri = "410") {
return 410;
}
if ($new_uri != "") {
return 301 https://newbrand.com$new_uri;
}
# ... normal handling
}
For domain migrations, the old domain must keep serving 301s for at least 12 months, ideally indefinitely. Letting the old domain expire mid-migration is the second-most-common catastrophic mistake.
The Change of Address tool
Google’s Change of Address (CoA) tool in Search Console (search.google.com/search-console/settings/change-of-address) is required for domain migrations only. It tells Google to expedite the consolidation of signals from old to new. Requirements:
- Both properties verified in Search Console.
- Old domain serving valid 301s on every URL.
- New domain accessible to Googlebot and serving 200s.
- Both
https://example.com/andhttps://www.example.com/(or whichever applies) verified separately.
CoA does not speed up indexing — it only tells Google’s de-duplication system to consolidate faster. You still need sitemaps, internal links, and external links pointing at the new domain.
Post-migration monitoring
Day 0 (launch day):
- Submit new XML sitemap to Search Console → Sitemaps.
- Submit
<loc>URLs to Bing Webmaster Tools and via IndexNow API. - Verify 301s on a sample of 100 random old URLs with
curl -I. - Confirm the new site’s
robots.txtis not blocking critical paths.
Days 1–14:
- Daily check Search Console → Indexing → Pages on both old and new properties.
- Watch the new property’s “Indexed” count rise and old property’s drop in tandem.
- Watch GSC Performance for both properties — old should decline, new should rise; the sum should be roughly stable.
Days 15–60:
- Re-crawl the entire new site with Screaming Frog weekly to catch broken links, missing canonicals, redirect chains.
- Track top 100 keyword rankings in Ahrefs Rank Tracker or Semrush Position Tracking.
- File disavow file resubmission if you migrated to a new domain — old disavows do not transfer.
Days 60–120 (recovery window):
- Compare Search Console clicks to pre-migration baseline. Expect 80–95% recovery by day 60, full or above by day 90.
- If recovery stalls below 80%, audit the URL mapping spreadsheet for redirect errors and content-equivalence problems.
Recovery from a failed migration
Symptoms of a failed migration: sustained traffic loss >30% beyond week 6, “Discovered - currently not indexed” growing, manual action notification, or “soft 404” errors on redirects.
The recovery sequence:
- Audit redirects. Run the old URL inventory through Screaming Frog → List Mode. Every redirect that returns 200 elsewhere or hits a soft 404 is a remediation ticket.
- Fix content equivalence. Where the new destination doesn’t match the old in content, either improve the new page or change the redirect target.
- Resubmit. New sitemap, GSC URL Inspection on top URLs (
Request Indexing), IndexNow ping for everything. - Wait. Recovery from a fixed migration takes another 4–8 weeks. The data tells you whether you’re recovering or stuck.
- If stuck >12 weeks after fixes, consider rolling back the URL structure changes and re-migrating later as a separate operation.
The 2026 AI-search consideration: ChatGPT Search (via Bing), Perplexity, and Gemini all rebuild their understanding of your site from a fresh crawl after migration. AI citation recovery often lags Google indexing recovery by 2–4 weeks because AI systems cache embeddings and don’t refresh them as aggressively as classic indexes.
Visualizing it
flowchart TD
A[Pre-migration audit] --> B[Build URL mapping spreadsheet]
B --> C[Manual review every low-confidence row]
C --> D[Implement 301s on staging]
D --> E[Verify with Screaming Frog list mode]
E --> F[Launch]
F --> G[Submit new sitemap to GSC and Bing]
G --> H[For domain change: Change of Address tool]
H --> I[Daily monitoring days 1-14]
I --> J{Recovery on track?}
J -->|Yes| K[Weekly monitoring days 15-90]
J -->|No| L[Audit redirects, content equivalence]
L --> M[Resubmit sitemap and request indexing]
M --> J
K --> N[Full recovery weeks 8-12]
Bad vs. expert
The bad approach
# "We're moving everything; just send them all to the homepage"
server {
listen 443 ssl;
server_name oldbrand.com www.oldbrand.com;
return 301 https://newbrand.com/;
}
<!-- Old site goes offline two weeks after launch because the team forgot to renew the domain -->
- No URL mapping spreadsheet
- No GSC Change of Address filing
- New site shipped with new domain + new platform + new URL structure simultaneously
- No staging environment, redirects tested only on launch day
- Bing Webmaster Tools never updated
This is the modal failed migration. Every old URL bulk-redirects to the homepage, which Google evaluates as a soft 404 across the board — the old URLs lose their inbound link signal because the destination doesn’t match the source. The homepage authority concentrates artificially, then bleeds out when Google realizes the redirects aren’t legitimate. Stacking three changes (domain, platform, URL structure) means there’s no way to isolate which one broke; rollback is impossible. Letting the old domain expire 14 days after launch ends the migration permanently with whatever signal made it through.
The expert approach
# Step 1: Inventory
# Pull GSC 90-day click data
gscli performance export --site oldbrand.com --start 2026-02-01 --end 2026-04-30 > gsc.csv
# Pull Ahrefs backlinks
curl "https://api.ahrefs.com/v3/site-explorer/all-backlinks?target=oldbrand.com" \
-H "Authorization: Bearer $AHREFS_TOKEN" > ahrefs.json
# Crawl current site
screamingfrog --crawl https://oldbrand.com --export-tabs "Internal:All" \
--export-format csv --output-folder ./sf-crawl
# Step 2: Build mapping
python build-mapping.py gsc.csv ahrefs.json ./sf-crawl > url-mapping.csv
# Manual review: flag every row below 0.85 mapping confidence
awk -F',' '$3 < 0.85' url-mapping.csv > review-required.csv
# Step 3: Targeted 301s using a map for O(1) lookup
map $request_uri $new_uri {
include /etc/nginx/conf.d/url-map.conf;
default "";
}
server {
listen 443 ssl http2;
server_name oldbrand.com www.oldbrand.com;
ssl_certificate /etc/letsencrypt/live/oldbrand.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/oldbrand.com/privkey.pem;
if ($new_uri = "410") { return 410; }
if ($new_uri != "") { return 301 https://newbrand.com$new_uri; }
# Fallback: any unmapped URL goes to nearest pattern, never to homepage
rewrite ^/blog/(.+)$ https://newbrand.com/articles/$1 permanent;
rewrite ^/products/(.+)$ https://newbrand.com/shop/$1 permanent;
# Final fallback: 404, NOT 301 to homepage
return 404;
}
// Step 4: Bulk submit to IndexNow for fast Bing/Yandex re-discovery
import https from "https";
const apiKey = process.env.INDEXNOW_KEY;
const urls = require("./new-urls.json");
const payload = JSON.stringify({
host: "newbrand.com",
key: apiKey,
keyLocation: `https://newbrand.com/${apiKey}.txt`,
urlList: urls,
});
const req = https.request({
hostname: "api.indexnow.org",
port: 443,
path: "/indexnow",
method: "POST",
headers: { "Content-Type": "application/json", "Content-Length": payload.length },
});
req.write(payload);
req.end();
Post-launch checklist (committed to project tracker):
- [ ] GSC: new property verified
- [ ] GSC: old property still verified, will remain so for 24 months
- [ ] GSC: Change of Address filed within 72 hours of launch
- [ ] Sitemaps submitted: new domain (GSC + Bing)
- [ ] IndexNow submitted: full new URL list
- [ ] Old domain: registrar set to auto-renew for 5 years
- [ ] Old domain: 301 monitoring via curl in CI hourly for 90 days
- [ ] Top 200 URLs: hand-verified 301 returns 200 at destination
- [ ] Disavow file: re-uploaded to new property if applicable
Every old URL maps to a specific new URL. Unmapped URLs hit pattern-based fallback rules; only truly removed pages return 404 (or 410 if explicit). The old domain stays alive for years, not weeks. Both GSC properties are monitored. IndexNow accelerates Bing/ChatGPT Search recovery. The disaster scenarios are eliminated by design rather than discovered after launch.
Do this today
- In Google Search Console, export the last 90 days of Performance → Pages data for both old and new properties. The page-level click counts are the floor of URLs you must redirect successfully.
- In Ahrefs Site Explorer, pull the Best by Links report for the old domain. Every URL with at least one referring domain must redirect to a content-equivalent destination.
- Build the URL mapping spreadsheet with columns:
old_url,new_url,confidence,equivalence,notes. Manually review every row with confidence below 0.85. - Stage the migration on a
staging.newbrand.comsubdomain with the full new IA. Crawl with Screaming Frog → Mode → Spider to validate every internal link returns 200. - Implement 301 redirects in your CDN or origin (Cloudflare Page Rules, Vercel
vercel.jsonredirects, Nginxmap). Test withcurl -Ion a sample of 50 old URLs before launch. - Day of launch: submit the new XML sitemap in Search Console → Sitemaps and Bing Webmaster Tools. Trigger an IndexNow ping for the new URL list.
- Within 72 hours: file the Change of Address in Google Search Console at
search.google.com/search-console/settings/change-of-addressif you changed domains. - Set up daily redirect monitoring with a CI job that
curl -Is 200 random old URLs and alerts on any non-301 response. Run for 90 days minimum. - Track top 200 keyword rankings in Ahrefs or Semrush from 14 days pre-launch through 90 days post-launch. The drop-and-recover curve tells you whether the migration is on track.
- Set the old domain’s registrar to auto-renew for 5 years minimum. The single biggest preventable migration loss is letting the old domain expire while 301s are still doing their job.
Mark complete
Toggle to remember this module as mastered. Saved to your browser only.
More in this part
Part 5: Technical SEO
- 026 Technical SEO Fundamentals 12m
- 027 Site Architecture 20m
- 028 Crawling & Indexing 17m
- 029 robots.txt Deep Dive 15m
- 030 XML Sitemaps 12m
- 031 Canonical Tags 20m
- 032 Meta Robots & X-Robots-Tag 13m
- 033 HTTP Status Codes 15m
- 034 Crawl Budget Management 16m
- 035 JavaScript SEO 26m
- 036 Core Web Vitals 17m
- 037 Site Speed & Performance 19m
- 038 HTTPS & Site Security 12m
- 039 Mobile SEO & Mobile-First Indexing 14m
- 040 Structured Data & Schema Markup 17m
- 041 International SEO (hreflang) 19m
- 042 Pagination 12m
- 043 Faceted Navigation 26m
- 044 Duplicate Content 13m
- 045 Site Migrations You're here 24m