How to Auto-Post From One WordPress Site to Another

In this tutorial I am going to show you how you can automatically post an article to another WordPress website with the help of a couple of hooks and REST API. There is also an alternative way of doing that with my Simple WP Crossposting plugin, we’re also going to cover in just a little bit.

By the way, in the similar tutorials about this topic it is usually recommended to use a RSS feed and a plugin which allows to import the content from a feed. Well, this may work when your post consists only from a title and some content but it won’t work of course for complex posts with custom fields, featured images etc.

Right now we’re going to dive deep into the coding solution, in case you don’t want to deal with the code you can either just scroll down or click this link to jump to the next chapter of this tutorial.

Which Hook to Use?

So, our goal here is to automatically run a function which allows us to auto-post to the other WordPress site every time we create a post (or a page, or a custom post type – we will decide it later).

Most likely you already know about save_post hook, but there are also save_post_{post type} and rest_after_insert_{post type}. Which one to use? Check the table below.

HookDescription
save_postThis hook runs every time a post (of any post type) is saved or updated.
save_post_{post type}This hook appeared in WordPress 3.7 and it is absolutely identical to save_post except one thing – you can provide a post type name as a part of the hook. For example if we’re going to run it for posts only, it will be save_post_post, for pages – save_post_page.
rest_after_insert_{post type}This one appeared in WordPress 5.0 and it is about to run only when a post is created or updated via REST API. So if you’re using Classic Editor plugin or your custom post type simply doesn’t support the Block Editor, then this hook is not for you.

In my my opinion it would be great to use the save_post_{post type} hook, because there will be no need to check for a post type inside the function. And I think we can do the whole thing for standard WordPress posts, in that case our hook will be save_post_post.

add_action( 'save_post_post', 'rudr_auto_post_to_other_site', 25, 2 );

function rudr_auto_post_to_other_site( $post_id, $post ) {
	
	// do the auto-post to the other WordPress site here
	
}

The thing with obsolete meta boxes in the Block Editor

Today there are two ways of presenting custom fields in Gutenberg:

  1. Using Plugin Sidebars (correct way),
  2. Using meta boxes the same way we used them before (backward compatiblity).

When you choose the second way, the meta fields are going to be displayed like this:

Advanced Custom Fields example in Gutenberg
Old-fashioned way of creating custom fields.

Let’s assume that we don’t care much how they look, but what we really care is how save_post and rest_after_insert_{post type} are going to work.

I just want you to keep in mind that when you’re displaying meta boxes that way, save_post (and save_post_{post type} accordingly) are going to run twice – before custom fields are saved and after the custom fields are saved. In other words Gutenberg performs an additional request to post.php (yes, it is not a REST API request) to save the meta boxes.

How to differentiate these kind of requests in the code? Easier than you think.

if( isset( $_REQUEST[ 'meta-box-loader' ] ) ) && $_REQUEST[ 'meta-box-loader' ] ) {
	// saving meta boxes	
}

So, if you’re going to use meta boxes the old-fashioned way, keep it in mind.

Auto-Post to the Other Site using REST API

Now we know the basics and are ready to do some auto-posting. In this example we are going to auto-post only once, when the post is initially published. It means that further post updates are not going to be synced with the other site.

If you need post updates to be synced as well or just got overwhelmed with the coding, please scroll down to the plugin solution.

/*
 * Auto-posting to another site
 * @author Misha Rudrastyh
 */
add_action( 'save_post_post', 'rudr_auto_post_to_other_site', 25, 2 );

function rudr_auto_post_to_other_site( $post_id, $post ) {
	
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	
	if( 'publish' !== $post->post_status ) {
		return;
	}
	
	// here we need to provide username and application password
	$login = '';
	$pwd = '';
	
	// let's provide the post data for the REST API request
	$post_data = array(
		'title' => $post->post_title,
		'status' => $post->post_status,
		'date' => $post->post_date,
		'slug' => $post->post_name,
		'menu_order' => $post->menu_order,
		'content' => $post->post_content,
		'meta' => array(),
	);
	
	// so we are using some custom fields, we need to add them to the request
	$post_meta = get_post_meta( $post_id );
	foreach( $post_meta as $meta_key => $meta_values ) {
		// simplified version for this tutorial
		$meta_value = reset( $meta_values );
		// add to the REST API request body
		$post_data[ 'meta' ][ $meta_key ] = $meta_value;
	}
	
	// auto-posting to "https://ANOTHER-WEBSITE"
	wp_remote_post(
		'https://ANOTHER-WEBSITE/wp-json/wp/v2/posts',
		array(
			'headers' => array(
				'Authorization' => 'Basic ' . base64_encode( "$login:$pwd" )
			),
			'body' => $post_data
		)
	);
	
}

Please keep in mind that a REST API endpoint will be different for pages and custom post types, so you will need to change /v2/posts to /v2/pages or /v2/{rest api base}.

How to check whether we’re publishing or updating a post?

If you don’t perform that kind of check, be ready for post duplicates to be created on another site. And there are different ways to check that.

First of all you can try to compare the post publish and last modified dates like this:

if( $post->post_date !== $post->post_modified ) {
	return;
}

When I test it on my localhost, everything works perfectly, but I assume this method may not work out on some slow sites (maybe).

So the safest way is to send an extra REST API request and to check whether the post with the same slug already exists:

if( 0 === strpos( wp_get_referer(), 'post-new.php' ) {
	return;
}

$request = wp_remote_get( add_query_arg( 
	array( 
		'slug' => $post->post_name 
	), 
	'https://ANOTHER-WEBSITE/wp-json/wp/v2/posts'
) );
if( 'OK' === wp_remote_retrieve_response_message( $request ) ) {
	$posts = json_decode( wp_remote_retrieve_body( $request ) );
	if( $posts ) {
		return;	
	}
}

Auto-Post to the Other Site using my Plugin

In this chapter I am going to cover how you can configure auto-posting to the other WordPress sites with the help of my Simple WP Crossposting plugin. First of all please install and activate the plugin on the site where you would like to do the auto-posting from and then jump straight into the plugin settings.

The first thing you need to do is to open “Sites” tab and add the other WordPress sites there.

how to add sites in plugin settings
In order to add a site, provide its URL and also a username and an application password.

Then on the “General” tab please check “Auto mode” option – it actually allows auto-posting.

Turn on the auto-posting to the other WordPress sites
On this settings page you can also decide what post types to allow for auto-posting.

That’s pretty much it! When you create or update a post on your website it will be automatically created or updated on the other sites you added before on the “Sites” tab.

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 X