Home › Blog › Article

Migrate to WordPress Without Losing SEO

Migrate to WordPress Without Losing SEO

To migrate to WordPress without losing SEO, export all URLs from the old CMS, build a complete 301 redirect map to the new WordPress permalink structure, move content and media with metadata intact, then verify every redirect returns 301 and watch Google Search Console until impressions return to baseline. You know it worked when old URLs no longer 404, Search Console shows coverage recovering within weeks, and organic traffic stays flat or grows instead of dropping after launch.

Preparation Before You Migrate to WordPress

Before touching a single file, inventory the source site. Crawl the old CMS with Screaming Frog SEO Spider 2026.1 or wget --spider -r -nd -nv https://old.example.com 2>&1 | grep -o 'https://[^ ]*' | sort -u > urls.txt. Export every indexable URL: posts, pages, category archives, tag archives, author pages, pagination, and attachment URLs. Store this as urls.csv with columns old_url,new_url,status.

Provision a staging WordPress 6.7 site (current stable in 2026) on PHP 8.3 with the same domain in a hosts-file override or a .test domain. Do not build on production. Install Rank Math SEO 1.0.2026 or Yoast SEO 24.0 to control titles and canonical tags from day one. If you need professional help at any stage, our WordPress Site Migration team handles the full pipeline.

Set the WordPress permalink structure to match the old pattern as closely as possible. If the old CMS used /blog/post-name/, set WordPress to /blog/%postname%/ in Settings → Permalinks. Matching structure removes hundreds of redirects before you write the first one.

Step by Step Migration Process

  1. Crawl the old CMS and export every indexable URL into a master spreadsheet.
  2. Build the URL map and generate the 301 redirect table for WordPress.
  3. Import content, taxonomy, and media with metadata and featured images preserved.
  4. Deploy redirects at the server or plugin layer and test every rule.
  5. Launch DNS to the WordPress stack and monitor Search Console for 14 days.
  6. Keep the old CMS read-only for 30 days so you can roll back if rankings drop.

1. URL Mapping and 301 Table

The 301 table is the contract between old and new. For every row in urls.csv, decide the new WordPress URL. Use the pattern: post maps to /%postname%/, category maps to /category/%category%/, tag to /tag/%tag%/. When slugs changed, map manually. Never redirect multiple old URLs to one new URL unless the content truly merged — that dilutes relevance.

Write the table as a PHP array for a must-use plugin at wp-content/mu-plugins/redirect-map.php. This loads before themes and cannot be disabled from the admin:

<?php
// wp-content/mu-plugins/redirect-map.php
add_action('init', function () {
    $map = [
        '/old-page'            => '/new-page',
        '/blog/2020/post-one'  => '/post-one',
        '/cat.php?id=12'       => '/category/news',
    ];
    $request = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $request = rtrim($request, '/');
    if (array_key_exists($request, $map)) {
        wp_redirect(home_url($map[$request]), 301);
        exit;
    }
});

For query-string URLs like /cat.php?id=12, add a second check on $_GET['id']. If you run Nginx, put bulk rules in the server block instead for speed:

Get a Quote

Email + requirement + budget range — we reply with a quote within 24 hours.

rewrite ^/old-page/?$ /new-page permanent;
rewrite ^/blog/2020/post-one/?$ /post-one permanent;

On Apache use .htaccess with Redirect 301 /old-page /new-page. Pitfall: redirect chains. If A→B→C, flatten to A→C. Use curl -sIL https://new.example.com/old-page | grep -i '^HTTP|^location' to confirm one hop only.

2. Content and Media

Export from the old CMS to WordPress-compatible format. Drupal 10 and Joomla 5 both support CSV or XML export; use the WordPress Importer 0.8 plugin or a custom WP-CLI script. For media, do not rely on the importer alone — it often fails on remote images. Download attachments with wget -P /tmp/media -i media-urls.txt, then import with wp media import /tmp/media/* --post_id=0 --title="${filename%.*}" --alt="${filename%.*}".

Preserve metadata: title, meta description, alt text, publish date, author, and taxonomy. A custom migration script should map old fields to post_title, post_content, post_date, and _thumbnail_id. Check that featured images attach with wp post list --fields=ID,post_title --meta_key=_thumbnail_id returning every post that had an image.

If you come from a platform comparison like WordPress vs Joomla: 2026 Vendor Decision Guide, you already know taxonomy names differ; map Joomla section/category into WordPress hierarchical categories explicitly in the import script. Pitfall: duplicate content from both /?p=123 and pretty permalinks — enforce canonical tags in your SEO plugin and disable ?p= access with a redirect to the pretty URL.

3. Verifying Redirects

Verification is not optional. Loop through the full old URL list and assert HTTP 301 to the exact target. Use this bash loop:

while IFS=, read -r old new; do
  code=$(curl -s -o /dev/null -w '%{http_code}' -L --max-redirs 3 "https://new.example.com$old")
  final=$(curl -sIL "https://new.example.com$old" | grep -i '^location' | tail -1 | tr -d 'r')
  echo "$old -> $code -> $final"
done < urls.csv

Every row must print 301 and the final location must equal the intended new URL. Any 404 or 200 on an old URL is a bug. Also test with JavaScript disabled and with cookies cleared so plugin-level redirects fire. In Chrome DevTools Network panel, disable cache and confirm the Status column shows 301, not 302. A 302 during launch is the most common silent ranking killer.

Use the official WP-CLI handbook to script bulk checks: wp eval 'var_dump(wp_remote_head(home_url("/old-page"))["response"]["code"]);' should print int(301). Pitfall: CDN caching of 301s — purge Cloudflare or Bunny CDN after deploying rules or you will see stale 200s.

4. Watching Index Recovery

After DNS cutover, open Google Search Console 2026 interface and submit the new XML sitemap from your SEO plugin at /sitemap_index.xml. Do not resubmit the old sitemap. Watch Pages report: expect a temporary drop in “Crawled – currently not indexed” followed by recovery over 7–21 days.

Track three numbers daily: total indexed pages, total impressions, and average position for your top 20 queries. Export from Performance → Search Results with the 2026 date-range compare set to “16 months”. If indexed count falls below 80% of the old baseline by day 14, you have a redirect or canonical bug — re-run the verification loop.

Check server logs for 404 spikes: grep ' 404 ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20. Any old URL in that list missing from your map must be added immediately. Pitfall: forgetting pagination and date archives; they carry link equity and must redirect to the closest new archive.

Rollback Plan

Keep the old CMS on a separate subdomain like old.example.com with database intact and files read-only. If organic traffic drops more than 30% for 7 consecutive days and you cannot find the cause, roll back: point DNS A record back to the old server, remove the WordPress canonical tags by taking the new site offline, and re-submit the original sitemap. Document every rollback step in a runbook before launch. After rollback, diff the urls.csv against Search Console Coverage to find missed routes, fix the map, and retry.

Action Checklist

Action Checklist
  • Crawl old CMS and export every indexable URL to urls.csv.
  • Map each URL to WordPress and deploy 301s via mu-plugin or server config.
  • Import content, media, and metadata; verify featured images attach.
  • Run the curl loop and confirm 301 with one hop for every row.
  • Monitor Search Console for 14 days and keep old CMS ready to roll back.

Frequently asked questions

How long does SEO recovery take after I migrate to WordPress?

Most sites see full index recovery in 7 to 21 days. Rankings stabilize within 4 to 6 weeks if every old URL 301s correctly and content is unchanged.

Should I use a plugin or server rules for redirects?

Use server rules (Nginx/Apache) for bulk static maps and a mu-plugin for dynamic query-string URLs. Plugins alone add overhead and can be disabled by accident.

Map every variation manually in the 301 table. Never rely on WordPress guessing — a wrong guess becomes a 404 that loses the link equity permanently.

Need hands-on help with your move? See our WordPress Site Migration page for fixed-scope plans and a free redirect audit before launch.

“, “faq”: [ { “question”: “How long does SEO recovery take after I migrate to WordPress?”, “answer”: “Most sites see full index recovery in 7 to 21 days. Rankings stabilize within 4 to 6 weeks if every old URL 301s correctly and content is unchanged.” }, { “question”: “Should I use a plugin or server rules for redirects?”, “answer”: “Use server rules (Nginx/Apache) for bulk static maps and a mu-plugin for dynamic query-string URLs. Plugins alone add overhead and can be disabled by accident.” }, { “question”: “What if my old CMS used different permalink structures?”, “answer”: “Map every variation manually in the 301 table. Never rely on WordPress guessing — a wrong guess becomes a 404 that loses the link equity permanently.” } ], “cover”: “A modern flat technical illustration of a website migration flow: a legacy CMS database on the left connected by glowing redirect arrows to a WordPress dashboard on the right, with search engine result bars staying level, no text, letters, numbers, logos or watermarks.

References & further reading

Need WordPress Development?

Free proposal and quote within 24 hours — we serve clients worldwide.

QQ