We are running several sub-domain sites on a WordPress Multisite environment and want to switch the primary site from the root to a sub-domain like so:

Current site is example.com with ID 1 (cannot rename because field is set and uneditable)

New site is new.example.com with ID 15 (tried to rename to example.com)

I followed some instructions for switching that involved renaming the sites and updating the wp-config.php file to give the new ID of 15 for the SITE_ID_CURRENT_SITE and Blog_ID_CURRENT_SITE. The result was the main site did not change and the admin got mucked up.

Is there a straight forward way to switch the main site out and replace it with the sub-domain site content without importing posts/pages and plugins?


Thanks for giving these tips. My conclusion with what I've seen in the database, read, and get from you is that the new subdomain site to replace the main site needs to have the base table names and ID of 1, updated paths etc. My only worry is that after switching these the network admin will have a problem -- so I basically need to compare the base tables (wp_options etc) to the equivalent (wp_x_options etc) to see if there is anything unique related to the network admin in those base tables.

  • Just-in-case it's not a typo above, it should be capital BLOG_ID_CURRENT_SITE, and I think SITE_ID_CURRENT_SITE probably needs to stay 1 (to match the wp_site table). See the code in wp-includes/ms-settings.php that uses these to setup $current_site->blog_id - obviously you need DOMAIN_CURRENT_SITE, PATH_CURRENT_SITE set etc. Whether getting this right will do the trick I don't know though. I don't have a subdomain multisite to check: there may also be paths in wp_X_options you'd need to change: you may need to debug through the bad state to work out what's going wrong.
    – Rup
    Jul 12, 2016 at 9:19

2 Answers 2


Four years old and no answer? So here we go…-

Let's take the following network setup as example (I'm using WP-CLI's site list command):

$ wp site list
| blog_id | url                | last_updated        | registered          |
| 1       | http://wp.tmp/     | 2016-08-04 08:39:35 | 2016-07-22 09:25:42 |
| 2       | http://foo.wp.tmp/ | 2016-07-22 09:28:16 | 2016-07-22 09:28:16 |

The network site list would look like this:

network site list

We want to use the site with ID 2 as the new root site with the URL http://wp.tmp/. This is actually the same problem as described in the question just with some other values for the ID and the URLs.

The multisite relevant part of the wp-config.php looks probably like this:

const MULTISITE            = TRUE;
const DOMAIN_CURRENT_SITE  = 'wp.tmp';
const PATH_CURRENT_SITE    = '/';

Updating database site settings

WordPress uses the tables wp_*_option and wp_blogs to find the matching blog for a given request URL and to build proper permalinks for this blog. So we have to change the values in the following three tables (for this example):

  • In wp_options the keys home and siteurl
  • In wp_2_options the keys home and siteurl (in your case this would be wp_15_options)
  • In wp_blogs the column domain for both sites with ID 1 and 2 (respectively 15)

I'm using Adminer for this, but any other DB management tool (PhpMyAdmin) does the job as well. (The screenshots shows the GUI in German language but I guess the idea is clear.)

adminer edit wp_options

In wp_options (the options table for site ID 1) I changed the values of both keys home and siteurl from http://wp.tmp to http://foo.wp.tmp. (The screenshot above shows the state before the update.)

I did exactly the same with the table wp_2_options but here I changed the value from http://foo.wp.tmp to http://wp.tmp.

Next step is to update the table wp_blogs:

adminer edit wp_blogs (Again, the screenshot shows the table before I made any change.) Here you simply switch the values from both sites in the domain column:

  • wp.tmp becomes foo.wp.tmp and
  • foo.wp.tmp becomes wp.tmp

Now you have to update the wp-config.php to deal correctly with the new settings data:

const MULTISITE            = TRUE;
const DOMAIN_CURRENT_SITE  = 'wp.tmp';
const PATH_CURRENT_SITE    = '/';
const BLOG_ID_CURRENT_SITE = 2; // This is the new root site ID

At this point you have again a working WordPress multisite but with a new root site:

$ wp site list
| blog_id | url                | last_updated        | registered          |
| 1       | http://foo.wp.tmp/ | 2016-08-04 08:39:35 | 2016-07-22 09:25:42 |
| 2       | http://wp.tmp/     | 2016-07-22 09:28:16 | 2016-07-22 09:28:16 |

network site list updated

Remember: during this process, your site will be not available and requests will end up in some nasty errors so you might want to arrange a 503 Service Unavailable response in front of your WordPress installation. This could be done using .htaccess.

Updating database content

Now comes the tricky part. At the moment, all URLs in the content tables are still pointing to the resources of the old sites. But replacing them is not that easy: Replacing every http://foo.wp.tmp with http://wp.tmp in the first step and every http://wp.tmp with http://foo.wp.tmp in the next step will end up in having all former URLs pointing to site ID 1 (http://foo.wp.tmp).

The best way would be to insert an intermediate step:

  • Search for http://foo.wp.tmp and replace it with a preferably unique slug: http://3a4b522a.wp.tmp
  • Search for http://wp.tmp and replace it with http://foo.wp.tmp
  • Search for http://3a4b522a.wp.tmp and replace it with http://wp.tmp

All these search and replace commands should ignore the three tables (*_options *_blogs) we updated before, otherwise they would break the configuration. You might also have a manual look for URLs in wp_*_options table outside of the home and siteurl keys.

I would suggest to use WP-CLI's search-replace command for this as it can deal with serialized data and has no limitations that HTTP might have.

  • +1 for a good and detailed overview. It would be handy to have a custom wp-cli command for this ;-) You refer to a "4 years" old question, but the question was asked 2016-07-12. PS: I noticed yesterday that Adminer is no longer available in the plugin directory on wordpress.org.
    – birgire
    Aug 10, 2016 at 19:35
  • Ha, I should read these dates twice. Adminer is in fact a stand-alone application that comes within a single PHP file. No need to use the plugin here. I wrote a plugin that at least allows you to change a site URL via WP-CLI: github.com/inpsyde/wp-cli-site-url
    – David
    Aug 10, 2016 at 22:41
  • yes, I'm aware of that, have few times been asked to extract data from abandoned sites without any available ssh/ftp/cpanel etc. In that case a plugin version becomes handy ;-) Thanks for the link, looks like a handy plugin too that you've built there.
    – birgire
    Aug 10, 2016 at 22:53
  • Great answer, I'm just shocked noone write a plugin for this... Is there a plugin for this? 3 easy steps! Pretty deterministic, too. How did you come up with it? :D
    – Gyuri
    Oct 9, 2018 at 7:41
  • It might be deterministic but in WordPress almost nothing is predictable. In sever years of professional WordPress I found a reason just once or twice to switch the primary site in an existing environment. I think it is a rarely edge case and that's why there is no plugin for it.
    – David
    Oct 10, 2018 at 15:02

An easier alternative (that doesn't involve touching any line of code) is to use the all-in-one-migration plugin:

  1. export new.example.com with ID 15and
  2. re-import it into example.com with ID 1
  • 1
    Concur. We had a sub-site that needed to replace the root. Imported directly over the root site with All-in-one-Migration w/ multisite add-on. Oct 3, 2019 at 21:55
  • While that migrates site data it doesn't change the main site - ID1 is where all the core admin and multi-site stuff is, it's unclear if the OP wanted to migrate site data or migrate what is primary site is. Jan 15 at 19:15
  • Important to note that the All-in-one-migration plugin doesn't feature this without paying for the Multisite Extension that "starts at 199$" Jan 27 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.