Sync Users Between Sites
In this post we are going to talk about REST API, particularly about how to sync user registrations, profile updates and removals between two completely separate WordPress websites.
If you need to sync posts instead, then I can suggest you a tutorial and a plugin.
Create a User on the Second Website Automatically
When a user is created on a WordPress website either by a registration form or manually, in both cases user_register
action hook is going to be fired. So our goal is to add a REST API request to an external website to the hook.
This is how we can do it:
add_action( 'user_register', 'rudr_register_user_both_sites', 10, 2 );
function rudr_register_user_both_sites( $user_id, $user_data ) {
$login = '';
$pwd = '';
$request = wp_remote_post(
'https://WEBSITE-DOMAIN/wp-json/wp/v2/users',
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$login:$pwd" )
),
'body' => array(
'username' => $user_data[ 'user_login' ],
'first_name' => $user_data[ 'user_login' ],
'last_name' => $user_data[ 'last_name' ],
'email' => $user_data[ 'user_email' ],
'url' => $user_data[ 'user_url' ],
'roles' => $user_data[ 'role' ],
'password' => $user_data[ 'user_pass' ],
)
)
);
if( 'Created' === wp_remote_retrieve_response_message( $request ) ) {
$body = json_decode( wp_remote_retrieve_body( $request ) );
update_user_meta( $user_id, 'user_id_2', $body->id );
}
}
- This code can be easily inserted into your theme
functions.php
file, but there are some moments you need to keep in mind, all of them are described here. - You also need to provide the administrator username of an external website (where you’re going to duplicate users) and an application password, how to get it is described here.
- It is also possible to add some user metadata with meta argument but I decided to skip this part in terms of simplicity but maybe I can describe this moment in comments. Or should I develop a plugin for syncing users between WordPress sites? What do you think guys? Let me know in comments.
- Please look also what is happening on lines 26-29, we retrieve ID of newly created user on “Site 2” and store it as user meta on “Site 1”. It is needed for updating users.
Sync User Profile Update
This step is similar, we just going to use a different hook profile_update
and a slightly different REST API endpoint (we will provide a user ID as a part of it). And course we need to know a user ID on “Site 2”, luckily we have already stored it in user meta when created a user.
add_action( 'profile_update', 'rudr_user_update', 10, 3 );
function rudr_user_update( $user_id, $old_user_data, $user_data ) {
$login = '';
$pwd = '';
$user_id_2 = get_user_meta( $user_id, 'user_id_2', true );
if( ! $user_id_2 ) {
return;
}
$request = wp_remote_post(
'https://WEBSITE-DOMAIN/wp-json/wp/v2/users/' . $user_id_2,
array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$login:$pwd" )
),
'body' => array(
'name' => $user_data[ 'display_name' ],
'first_name' => $user_data[ 'user_login' ],
'last_name' => $user_data[ 'last_name' ],
'email' => $user_data[ 'user_email' ],
'url' => $user_data[ 'user_url' ],
'roles' => $user_data[ 'role' ],
'password' => $user_data[ 'user_pass' ],
'description' => $user_data[ 'description' ],
)
)
);
}
Removing Users on Both Sites at the Same Time
add_action( 'delete_user', 'rudr_user_delete' );
function rudr_user_delete( $user_id ) {
$login = '';
$pwd = '';
$user_id_2 = get_user_meta( $user_id, 'user_id_2', true );
if( ! $user_id_2 ) {
return;
}
$request = wp_remote_request(
add_query_arg(
array(
'force' => true,
'reassign' => 1
),
'https://WEBSITE-DOMAIN/wp-json/wp/v2/users/' . $user_id_2
),
array(
'method' => 'DELETE',
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( "$login:$pwd" )
)
)
);
}
In this example please take a look at the required query arguments force
and reassign
, if you do not provide them, REST API request is not going to work.
Guys, what do you think? Would you like a plugin for that? Please, let me know in comments.

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
Fantastic!
This content has been immensely helpful.
I appreciate your kindness
I will replicate updates on this
Thanks for this post!
I’ve implemented something like this myself and found a few issues which your implementation has as well.
1. When the user update the password via a password reset link, the profile_update hook is not called. You can use the hook after_password_reset to get the password in plain text and update the user on the other site.
2. When the user updates their password the user_pass get via the profile_update hook is already hashed. By sending the password to the other site the password get hashed a second time on that site. Which makes the password incorrect. So you should not set the password property in that remote_request call.
You can not get a plain text password from the hashed password (which is a good thing) and you can’t prevent the double hashing via a hook on the remote site.
But, you can get the updated password in plain text via the user_profile_update_errors hook. This is fired before updating the user. You can check via that hook if there is a new password and if so, update the password on the remote site.
3. When the user does not have the user_id_2 metafield, because the user is already added on the other site before this implementation. You can find the remote user id via the email by calling the endpoint https://WEBSITE-DOMAIN/wp-json/wp/v2/users?search=<>