Planes at afternoon

Let’s close the migration trilogy we started two weeks ago with this final article on how to merge multiple WordPress blogs into one. If you didn’t read the previous articles (or don’t remember them now ?), here is a brief summary. First, we explained the first steps to merge the three blogs we had, including details on the way we proceeded to extract the three WordPress databases and clean their contents. After that, in the second part we dealt with the mapping between database contents and the details to put them inside the tables of our target WordPress multi-site installation (the one you’re visiting right now).

As a result from the previous steps, we’ll start now with a WordPress database that contains the following tables:

Relevant tables after the migration.
Relevant tables after the migration.

Today I’ll explain the last steps of the process, as well as some common problems we found (which you may face too ?). Because yes, there are always problems during a migration. The important thing is to be aware of them and minimize their impact.

Let’s go!

Final Steps of the Migration

Once we populated all the tables in the picture above, we’re close to completion—there are some issues we have to address, though, or they’ll arise once the site goes live.

Replacing Links

I’m sure you were expecting this one—all the links in the migrated content are probably wrong! For instance, imagine we had a blog post in WPrincipiante (our old Spanish site) that linked to another post in the same blog. That link could have been something like After the migration, this URL doesn’t exist anymore — doesn’t exist now, remember? But we just migrated this post, so it does exist somewhere. In particular, its new (valid) URL is

So, we have posts that link to old URLs, completely unaware that we moved them. If we don’t do anything, we’ll get 404 Not Found errors when we remove WPrincipiante completely. Moreover, the same applies to images and any other files we might have linked in our blogs!

There are different options for resolving this issue. On the one hand, you can use redirections. A redirection tells your server something like this: “if anyone asks for the URL, tell him that he should ask for instead”. This way, you don’t need to replace anything anywhere—your old links will just work. There’s a catch, though—doing so results in more requests to your server and slightly slower response times.

On the other hand, you can simply replace old links with the new ones everywhere in your database. And, spoiler alert, that’s what we did ?. There are a few plugins that help you to search and replace stuff all over your website (for instance, Better Search Replace, Search & Replace, or Velvet Blues Update URLs), but we decided to implement our own code and run it directly on the database, as part of the migration itself.

In our code we used regular expressions, which are an “easy” and usually quite safe way for replacing text. If you’re not familiar with regexps, be careful! They’re quite complex, specially for beginners ?. Here you have a few examples of the regexps we used in WPrincipiante’s content:

content = content.replaceAll(
   "href=""" );
content = content.replaceAll(
content = content.replaceAll(
   "src="" );

Assuming that post’s content is in content, the first statement simply replaces links to the old front page (the regexp either matches or, with a trailing slash) with links to Nelio Software‘s Spanish front page (

The second statement matches all other anchor tags whose href attribute links to WPrincipiante. Thus, for example, a post such as is replace with its new version In this particular example, the previous regular expression will also assume that links to a page or to an asset are blog posts, and so their URLs will be replaced too. During our migration this wasn’t a problem, but that doesn’t mean it can’t be a problem in yours ?. So, as always, be careful when replacing stuff!

Finally, the third statement replaces images (<img>) in WPrincipiante (for instance, with their new location in Nelio Software (that is,

We’ll apply the same steps in the contents migrated from old Nelio Software and Nelio A/B Testing. As I said before, regular expressions are very powerful, but they can be dangerous if you don’t use them carefully. Before replacing anything, make sure you backup your content.

Loading our SQL File

Once you complete the previous step, you’re ready to add the merged content in your new WordPress server (in our case, a multi-site WordPress installation) by simply importing a SQL file with our work. However, you have to be careful when doing this too—remember we only worked with a few tables during the migration, which means there are a few WordPress tables (such as, for instance, wp_options) that remained unchanged. So, you can’t replace all your database with an export of your migration file—you have to overwrite the tables you changed only!

To do that, just export a SQL file with the tables we’ve been working with during the past two weeks. Remember to add the DROP TABLE sentence in your exported file, so that tables are completely replaced when the SQL file is imported. Finally, just import the SQL file in your destination WordPress installation and you’re done! If you now go to the Dashboard, you’ll see that all your users, comments, posts, tags… are in place. Wonderful, isn’t it?

Unfortunately, if you go to the Media Library you’ll realize that images are broken… ?

Move Images from Old Servers to their New Location

If you don’t see any images in your new installation, don’t worry—it’s completely normal, for you haven’t moved them from the old server(s) to the new one. Let’s see a method for doing so. It’s not the most efficient method, but it always works (which is what we want, right?).

As you may already know, WordPress stores your images in a directory named /wp-content/uploads/. Since we started with three different websites, I downloaded each web’s assets separately and stored them in three different directories (testing, wprincipiante, and nelio) in my local computer.

Then, I merged the images from testing and nelio (the English blogs) into a single directory. This step allowed me to detect whether we had images with colliding names. If we did, then we’d have to check whether they are the same image (and hence they can be merged without any further ado) or their contents are different (and then we have to decide how we fix this). Luckily for us, there were just a few collisions with images that we uploaded in both blogs, so they actually were the same image.

I moved the images from WPrincipiante to /wp-content/uploads/sites/3/, which is where the Spanish sub-site in our multi-site installation stores images. I then moved the images from the previous merge to /wp-content/uploads/, which is the preferred location for the main, English sub-site.

You can easily upload all these files to your server using an FTP client. In our case, we used a command line tool named lftp, along with its mirror command. This tool allows you to upload files in parallel, increasing the efficiency and reducing upload times. Awesome!

Regenerate Thumbnails

Our new website uses a new theme designed by our colleagues and friends at SiloCreativo. You may have noticed that, when moving from one theme to another, images might look slightly odd. That’s because of thumbnails. When you upload an image to WordPress, WordPress generates multiple thumbnails of said image. The different thumbnails it creates depend on your active theme, which tells WordPress the different sizes it’ll use (and, hence, the thumbnails it needs). Thus, for example, the theme can use a tiny image in its related posts widget, but the full-size image in the single post page.

To overcome this issue, just use Regenerate Thumbnails, a simple and powerful plugin that will help you to regenerate any image’s thumbnails from within your Dashboard. It even helps you to regenerate all the images in your website at once!

No Featured Images in our Posts

Another unexpected surprise came when I realized some old posts didn’t have a featured image. This wasn’t a migration problem—the original posts didn’t have a featured image! Migrations are a great opportunity for fixing whatever it is you don’t like about your site… so I decided I’d fix missing featured image. Plugins like Media Tools or Auto Post Thumbnails look for posts that don’t use a featured image and, for each of them, set the first image in the post as its featured image. It’s not perfect, but it works ?.

SEO-Friendly Migrations

I’m quite sure you want to keep your SEO after the migration, don’t you? To do that, just make sure that old URLs are still accessible and redirect your visitors to the new content using redirections. This can be easily done with a plugin named Redirection.

In our case, we installed this plugin in both Nelio A/B Testing and WPrincipiante. For each post we migrated, we created a redirection rule stating that “the resource your requesting with this old URL is now in this new URL”. In the following you can see a few examples of these redirection rules:

Redirections for posts from Nelio A/B Testing.
Redirections for posts from Nelio A/B Testing.

We checked this redirections and, once we knew they were working properly, we got rid of the original posts in Nelio A/B Testing and WPrincipiante. From that moment on, whenever a visitor accesses a URL in one of these two old installations, the redirection plugin kicks in and redirects him to the new location.

To redirect old Nelio Software‘s URL we decided to apply a different approach. We could have used the Redirection plugin too, but that adds a tiny delay in our response times (for each request our server receives, Redirection would kick in and check if there’s a matching rule for the given URL). Instead, we added a tiny PHP code that hooks into WordPress404_template filter. This filter is executed right before WordPress returns a 404 Not Found error. This way, if WordPress is about to return a 404 error, we just need to check if the user asked for an old URL and, if he did, redirect him to the new URL (using wp_redirect). This has two benefits—on the one hand, redirection rules are only processed when things are about to go wrong and, on the other hand, 404 errors only occur when the user asks for a URL that really doesn’t exist.

Other Problems

Even if you follow all the steps we’ve been discussing in this series, there are some problems you might still encounter. In our particular case, we had a few issues that we didn’t foresee and we had to address. In the following, I’ll briefly review them and, hopefully, give you a hint of what you might face in the future!

SSL Activation

This has been the biggest problem we faced. We wanted our new website to use HTTPS, and so we had to get an SSL certificate and install it in our new server. Long story short, we had to update our DNS entries so that pointed to the new multi-site server and, at the same time, we had to install the certificate in WPEngine (our hosting provider). Things weren’t working and I had no idea why. As it turns out, WPEngine’s internal caches were the problem. Luckily, a brief chat with their support team fixed the issue. So, my advice here is: if you encounter similar issues, ask your hosting provider for help!

Crawl Errors

After launching the new website, there are a few tasks you’ll have to take care of every now and then. One of these tasks is to monitor how the new website works using tools such as Google Search Console. Thanks to these checks, I was able to find out a few invalid redirection rules.

Crawl errors on Google Search Console.
Crawl errors on Google Search Console.

Just look at the console once a week (or every two weeks) during the first few months after the migration, and fix any errors that might pop up.

Future Work

Finally, I’d like to mention a few tasks that we’d like to address at some point, but we didn’t include in the migration itself. If you have the time to address them from the very beginning, I recommend you to do it.

Image Size Reduction

When we moved our images from the old server to the new one, we realized that some of the images we updated a long time ago were too big. This results in more disk space used, more bandwidth consumption, and slower page load times. Using a few scripts, you can quickly determine which images are “too big” and reduce their size before transferring them to your new site.

On the other hand, you might also detect that some images are never used (for instance, thumbnails generated by an old theme). You may want to identify these images and remove them from your migration.

Merge All Webs in Nelio Software

In this migration we only merged our three blogs. However, Nelio A/B Testing and Migrate to WordPress still exist as separate domains. Our goal is to integrate those websites within, as we did with our new service Nelio Content. As you can see, Nelio Content doesn’t have its own website, but it’s part of Nelio Software.

In Summary…

I’ve said it several times during this post series, but I’ll say it once again nonetheless: migrations are complex and details are the key to success. We had a few problems during our migration, but I think the final result is a complete success. The new website has been running for a few weeks now and I can tell you that search engines didn’t penalize us and our user traffic trends are similar to what we had before (even are growing).

If you plan to merge your websites too, just be careful and go step by step—don’t hurry. If you need someone to take care of the migration, don’t trust services that “automate” the whole process and have some money ready. Migrations are complicated and complex, so make sure you ask for an expert’s help.

Featured image from Blake Richard Verdoorn.

Leave a Reply

Your email address will not be published. Required fields are marked *

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.