Migrating WordPress, step by step

If you develop for WordPress, you’re bound to occasionally have to migrate the content of a WordPress website from one place to another.

The simplest approach is to ‘just’ copy the database to a new location, and then solve for problems arising at your website’s new location. However, if your origin installation is having hard-to-identify issues, you’ll also likely take these issues with you to the new location.

WordPress’ native export/import should be the clean solution for migrating content between WordPress installations, but, using this has so often not worked for me that I no longer even try; Imports often time out, and importing content in custom fields is even more of a challenge.

I very recently needed to migrate a bunch of websites out of a WordPress Multisite installation, into their own installations. Once, Multisite seemed like a good idea, but, things change, and Multisite is particularly top-heavy, while also not quite as well supported.
So, once more, I had to shop around for a practical, reliable, and reasonably fast way for migrating content from one WordPress installation to another.

Also, although I was backing up the sites in this multisite installation with Updraft, I’ve found Updraft to be slow and not very reliable. And, either way, it backs up the whole underlying database, leaving me with the problem described above, when wanting to move content around and relying on Updraft as the source of the data to move.
As an aside, Jetpack’s backup feature, though recently doubled in price, works well, but does not support multisite.

There is no shortage of plugins that claim to be able to do WordPress migrations. I tried a number of them, but avoided plugins for which I had to pay before being able to try them out. Considering that most of the free ones failed in what they are supposed to do, I expected that many of the paid ones were not going to be any better, not in the least because several of the paid ones are the ‘pro’ versions of their free counterparts.

Related:  Angry and sad

However, I did find a plugin with which migrating content between WordPress installations was massively simplified. The plugin is WP Import Export Lite. There’s a pro version of the plugin, selling at 109 USD. I have not yet found the need to go with the pro version, but with the experience I’ve had, so far, I won’t hesitate to fork over this money, when needed.

Here’s the step-by-step process I used for migrating content from one WordPress installation (within multisite) to a standalone WordPress installation.

  1. Perform a clean WordPress install.
  2. To the clean install, add all plugins you need. Then activate, and configure them.
    If you use Wordfence, or the Jetpack firewall, be advised that, if you have put your install in a subfolder and you later change the subfolder (like when going ‘live’), you will probably need to update the Wordfence-created user.ini to reflect the change.
  3. If you use custom post types, I typically use CPT UI, migrate your custom post types. CPT UI has a simple export/import feature for this.
  4. If you use ACF, or ACF Pro, migrate your custom fields. ACF also has a simple export/import feature for this.
    In the past, I’ve also played around with Pods, but their functionality has been lagging behind, compared to ACF.
  5. Migrate users, using WP Import Export Lite.
    1. Consider including the ‘User role’ of each user.
    2. Consider including the password for each user.
    3. Consider migrating the ID to a ‘Legacy ID’ custom field.
    4. Add custom fields. Some custom fields you might have to import to a temporary field, for processing in the target WordPress installation.
  6. Migrate taxonomies, one taxonomy at a time, using WP Import Export Lite.
  7. Migrate content, one post type at a time, using WP Import Export Lite.
    1. You can include authors in the migration by including an export field which contains the email address of the author, and then using that to match the author by email, at the time of import.
    2. Include the custom fields. Some might have to go to a temporary field, for processing in the target WordPress installation.
  8. Configure menus, widgets, settings, etc.
  9. Migrate your theme.
Related:  50? Make that 2…

Notes

  • When exporting, make sure you include custom fields, if any.
  • If you include images in your export, set the step size to a low number, on import, to avoid timeouts. Perhaps just set it to ‘1’, to minimise the risk of timeouts.
  • One part of the migration which still needs some custom work, as far as I can tell, is when your custom fields, or post/taxonomy parents, reference other content by ID.
    The only way I can see in which this can be resolved, is by storing the old reference, as well as the old ID, with the imported content, and then writing a custom function, or using the REST API to rebuild these hierarchies, based on these imported, old, IDs.
    Storing the old ID with the imported data also is useful when you need to re-import the same data, as you can use that old ID to match the already imported records with the re-import.
  • WP Import Export Lite allows you to export the output of a PHP function which takes the value of a field. One way to use this, is to output an image URL, when an image ID is referenced.
  • WP Import Export Lite nicely imports images embedded in content, but I don’t believe these imports come with titles or captions, or other media-specific data.
    WordPress offers an export/import for media (as for other content), but exactly these imports often fail through timeouts. However, imports can be run multiple times, without the import generating duplicates, but this then ends up being a cumbersome process, particularly if your media library is large.
    This also complicates a situation where a custom field contains references to IDs of media objects.
    However, there’s another plugin, Moving Media Library, which seems to work well in moving the data of your media library.
    Pleasantly, the plugin allows for mapping old user IDs to new user IDs, even if you have to move the files yourself. Worse, custom fields are not migrated.
Related:  Replacing Postlight's Mercury scraping service with your self-hosted copy