Hello!
There is quite a bit of documentation with how to scale your WordPress site for enterprise. Additionally there are quite a few enterprise WordPress hosting solutions that allow you to “stage” your content on staging sites with automated methods to push or clone the staging site (once an internal approved process gives the thumbs up perhaps) to the live / production website.
These systems are great and not only sanitize and streamline the publication process of your website, but also increases the security and containment of any issues that may come up with your website. The live site can be further locked down and restricted as a result of this type of process because people (administrators, contributors) no longer need to be logging in and interacting with the live production website. All of it can be done on a more private staging site.
For many people this type of process works generally well. Where you may run into problems with this blank slate cut-and-paste staging to production push system is when you have a website that may have user supplied content such as websites that have comments, reviews, forums and other similar user based interactions. Beyond this if you have an e-commerce system such as Woocommerce , then each order is a custom post saved into WordPress that would be overwritten if you pushed your staging site to production.
Its possible to merge changes in these scenarios, and there are a few plugins that do this. We have developed an internal solution for merging changes so you could “push” an entire wordpress database from staging to production, but all the while retaining Woocommerce specific data such as order information. I’ll leave that for a future post to go over.
For now I’d like to go over our new plugin that was just released : Shift8 Push
What is Shift8 Push?
This plugin intends to provide for a relatively straightforward method for one to “push” a single post or page within WordPress from one site to another. This plugin was mostly created as a proof of concept and, depending on the interest level from the broader WordPress community, can be expanded further.
It is assumed you will be installing Shift8 push on the source (i.e. staging) server first and foremost. You then want to configure an application password on the destination server for our plugin to connect, authenticate and push content.
Once thats setup (and you have verified the connection works in the plugin settings), you can simply go to the post or page that you would like to push to the new site. You should see a new “Push” button on the edit page/post screen. Its as simple as that! Pushing the post/page will create (if it doesnt exist already) or update (if it already exists, based on slug).
How to push a single post in WordPress
Curious how it works? Well we use the widely available wp_remote_get function to compile the post data, check if the slug exists and post all the relevant data to the destination site.
Check if the post exists in WordPress with wp_remote_get
Here’s a snippet in our codebase for how we check if the post exists already. This is integral to the plugin determining whether to simply create a brand new post or update an existing one. Since depending on the post ID variable on the source and destination will be problematic as the ID primary keys will certainly drift between two sites, we will resort to matching post slugs instead :
// Check if post exists $check_exists = wp_remote_get( $destination_url . S8PUSH_APIBASE . $post_type . '?slug=' . $post_data->post_name, array( 'method' => 'GET', 'headers' => $headers, 'httpversion' => '1.1', 'timeout' => '45', 'blocking' => true, ) ); $check_object = json_decode($check_exists['body']); // If we found an existing post with slug match if (count($check_object) > 0) { // Code goes here to update }
The $headers variable contains all the authentication information to connect via the application password discussed earlier here.
How to update an existing WordPress post with wp_remote_post
In this next snippet we will take the existing post we’ve found and update it based on the matched slug name :
if (count($check_object) > 0) { $destination_id = esc_attr($check_object[0]->id); $api_response = wp_remote_post( $destination_url . S8PUSH_APIBASE . $post_type . '/' . $destination_id . '/', array( 'method' => 'POST', 'headers' => $headers, 'httpversion' => '1.1', 'timeout' => '45', 'blocking' => true, 'body' => $data, 'data_format' => 'body', ) );
We are simply getting the post ID on the destination server based on the matched slug. Then we are specifying that hey we want to update this post and submit the respective data.
How to create a new post in WordPress with wp_remote_post
If we want to just create a brand new post (if there is no existing slug matched posts) then we want to complete a similar wp_remote_post interaction but this time with no destination post ID specified, which indicates that we want to simply create a brand new post
$api_response = wp_remote_post( $destination_url . S8PUSH_APIBASE . $post_type, array( 'method' => 'POST', 'headers' => $headers, 'httpversion' => '1.1', 'timeout' => '45', 'blocking' => true, 'body' => $data, 'data_format' => 'body', ) );
Does this work with Page builders?
We’ve tested this plugin with Gutenberg, WPBakery Page Builder and Beaver builder. All seem to work fine but more testing is likely ideal as there are so many other page builders out there and potentially more edge cases that may need to be addressed with how specific page builders work. Thankfully what our plugin does is gather all the custom meta keys and values for the post you are trying to push, and include it in the data thats submitted via the wp_remote_post query detailed above. If you have the same plugins installed on the destination server, then it should work.
What about media embedded in the post?
Synchronizing media has not been perfected in this plugin. This is because media can be integrated into a post in a variety of different ways. IF you are using a page builder like WPBakery Visual Composer, Gutenberg Blocks or Beaver Builder, there will be an embedded reference to a media library ID number. This gets tricky when we want to migrate this data as we would then need to take the old ID, upload the image to the destination server and get a new ID then swap the old/new IDs in the embedded post.
Likely having this type of automated functionality would require us to accommodate the many different page builders because they may integrate media in slightly different ways where sometimes data is serialized and sometimes its not.
So for now, you have to push the post data and re-upload the media. Not ideal but again depending on the interest in this plugin, we can justify spending more development time to accommodate.
Conclusion
Again this project started as a proof of concept because not many reliable plugins offer this type of functionality in a simplistic way. There are merging, migration and backup/restore plugins out that that may touch on some of these elements, but many are commercial or too bloated for a simple page/post push system that we are trying to accomplish.
Our solution is free, but still in development and would welcome any support, comments, feedback and testing that anyone is willing to provide.