helban.dev

Clone a WordPress site: what the copy keeps and what breaks

Copy a WordPress site together with its database and the forms, menus and images come along, because the IDs that connect them travel with the database. What breaks is a site rebuilt from theme code into a fresh database, where every ID written into a pattern points at nothing. Below is a master site I built for a client who wanted a new local site for each type of service, and how it handles both routes.

Stack: WordPress · GeneratePress Premium · GenerateBlocks Pro · WP-CLI Scope: child theme + provisioning scripts Delivered: July 2026

Why use one WordPress theme for multiple websites?

The client runs local sites that bring in inquiries, one for each type of service. Every one of them does the same job: describe a service, show a phone number, take an inquiry. The name, the colors, the contact details and the wording are what change. Built by hand, site number twenty costs as much as site number one.

So the brief was a master site first and, as a later stage, a script that clones it. I added my own scripts that install and update the master. That raises the bar: the master has to keep working after someone copies it and changes the details, and looking right on the day it ships is the easy part.

How do I duplicate a WordPress site without losing forms and menus?

Copy the database along with the files. The clone tools in hosting panels do that, and so do migration plugins: Duplicator, for one, packs the site's files and database into a single file. In WordPress, the form on a page, the menu in the header and the image in a block all point at other records by number. A database copy keeps every one of those numbers, so each reference still finds its target.

I tested this before handing the master over, rather than take it on faith. I copied its database and uploads into a second, empty WordPress at a different address, installed the same theme and plugins, and replaced the old domain throughout the database. The copy came up with all 28 design classes the master had at the time, and its computed styles matched the original's with zero differences. The form rendered with all its fields, and the business details were in the structured data. The old domain appeared nowhere in the page it served.

That test has two limits. It was a copy onto a second WordPress of my own, not a run of the duplication tool in the client's hosting panel, although the mechanism is the same: files and database moved to a new address. And it came before the header menu and the card photos existed, so for those two the argument is in the next section.

When do database IDs break a WordPress copy?

When the site is rebuilt instead of copied. This master lives in theme files: a block pattern for each section of the page, and a script that installs them into an empty WordPress. A new installation means a new database, and the new database numbers everything from scratch.

It showed up on the very first installation. The hero pattern carried the form as "formId":28, the number the form had been given in my local database. On the client's server the same form was post 6. GenerateBlocks Pro embeds a form by that number, so the pattern as written would have shown the form on one machine only, mine, and nothing everywhere else.

So nothing in the theme or its patterns carries a number the database invented. The form is looked up by its slug when the page is put together. The header menu is read by its slug, and the update script creates that menu if it doesn't exist. The placeholder photo on the service cards is a file inside the theme, not an upload, because an upload's ID belongs to the database it was uploaded into. A search of the theme for such numbers finds none. A copied site would have been fine either way; it is the rebuilt one that would have lost its form.

What should change between cloned sites?

Six things, all in one Customizer section: business name, logo, brand color, phone, email and address. They take nine fields, because the address uses four. After a copy, nothing else needs touching.

The address is split on purpose. Google wants a local business address in parts, not as one line of text. A single field would have to be split by guesswork, and the first address typed in an unexpected format would quietly produce broken structured data, on sites whose whole point is local search. The address line in the footer is built from the same four fields, so what visitors read and what Google reads can't drift apart.

Should every cloned site look the same?

I thought so. I recommended keeping the design in the theme's code, under version control, so fifty sites could never drift apart. The client said no and gave the reason in the same message: these sites are meant to look different from each other. They are not branches of one franchise.

He was right, and I had answered a question he never asked. Identical sites matter when the brand is what you sell. Here each site is its own product and should feel like a separate local business. So the design stays in each site's database as global classes that can be edited per site, and my job changed from preventing drift to making it cheap.

The test copy showed what that means in practice. I changed the brand color and the business name on the copy only. The copy changed everywhere the color is used, and the original next to it stayed exactly as it was.

How do you update cloned sites after launch?

With three scripts. The first turns an empty WordPress into the master. The second deploys changes: it copies the theme across, deletes files that have left the repository, runs the migration and clears the caches. The third, the migration, changes content that already sits on the pages.

All three can run again without harm. A second run of the installer repairs instead of creating duplicates. It also compares what is on the site with what it would write, refuses when the two differ, and names the script to run instead. That guard came from a near miss. When the client's first round of fixes was ready, rerunning the installer would have replaced his own headline, his copy and his branding with my demo values. He edits his own pages, so any script that touches them has to assume his text is there.

The migration reads the blocks already on a page and changes only what it has to, leaving his wording alone. It has a test with eight assertions. Two of them check that his exact text survives the change and that a second run leaves the markup identical down to the byte.

What should you check after cloning a WordPress site to a new domain?

The page cache, first. On the client's host, saving the business name in the Customizer cleared the cached page at once. Changing the same field from the command line did not, and a logged-out visitor kept getting the old name from the cache. A script that writes a new site's details has to clear the cache itself, or the new site can show its first visitors the details of the site it was copied from.

Second: where the inquiry form sends mail

The form sends to the address in the Customizer's email field. If that field is left empty on a new site, inquiries go to the site's admin address instead. Mail still goes out, so nothing looks wrong. Fill in the fields, then send yourself a test inquiry before any phone number goes live.

Where does this project stop?

Cloning the sites was planned as a second stage, and the client never funded it. I didn't build the clone script, and I have never used the duplication tool in the client's hosting panel. What this project proves is the master and its tooling, plus the test copy described above.

So there are no figures here about live sites, traffic or rankings, because I measured none.

Planning sites for several locations?

Tell me how many sites you expect and what really differs between them. The answer decides whether you need a template at all, and if you don't, I will tell you.

Ask about your build