Skip to content

How to move WordPress to a new domain and keep your links and search traffic

A domain move is four jobs. Make the site answer at the new name, rewrite the old name wherever it is stored, redirect every old address to the same path with a 301, and tell search engines. Keep the old domain registered, because the redirect has to stay for a long time.

By
WP Ministry
Published

In short

  • Point the new domain at the site and get its certificate working before you change anything in WordPress.
  • Rewrite the old name with wp search-replace, dry run first. The real run changes WordPress's two address settings in the same pass.
  • Never replace addresses with plain SQL, and never change the guid column.
  • Redirect every old address to the same path on the new domain with a 301, in one hop, and check several by hand.
  • Submit a Change of Address in Google Search Console for every form of the old domain. It forwards signals for 180 days.
  • Keep the old domain registered, pointed at a server and covered by a certificate. Google's guidance is to keep the redirects for at least a year.

Moving a WordPress site to a new domain is four jobs. Make the site answer at the new name. Rewrite the old name everywhere it is stored. Redirect every old address to the same path on the new domain with a permanent (301) redirect. Then tell search engines.

The redirect has to stay for a long time, so the old domain has to stay registered, pointed at a server and covered by a certificate.

This page is for a single site that keeps its hosting and changes its name. A multisite network is moved differently. If you also plan to change hosts or redesign, do that separately: Google's guidance is to change only one thing at a time.

Get the new name ready first

None of this changes the live site.

  • Add the new domain to the hosting account, so that it serves the same site as the old one, and point its DNS there. If the control panel has no obvious place for this, ask the host.
  • Get a certificate that covers the new name. A browser checks that the certificate matches the name in the address, so the old domain's certificate is no use for the new one. How to install a free SSL certificate covers getting one. Set up the DNS first: the issuer has to confirm that you control the domain.
  • Open https://new-example.com/ in a browser. You should reach your site with no certificate warning. Its links still lead to the old name. That is expected.
  • Take a full backup of the files and the database, and keep a copy somewhere other than the server.
  • Lower the DNS TTL on any record you are going to change. A DNS answer is cached for as long as the record's TTL (time to live) says. Google's guidance for a hosting move is to lower it to a few hours, at least a week ahead, so that a change spreads faster. If both domains already point at the same server and will stay there, skip this.
  • Add both domains to Google Search Console. The section on search engines below says which kind of verification survives the move.
  • Pick a quiet day. Google suggests timing a move for when traffic is low.

Rewrite the old name in the database

WordPress keeps its own address in two settings, and the old name is also saved inside posts, menus, widgets and the settings of themes and plugins. How to change your WordPress URL explains the two settings and four ways to set them. For a whole domain move, one WP-CLI command deals with the settings and the stored copies together. It runs over SSH, from the site's folder: see how to use WP-CLI if it is new to you.

Why a plain find and replace breaks things

Themes and plugins save many settings as serialized data, which records the length of each piece of text beside the text:

text
s:32:"https://old-example.com/pricing/";

The 32 is the number of characters in the address. Change the address with a SQL REPLACE, or in a text editor on an exported file, and the number stays as it was. If the new address is longer or shorter, the two no longer agree and WordPress cannot read the setting. WordPress's documentation warns that a search and replace across the whole database breaks serialized data in this way.

WP-CLI's search-replace command does not have this problem: its reference says it handles PHP serialized data.

What the flags do

FlagWhat it does, from the WP-CLI reference
--dry-runRuns the whole operation and shows the report, and saves nothing to the database.
--skip-columns=guidLeaves the named column alone.
--all-tables-with-prefixIncludes every table that has the site's table prefix, even one a plugin made without registering it with WordPress. Without it, only registered tables are searched.
--all-tablesIncludes every table in the database, whatever its prefix. Use it only when the database holds this site and nothing else.
--preciseDoes every replacement in PHP. By default the command uses fast SQL queries and switches to PHP for columns that hold serialized data. Slower, and more reliable with complex serialized data.
--report-changed-onlyLists only the columns where something changes.

The guid column holds the permanent identifier WordPress gives each post. Feed readers use it to tell which posts they have already shown, so a changed one makes old posts appear as new. It keeps the old domain for good. WordPress's documentation is blunt: "Never, ever, change the contents of the GUID column, under any circumstances."

Run the replacement

Use your own two addresses, written exactly as they appear under Settings, then General, with no slash at the end.

  1. Step 1: Export the database

    This writes the database to your home folder. A copy inside the site's own folder could be downloaded by anyone who guessed its name.

    bash
    wp db export ~/before-domain-move.sql
  2. Step 2: Do a dry run

    The report is a table of each table and column that holds the old address, and it ends with a line such as Success: 9 replacements to be made. Expect wp_options and wp_posts in it. Nothing has been saved.

    bash
    wp search-replace 'https://old-example.com' 'https://new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only --dry-run
  3. Step 3: Run it for real

    This rewrites the database, and the only way back is the export from the first step. It is the same command without --dry-run. WordPress's two address settings are rows in wp_options, so this run changes them too, and from this moment WordPress builds its links with the new name. wp option get home should now print the new address.

    bash
    wp search-replace 'https://old-example.com' 'https://new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only
  4. Step 4: Repeat for the other forms of the old address

    Each run replaces one exact piece of text. Do a dry run for each form the site was ever reached by, then run for real each one that finds something. Leftover http:// addresses cause mixed content warnings.

    bash
    wp search-replace 'http://old-example.com' 'https://new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only --dry-run
    wp search-replace 'https://www.old-example.com' 'https://new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only --dry-run
    wp search-replace 'http://www.old-example.com' 'https://new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only --dry-run
  5. Step 5: Replace addresses stored as JSON

    PHP's JSON encoder writes each slash as \/ unless told not to. A plugin that saves data that way holds the address as https:\/\/old-example.com, which the runs above do not match. Keep the single quotes, so that the backslashes arrive as typed, and remove --dry-run once the report looks right.

    bash
    wp search-replace 'https:\/\/old-example.com' 'https:\/\/new-example.com' --skip-columns=guid --all-tables-with-prefix --report-changed-only --dry-run
  6. Step 6: See what is left

    This lists every place the old name still appears, by table, column and row. Expect the guid column of wp_posts, and leave it. Expect email addresses such as info@old-example.com: the runs above looked for web addresses and did not touch them. Change those only if the mailbox is moving too. search-replace also skips any table with no primary key, so a row in one of those has to be edited by hand.

    bash
    wp db search 'old-example.com' --all-tables-with-prefix
  7. Step 7: Empty every cache

    Run wp cache flush for the object cache. Then clear the caching plugin, the host's cache and any CDN.

Two things the command does not settle:

  • wp-config.php. If the file defines WP_HOME or WP_SITEURL, those lines override the database and still hold the old name. Edit them by hand.
  • A page builder. Some have a tool of their own for this. Elementor's documentation, for one, says to go to Elementor, then Tools, open the Replace URL tab and enter the previous and the current address.

Redirect the old domain to the new one

WordPress does not do this for you. Between host names, its built-in redirect only moves a visitor from the www form to the bare form of the same name, or back. Until the server redirects the old domain, both names show the same pages.

Google's guidance says what the redirect has to be: permanent and done by the server, from each old address to its own new one, in one hop. For a change of domain alone, Google says a wildcard redirect will do, with no list of addresses. Do not send everything to the home page: Google says that can confuse visitors and may be treated as a soft 404.

.htaccess

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old-example\.com$ [NC]
RewriteRule ^(.*)$ https://new-example.com/$1 [R=301,L]
Use the one that matches the server the old domain is on.

Apache, both domains in one folder. This is the case when the new domain was added to the same site. Put the three lines above the line # BEGIN WordPress. The condition limits the rule to the old name, with or without www. R=301 sets the status: without a number, Apache's R flag sends a 302. The query string is passed through unchanged.

Apache, old domain in its own folder. One line is the whole file. Apache's documentation prefers Redirect for a simple move to another server, and says that the rest of the path and any query string are added to the target.

nginx. The old names get a server block of their own, which nginx's documentation calls the right way to do it. $request_uri is the full original request, path and query string. The certificate paths are examples: use those of the certificate that covers the old domain. Check the file with nginx -t, then reload nginx.

With no access to either file, use the redirect tool in the hosting control panel, or forwarding at the registrar, and hold it to the checks below.

If some pages also get a new path in the move, the wildcard is not enough for those. The redirect map builder turns a list of old and new addresses into rules, which go above the wildcard. How to set up redirects in WordPress covers where rules can live.

What the old domain needs from now on

  • Its registration. ICANN's guidance for registrants is that a name that is not renewed may be released and registered by someone else. Google recommends paying for the old domain for at least a year, so that nobody else can buy the abandoned name and misuse it.
  • DNS that points at a server which answers with the redirect.
  • A certificate. The browser checks the certificate before it sends the request, so an old https:// link to a domain with an expired certificate shows a warning and never reaches the redirect. A Let's Encrypt certificate is valid for 90 days, so the old domain has to stay set up for renewals.

Check the redirect

  1. Step 1: Ask for several old addresses

    Run these on your own computer with real addresses from the old site: the home page, a deeper page with a query string, and a file from the media library. Mix in the http and www forms. -I fetches the headers only.

    bash
    curl -I https://old-example.com/
    curl -I "https://old-example.com/about-us/?utm_source=test"
    curl -I http://www.old-example.com/wp-content/uploads/2026/01/photo.jpg
  2. Step 2: Read the status line and the Location line

    Among the lines each command prints, look for these two. The status must be 301, and the address after Location: must be the same path and query string on the new domain, over https. A 302 is a temporary redirect. A Location: that names the home page for a deeper address means the path is being dropped.

    text
    HTTP/1.1 301 Moved Permanently
    Location: https://new-example.com/about-us/?utm_source=test
  3. Step 3: Follow one to the end

    -L makes curl follow each redirect and print the headers of every stop. The right result is one 301 and then a 200. The redirect checker shows the same thing in a browser: every hop, its status code and where it sends you next.

    bash
    curl -IL http://www.old-example.com/about-us/

If the browser reports too many redirects, something on the new name is sending visitors back to the old one. Look for a leftover WP_HOME line in wp-config.php, a rule in a redirect plugin or a rule at the CDN. How to fix ERR_TOO_MANY_REDIRECTS has the steps.

Tell search engines

The redirects carry most of this. The tools below tell the engines directly.

Google

  1. Step 1: Make sure both domains are verified in a way that lasts

    A Domain property covers every subdomain and both http and https, and is verified with a DNS record. That record does not depend on the site, so it keeps working once the old domain only redirects. A verification file does not: Search Console will not follow a redirect to another domain to find it. For a site that redirects all its traffic, Google recommends the HTML tag method, or use the DNS record.

  2. Step 2: Check what the Change of Address tool requires

    You must be an owner of both properties, in the same Google account. The property must be at the domain level, not a path. A 301 from the old home page to the new one must already be in place: the tool checks a few pages for 301s before it accepts the request.

  3. Step 3: Submit a Change of Address for every form of the old domain

    Open the tool in the old domain's property and follow it. It moves both http and https, and it does not move subdomains, www included. Google says to submit it for every variant of the old domain, with and without www, even those you do not use.

  4. Step 4: Submit the new sitemap

    In the new domain's property, open the Sitemaps report, paste the sitemap's address into "Add a new sitemap" and submit it. WordPress's own sitemap is at /wp-sitemap.xml, unless an SEO plugin provides a different one. Open it first and check that every address in it uses the new name. Google says the old sitemap can be removed at this point.

The tool tells Google to favor crawling and indexing the new site, and forwards signals from the old one, for 180 days. The request can be canceled within those 180 days. Google's help says to keep the redirects for at least 180 days, and longer if Google Search still sends visitors to the old addresses. Its site-move guidance goes further: keep them for as long as possible, generally at least a year.

Bing

Bing Webmaster Tools lists no site move tool among its current features. Bing's webmaster guidelines say what to do instead:

  • Use 301 redirects for permanent changes of address.
  • Keep the sitemap to current addresses, and remove redirected ones from it promptly.
  • Use IndexNow to tell Bing when addresses are added, changed or removed.

So add and verify the new domain in Bing Webmaster Tools, which can import sites already verified in Google Search Console, and submit the new sitemap in its Sitemaps report.

Everything else that carries the old name

Other systems hold the old address too, and no redirect updates them.

  • Email addresses on the old domain. Mail does not follow the website. Those mailboxes work for as long as the old domain stays registered and its mail records are left alone. In WordPress, check "Administration Email Address" under Settings, then General: a new address there takes effect only after the confirmation link sent to it is clicked. WordPress's own messages are sent by default from wordpress@ and the site's domain, which is now the new one.
  • Analytics and tags. Google's guidance is to set up analytics for both sites and to ask your analytics provider how. Check the site address in the analytics property, and any tag that fires only on a named host.
  • Payment gateways. Stripe, for one, has you register each webhook endpoint as a full https address. Change webhook and return addresses in the provider's dashboard. Do not count on the redirect to carry them: Apache's documentation for its Redirect directive notes that a POST is discarded.
  • Sign-in with Google and other OAuth logins. Google's documentation says the redirect address a site sends must exactly match one registered for the app. Add the new domain's address in each provider's console.
  • API keys tied to a domain. A reCAPTCHA key, for example, is tied to the domains named when it was made. Add the new domain to each such key.
  • License keys. A paid plugin's license can be registered to one address. Elementor's documentation describes a license mismatch error after a change of domain, fixed by deactivating the license and activating it again. Check every paid plugin and theme.
  • The SEO plugin. View the source of a page on the new site and check that the rel="canonical" line names the new domain: Google's guidance is that each new address should name itself there. Then read the plugin's settings for any address typed in by hand.
  • Addresses written into theme and plugin files. The replacement reads only the database. The command under this list names every file under wp-content, outside uploads, that still contains the old name.
  • Links you control elsewhere. Google lists social profiles and ad campaigns, and suggests asking the sites that send you the most visitors to update their links.
bash
grep -rIl "old-example\.com" wp-content --exclude-dir=uploads

The website migration checklist has the wider list for a move of any kind.

What to expect afterward

All of this is from Google's documentation on site moves.

  • Link credit is not lost. Google says 301 and other permanent redirects do not cause a loss of PageRank.
  • Rankings may move about for a while. Google says to expect temporary fluctuation while it crawls and indexes the site again, and that rankings settle over time.
  • It takes weeks, not days. For a medium-sized site, Google says it can take a few weeks or more before it shows the new addresses in place of the old ones, and longer for a large site. The move happens one address at a time, with no fixed schedule.
  • Google crawls more than usual. Crawls of the old addresses are redirected to the new site, on top of its normal crawling. Make sure the server can take it.
  • Some old addresses stay in results. Google does not erase the old site from its index. An old address with no equivalent page on the new site can keep showing.
  • Search Console shows it happening. The count of indexed pages falls on the old property and rises on the new one. An unusual number of "Not found" errors needs a look: Google says redirects that lead to pages that do not exist are a mistake it sees often.

When to get help

Get help when the site takes payments, when you have no SSH access, or when a dry run reports tables you do not recognize.

Our WordPress migration service moves one WordPress site from one host to another. A change of domain is a different job, so say so when you ask for the free diagnosis, and you get a quote in writing before anything is moved.

Common questions

How long do I have to keep the old domain?

At least a year, and longer if you can. Google's site-move guidance is to keep the redirects for as long as possible, generally at least a year, and to consider keeping them indefinitely for visitors' sake. Its Change of Address help gives 180 days as the least.

Will I lose my search rankings?

Google says that 301 redirects do not cause a loss of PageRank, and that rankings may fluctuate for a time while it crawls and indexes the site again. Nobody can promise the result. What is in your hands is the redirect from every old address to the same page, the Change of Address request and the new sitemap.

Can I redesign the site or change hosts at the same time?

Google advises against it. Its guidance is to change one thing at a time: the domain first, then the rest. Its Change of Address help adds that a move combined with new content and a new address structure will probably lose some traffic, because Google has to assess the pages again.

Can I do this without SSH or WP-CLI?

Yes. For the database, use a search and replace plugin that says it handles serialized data and offers a dry run. WordPress's documentation names Better Search Replace. For the redirect, use the tool in your hosting control panel. Then run the same checks: a 301, the same path, one hop.

More on this subject

Migration, done for you

Migration is $59. One site, one move, tested before the DNS change. It starts with a free diagnosis.