Why a plain search and replace breaks WordPress
WordPress stores a lot of settings as serialized PHP arrays. Each string inside one carries its own length, like s:23:"https://old-site.com/x". Replace the domain with a raw SQL find and replace and the string changes length but the number in front of it does not. PHP then refuses to unserialize the value and WordPress silently throws it away. That is why "I changed the domain in the database" so often ends with empty widgets, a theme customiser reset to defaults, and page builder layouts that load as blank pages.
Elementor is the classic casualty. It stores layouts as JSON with escaped slashes, so the old URL appears as https:\/\/old-site.com inside a serialized string. Both layers have to be decoded, replaced and re-encoded correctly or the page is gone.
A migration tool has to unserialize each value, replace inside it, then reserialize with corrected lengths. Everything below assumes you are using one that does, which is the whole point of Dragon Migrate.
Before you start
- Access to both sites. The old site's wp-admin, and a fresh WordPress install on the new domain with its own admin login.
- The exact old and new URLs, including scheme.
https://old-site.comandhttps://new-site.com. If the old site was ever served overhttp://, note that too. You will run a second pass for it. - A recent backup of the old site. Dragon Migrate can take one from the Backups tab in a click. Do it anyway.
- A content freeze. Tell anyone who edits the site to stop until you are done. Anything written after the export is lost unless you export again.
- A low DNS TTL on the new domain if it is already live somewhere. Not essential for the migration itself, but it makes the cutover painless.
Step 1: dry-run the search and replace
Install and activate Dragon Migrate on the old site and open Tools, then Migrate. On the Export tab set Find to the old URL and Replace to the new one, then tick Dry run.
The dry run reports what would change without writing a file: how many rows in which tables, and how many serialized values could not be rewritten safely. A handful of untouchable values is normal (encrypted blobs, binary data). Thousands of them means something is off, usually a stray trailing slash in the Find field.
Save the configuration as a Profile while you are here. You will probably run this more than once.
Step 2: export
Untick Dry run and export. The export streams a gzipped SQL file in batches sized to your host's time and memory limits, so it finishes on shared hosting where a single long request would be killed at 30 seconds. If the tab closes, reopen it: the job resumes from its cursor.
If you also need the files (uploads, themes, plugins), use the Archive tab instead. A full-site archive bundles the database dump with the file tree in one zip.
Download the file from the Export screen. It is served through an authenticated endpoint from a randomly named directory, so the raw path is never exposed. Treat it as sensitive: it is your entire database.
Step 3: import on the new domain
On the new site, install WordPress, install Dragon Migrate, and open Tools, then Migrate, then Import. Upload the dump.
Two things happen automatically:
- A safety backup of the new site's current database is taken first. A wrong import is one restore away from undone.
- The import replaces the database that holds your login session. The job still finishes, because each job carries its own credential, but you will be logged out at the end. Log back in with the old site's admin username and password, because those are the users you just imported.
If the two sites use different table prefixes the import stops and tells you, rather than importing a second set of tables alongside the first. Match the prefix in the new site's wp-config.php and try again.
Step 4: fix what a database move cannot
- wp-config.php. If
WP_HOMEorWP_SITEURLare defined there, update them. They override the database. - Permalinks. Open Settings, then Permalinks and press Save without changing anything. This rewrites the .htaccess or nginx rules for the new domain.
- The http to https pass. If the old site had a history of plain http URLs in content, run Find and Replace again on the new site with
http://old-site.comtohttps://new-site.com. Dry-run it first. - Hardcoded paths. Theme options and some plugins store server paths, not URLs. Search for the old
/home/olduser/public_htmlstyle path if uploads look broken. - Cache and CDN. Purge any page cache and object cache. If you use a CDN, update its origin.
- Third-party services. Google Search Console (add the new property and submit a change of address), analytics streams, payment webhooks, OAuth redirect URLs, licence keys tied to the domain.
Step 5: check the things that break quietly
Open the site with the browser console showing. Mixed content warnings mean an http URL survived. Then check:
- The homepage and two or three builder-built pages render with their layouts.
- Widgets and menus are intact.
- The theme customiser still has your settings.
- Media loads, including images inside galleries and sliders.
- Forms submit and emails arrive.
- WooCommerce, if present: a test checkout, and the webhook URLs in the payment gateway.
Redirect the old domain
Keep the old domain for as long as you can afford to. Serve a permanent 301 redirect from every old URL to its new equivalent, preserving the path. On Apache:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old-site\.com$ [NC]
RewriteRule ^(.*)$ https://new-site.com/$1 [R=301,L]This carries search rankings across and stops the old links on other sites from dying. Once traffic to the old domain has dried up, the broken link report on the new site tells you which of your own internal links still point at it.
Doing it directly between two live sites
If you migrate sites regularly, the download-and-upload step is the tedious part. Dragon Migrate Pro pairs two sites once and then pushes or pulls the database directly, with the same serialization-safe rewrite applied in transit. Media, themes and plugins sync over the same connection, compared by checksum so nothing is sent twice. The receiving site takes a rollback point before the first write and restores it if the transfer fails.
Troubleshooting
Blank page-builder pages after import. Almost always an escaped-slash problem from a tool that did not handle JSON inside serialized data. Re-run the migration with a serialization-safe tool; there is no reliable repair for a broken serialized string after the fact.
"Too many redirects". WP_HOME in wp-config.php disagrees with the database, or the new host forces https while the siteurl option says http. Fix wp-config.php first.
Export times out. It should not, because jobs run in adaptive batches, but a hosting firewall can kill the admin-ajax polling. Use the WP-CLI command instead: wp dragon-migrate export --search=https://old-site.com --replace=https://new-site.com.
Login fails after import. You are typing the new site's credentials. Use the old site's admin login. If you have lost it, reset it with wp user update admin --user_pass=....