Multisite Order Sync in WooCommerce

I’ve been talking a lot about WordPress Multisite synchronisation throughout my blog. And also I have multiple plugins for that, for example – if you are looking for a way to sync WooCommerce products, you can check this plugin, only product inventory – this one.

And right now I would like to talk about WooCommerce orders, specifically about a scenario when you want all the order across your Multisite network to appear on a single store and (optionally) to be removed from the original store where this order has been made.

When an Order is Created (Purchase is Made), Automatically Create its Copy on the Other Store

There are actually two ways how we can achieve that:

  1. We can try to use switch_to_blog() and restore_current_blog() hooks during the order creation process and see what happens. In my opinion it is just a guessing game when literally everything could go wrong. For example the customers could stay on another blog database and who knows what can happen.
  2. Another option is just using woocommerce_new_order action hook, switching to another blog inside of it and create a new order programmatically (there is another tutorial on that) using all the data we have.

In my opinion the second option is safe, so let’s better use it.

add_action( 'woocommerce_new_order', 'rudr_sync_order', 10, 2 );

function rudr_sync_order( $order_id, $order ) {

	// let's prepare some order data first, here we have everything we need
	$order_data = $order->get_data();

	// we don't know product IDs on Site 2, so we must use SKUs, in that case let's reorganize line_items array
	$order_data[ 'products' ] = array();
	foreach( $order_data[ 'line_items' ] as $line_item ) {

		if( ! $sku = get_post_meta( $line_item->get_product_id(), '_sku', true ) ) {
			continue;
		}

		$order_data[ 'products' ][] = array(
			'sku' => $sku,
			'qty' => $line_item->get_quantity(),
			// in the case we assume that prices of products on Site 1 and Site 2 are the same, so I skup subtotal etc
		);

	}

	switch_to_blog( $blog_id );
	
	// super-crucial to remove the hook first, otherwise we will have unlimited amount of orders!!!
	remove_action( 'woocommerce_new_order', __FUNCTION__, 10, 2 );
	// create an order
	$synced_order = wc_create_order();
	// you can decide what order status should be or you can use the one from $order_data
	$synced_order->set_status( 'on-hold' );

	// products
	foreach( $order_data[ 'products' ] as $item ) {
		$synced_order->add_product( wc_get_product( wc_get_product_id_by_sku( $item[ 'sku' ] ) ), $item[ 'qty' ] );
	}
	$synced_order->calculate_totals();

	// set customer data
	$synced_order->set_address( $order_data[ 'billing' ], 'billing' );
	$synced_order->set_address( $order_data[ 'shipping' ], 'shipping' );
	if( $order_data[ 'customer_id' ] ) {
		add_user_to_blog( $blog_id, $order_data[ 'customer_id' ], 'subscriber' );
		$synced_order->set_customer_id( $order_data[ 'customer_id' ] );
	}
	
	// some other data
	$synced_order->set_payment_method( $order_data[ 'payment_method' ] );
	$synced_order->set_payment_method_title( $order_data[ 'payment_method_title' ] );
	$synced_order->set_order_key( $order_data[ 'order_key' ] );
		
	$synced_order->save();

	// add some products
	restore_current_blog();

}

Now let’s dive into the details of this code snippet:

For me it worked out well and a synced order on Site 2 has been created.

WooCommerce Multisite order sync

Delete Orders from the Initial Store

Since we decided to have all the multisite network orders on a single store (Store 2 for example), we probably don’t need them on their initial stores, right?

The first thing that comes to a mind is to add wp_delete_post() function at the end of the function in the previous chapter of this tutorial. But it doesn’t work out well.

Unable to create order WooCommerce error

So what to do? I assume we need to do some stuff on WooCommerce Thank You page. And in my opinion there are two ways how it can be achieved:

  1. Create your own custom Thank You page and redirect to it on order creation.
  2. Modify WooCommerce template (copy to your theme and then modify of course) templates/checkout/thank-you.php.

If you decide to use the second way, the modification assumes the following:

<?php
/**
 * Thankyou page
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/checkout/thankyou.php.
 *
 *  ...
 *
 */

defined( 'ABSPATH' ) || exit;

wp_delete_post( $order->get_id(), true );

switch_to_blog( $blog_id );

$order = wc_get_order( wc_get_order_id_by_order_key( $_GET[ 'key' ] ) );

What we are doing here:

Display the Orders from the Main Store in Member’s area

Since we decided to remove the orders from their inititial stores, we need to display something in My account > Order, don’t we?

And finally I have really great news for you! The function woocommerce_account_orders() that get and displays user orders with the help of template my-account/orders.php is pluggable! It means that we can copy and paste this function in our theme or plugin and its modified version is going to be used automatically.

As simple as that!

function woocommerce_account_orders( $current_page ) {
	
	switch_to_blog( $blog_id );
	
	$current_page    = empty( $current_page ) ? 1 : absint( $current_page );
	$customer_orders = wc_get_orders(
		apply_filters(
			'woocommerce_my_account_my_orders_query',
			array(
				'customer' => get_current_user_id(),
				'page'     => $current_page,
				'paginate' => true,
			)
		)
	);

	wc_get_template(
		'myaccount/orders.php',
		array(
			'current_page'    => absint( $current_page ),
			'customer_orders' => $customer_orders,
			'has_orders'      => 0 < $customer_orders->total,
			'wp_button_class' => wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '',
		)
	);
	
	restore_current_blog();
	
}

So, I modified only lines 3 and 27.

Sync WooCommerce orders and display from the main store only.
I know it is not clear from the screenshot but we are displaying orders from the main store (Store 2) only.

If you have any questions or would like something to add to this guide, welcome to comments, guys. And of course, if you need any custom development – feel free to contact me.

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