ThemeLab's Blog

Stay up to date with our newest WordPress themes, WordPress plugins, WordPress tutorials, and other announcements.

Why WordPress Widgets Vanish When Migrating to New URL

Last Updated on by

I was working on a client site the other day and noticed a strange issue: almost all of my widgets vanished when I migrated the site from a local server to a separate development server.

I have a pretty simple procedure for migrating WordPress:

  • Upload the contents of the directory WordPress is installed in
  • Export the database using PHPMyAdmin
  • Replace all references of the old URL to the new one in the database dump
  • Import the updated database dump to the development server

It’s a procedure I’ve been using for years without issue, except this time around, all my text widgets were nowhere to be found on the development site.

The Problem

I luckily stumbled across this post by Andy Stratton: Lost Widgets When Migrating WordPress Domains (dev to production server). In the post, he explains how WordPress stores widget data in a serialized array.

Here’s a simplified example of how a text widget is stored in a WordPress database:

s:5:"title";s:22:"The title of my widget";s:4:"text";s:101:"Text goes here <a href='http://localhost/wordpress/'>This is a link which URL is going to be replaced";

Notice how the number after the s: corresponds with the number of characters in the string that follows (i.e. s:5:”title” … “title” is 5 characters long).

When you do a basic find and replace for all mentions of a URL in a database and the new URL has a different amount of characters than the one before, this will invalidate the serialized array.

Basically, you lose all your widgets that are stored in that array, including individual widgets that didn’t have a URL (or any text for that matter) replaced with a new one with a different amount of characters.

This problem never happened to me before, even when hardcoding old URLs in WordPress posts, because posts (along with all other post types) are stored differently than widgets, and aren’t affected by this sort of serialized data issue.

They widgets are not technically “lost” however, you just need to edit your database (in one way or another) to make the serialized array valid again.

How To Fix It

In my particular case, there were only 5 text widgets that included content with hardcoded URLs. I just manually updated them, then followed my usual migration procedure.

By manually updating them from the widget panel, the string lengths are automatically updated in the database. Alternatively, you could count the new string lengths and edit the database directly, although that’s a little risky and unnecessary when you can just edit the widget text normally.

After importing my new database, my widgets were back!

If you have a ton of offending widgets and would rather not manually update each one, you’re going to need a different & more efficient approach.

It may be worth looking into the WordPress (And Others) Search and Replace Tool. This tool was developed by Interconnect IT to solve this, and similar problems. It’s important to note, however, their disclaimer:

IMPORTANT: This code is supplied with no warranty or support implied. You use it entirely at your own risk. [...] And when you’ve finished using the script, PLEASE delete it as it can pose a serious security risk to your site.

…so yeah, delete it when you’re done.

Note: Also, it was suggested that simply updating the site URL in your WordPress admin panel would solve this issue. This is a technique commonly used when migrating WordPress sites to new URLs. But it doesn’t, and shouldn’t affect text already inside of a widget. Therefore, this method won’t work in this sort of situation.

Shortcodes instead of Hardcodes

Another way of “solving” this issue, is to just never interlink to different URLs on the same site by hardcoding the base site URL into a text widget. Instead, you may want to look into including the page URL with a shortcode instead.

I found a cool plugin called Peter’s Blog URL Shortcodes which gives you access to a number of shortcodes you can use to link to different parts of your site, dynamically.

If you’d rather not install that plugin, you can always just make your own shortcode by adding the following into your functions.php (or separate plugin) file.

function themelab_url_shortcode() {
return get_bloginfo('url');
}
add_shortcode('url','themelab_url_shortcode');

Note: Slightly altered code from the source for less generic function prefixing.

You’ll also need to add some code to allow the use of shortcodes in widget text to your functions.php (or separate plugin) file.

add_filter('widget_text', 'do_shortcode');

Source: DigWP

This way, you don’t have to worry about replacing new URLs in widget data and messing up the string length. The URLs are automatically output by the shortcodes.

Wrapping Up

This may be an issue some of you experienced WordPress developers were already aware of. But if you ran into this problem like I did and were wondering how to fix it, I hope this information came in handy for you.

As well as for future reference, this is definitely something to keep in mind when you’re migrating WordPress to a new URL, especially if you use a lot of text widgets that may be affected by a similar issue.

And yes, I realize this is my first blog post in ages. If you want to know what I’ve been up to lately, check out my recent interview on WPTavern. A quick roundup:

  • I’ve been in college the past few years, hence the lack of updates here.
  • I’m now working full time as a front-end developer (mostly WordPress stuff).

It gives me the chance to work on a lot of awesome WordPress projects, and hopefully some experience I get from that will find it’s way here in the form of blog posts like this one.

  • Ross W

    This is right, but there’s a few other things to know.

    There are all sorts of places where the URL might be encoded in a serialised array. I’ve seen it in widget settings, plugins settings, theme settings, even post_meta for media items.

    Another method I’ve used that’s easier is to use the WordPress Move plugin. To do this, once you’ve copied the database over just update ‘siteurl’ and ‘home’ in the wp_options table, login to wp-admin, install the plugin and then use the migration tool to rename the URL.

    It’s also worth noting that you shouldn’t really do a global search and replace because the ‘guid’ field on in wp_posts should not be updated.

    Finally, if you do a lot of this kind of thing I’d really recommend a tool like ManageWP or InfiniteWP – it will make your life a whole load easier!

    • Leland

      Hey Ross, thanks for the added insights. Nice to know there are a few other (easier) methods of handling this, especially when the issue is not within widget text.

      And thanks for the tip on the ‘guid’ field, I’ll look into that.