Moving Posts between Sites in Multisite Network

Once you moved the posts from one website to another and if you would like to display them in a once place, you can try my plugin for this purpose.

Step 1. Add Bulk Actions

At the very first moment I was not sure how to implement the UI for our task, but I decided to use Bulk actions, because in many cases it will much more convenient to move multiple posts to another blog.

Working with bulk actions, you should also know, that for pages, the filter will look like bulk_actions-edit-page, for custom post types bulk_actions-edit-{CPT name}. Or better read a tutorial about bulk actions on my blog.

add_filter( 'bulk_actions-edit-post', 'misha_my_bulk_multisite_actions' );

function misha_my_bulk_multisite_actions( $bulk_array ) {

 	if( $sites = get_sites( array(
		// 'site__in' => array( 1,2,3 )
		'site__not_in' => get_current_blog_id(), // excluding current blog
		'number' => 50,
	))) {
		foreach( $sites as $site ) {
			$bulk_array['move_to_'.$site->blog_id] = 'Move to "' .$site->blogname . '"';

	return $bulk_array;


Important notice about line 8 – as you can see I set the maximum 50 sites to be displayed here. WordPress Multisite network supports unlimited amount of sites, so if you have 1000+ sites in your Network, you’d better think about another implementation of this step, I can give you two hints:

I have only 3 blogs in my Network, so my result looks like this:

Creating bulk actions for each blog of WordPress Multisite Network

Step 2. Move / Copy Posts

Do not worry about handle_bulk_actions-edit-post filter hook here – it will be the same for Posts, Pages and Custom Types.

add_filter( 'handle_bulk_actions-edit-post', 'misha_bulk_action_multisite_handler', 10, 3 );

function misha_bulk_action_multisite_handler( $redirect, $doaction, $object_ids ) {

	// we need query args to display correct admin notices
	$redirect = remove_query_arg( array( 'misha_posts_moved', 'misha_blogid' ), $redirect );

 	// our actions begin with "move_to_", so let's check if it is a target action
	if( strpos( $doaction, "move_to_" ) === 0 ) {
		$blog_id = str_replace( "move_to_", "", $doaction );

		foreach ( $object_ids as $post_id ) {

			// get the original post object as an array
			$post = get_post( $post_id, ARRAY_A );
			// if you need to apply terms (more info below the code)
			$post_terms = wp_get_object_terms($post_id, 'category', array('fields' => 'slugs'));
			// get all the post meta
			$data = get_post_custom($post_id);
			// empty ID field, to tell WordPress to create a new post, not update an existing one
			$post['ID'] = '';

			switch_to_blog( $blog_id );
			// insert the post
			$inserted_post_id = wp_insert_post($post); // insert the post
			// update post terms
			wp_set_object_terms($inserted_post_id, $post_terms, 'category', false);
			// add post meta
			foreach ( $data as $key => $values) {
				// if you do not want weird redirects
				if( $key == '_wp_old_slug' ) {
				foreach ($values as $value) {
					add_post_meta( $inserted_post_id, $key, $value );


			// if you want to copy posts, comment this line
			wp_delete_post( $post_id );


		$redirect = add_query_arg( array(
			'misha_posts_moved' => count( $object_ids ),
			'misha_blogid' => $blog_id
		), $redirect );


	return $redirect;


Step 3. Show an appropriate notice

This step is just for a better usability, I mean everything should work even if you’ve implemented only Step 1 and Step 2 of this tutorial.

add_action( 'admin_notices', 'misha_bulk_multisite_notices' );

function misha_bulk_multisite_notices() {

	if( ! empty( $_REQUEST['misha_posts_moved'] ) ) {

		// because I want to add blog names to notices
		$blog = get_blog_details( $_REQUEST['misha_blogid'] );

		// depending on ho much posts were changed, make the message different
		printf( '<div id="message" class="updated notice is-dismissible"><p>' .
			_n( '%d post has been moved to &quot;%s&quot;.', '%d posts have been moved to &quot;%s&quot;.', intval( $_REQUEST['misha_posts_moved'] )
		) . '</p></div>', intval( $_REQUEST['misha_posts_moved'] ), $blog->blogname );



Finally we got this:

Moving posts between different blogs in WordPress Multisite network
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on Twitter