seo101

Site Migrations

A migration is any change that alters URLs, rendering, or domain - redesigns, CMS/framework swaps, domain changes, HTTP→HTTPS, consolidating sites. It's the highest-stakes routine operation in SEO: done well, traffic dips slightly for a few weeks; done badly, years of accumulated equity evaporate in a deploy. The difference is process.

The iron rules#

  1. Every old URL gets a response plan. Redirect (301) to its closest equivalent, or deliberate 410. No mass 404s, no "the homepage will catch it."
  2. Redirect to equivalents, not the homepage. Blanket homepage redirects are treated as soft 404s - equity evaporates anyway.
  3. One change at a time when possible. Domain + design + platform + content all at once means when traffic drops, you can't isolate why.
  4. Measure before, so you can verify after.

Phase 1: Inventory (before anything else)#

Build the complete list of URLs that matter - from a full crawl, GSC (everything with impressions), analytics (everything with sessions), sitemap, and your backlink tool (everything with external links). Union these; the result is your migration universe. For each URL, record current traffic, rankings and linking domains - that's your baseline and your prioritization weight.

Phase 2: The redirect map#

A spreadsheet (or generated file) mapping every old URL to its new home:

redirect-map.csv
old_url,new_url,type
/blog/2019/05/seo-tips,/guides/seo-basics,301
/products.php?id=42,/products/ergo-chair,301
/old-category/,/new-category/,301
/discontinued-thing,(410 gone),410

Rules of thumb:

  • Pattern-redirect where structure allows (/blog/:year/:month/:slug → /guides/:slug), itemize the exceptions
  • No chains: old → new directly, including fixing existing old redirects to point at the final destination
  • Page-to-page equivalence by intent: the new URL should satisfy the same query

In Next.js, bulk redirects live in config:

next.config.ts (excerpt)
async redirects() {
  return [
    { source: "/blog/:year/:month/:slug", destination: "/guides/:slug", permanent: true },
    { source: "/products.php", destination: "/products", permanent: true },
  ];
},

(For very large maps, serve them from middleware/proxy or the edge config rather than thousands of static entries.)

Phase 3: Pre-launch on staging#

Audit the new site as if it were a stranger's (audit playbook) - crawl it, verify titles/canonicals/schema/render parity with production. Then test the redirect map against staging with a script: fetch every old URL, assert one-hop 301 to the mapped target.

Phase 4: Launch day#

□ robots.txt correct on production (no staging disallow!)
□ noindex absent from production templates
□ Redirect map live - spot-check top-100 old URLs
□ New sitemap submitted in GSC; old sitemap left up briefly
  (it helps engines discover the redirects faster)
□ Domain change? → GSC "Change of address" tool
□ Canonicals point to new URLs (not old, not staging)
□ Analytics + GSC verified on the new property
□ Internal links updated to final URLs (not riding redirects)

Phase 5: Monitor and stabilize#

Expect temporary flux (days to a few weeks) while engines reprocess. Watch daily at first:

  • GSC Indexing on both properties: old URLs should drain as "redirected", new ones fill the index
  • Crawl stats: a spike is normal (Google revisiting everything); sustained 404 spikes are your gaps - patch the redirect map as they surface
  • Rankings/traffic by section vs. your Phase-1 baseline: section-level losses point at section-level mistakes (a template's canonical, a missed pattern)
  • Server logs: Googlebot hitting old URLs and getting anything but a 301 = work

Keep redirects live for years (link equity flows through them as long as external links point at old URLs), and never recycle the baseline comparison away - +90 days against pre-migration numbers is the success criterion.

Next, the final guide: Analytics & Forecasting - reporting and predicting SEO as a professional.