Add Custom Order Actions in WooCommerce

Recently I’ve been working on adding some order actions that allow users to manually sync orders to specific stores, as a part of my Order Sync for WooCommerce plugin.

Here is an example:

WooCommerce add custom order actions

I was quite surprised that there were no good explanations over there. So, as usual, let me share with you my experience of how I did it.

The whole process of creating an order action consists of three steps:

  1. We need to use the woocommerce_order_actions hook to add an order action to the list of all order actions.
  2. Then we have to use either woocommerce_order_action_{$action} or woocommerce_process_shop_order_meta to process an order action. Below I will explain the difference between using one or another hook.
  3. Finally, we need to create a custom message to show to our shop users, do we not? In order to do that, we need to use woocommerce_order_updated_messages.

Ok, now let’s jump straight into it.

Step 1. Add an Order Action

First things first, we need to use the woocommerce_order_actions WooCommerce filter hook to add our custom order action into an array of all registered actions.

The hook is very convenient because it has the WC_Order object available as a second argument. So, for example, we can add our custom order actions only for specific order statuses.

add_filter( 'woocommerce_order_actions', 'rudr_add_order_action', 25, 2 );

function rudr_add_order_action( $order_actions, $order ) {
	
	// only for specific order status
	if( ! in_array( $order->get_status(), array( 'processing', 'completed' ) ) ) {
		return $order_actions;
	}

	$order_actions[ 'sync_order' ] = 'Sync to: Store 2';
	return $order_actions;
}

Just add this snippet to your WooCommerce website and here we go:

Custom order action in WooCommerce

Step 2. Process an Order Action

At this moment, our custom order action has appeared in the all order actions list, however, if you select it and try to update an order – nothing will happen.

Quite obviously, it is because we have done nothing to process this order action. Let’s do it right now. Actually, there are two ways how we can do it:

  • Method 1. Using the woocommerce_order_action_{$action} hook – this one should fit you well in most cases and it is a standard way to process an order action.
  • Method 2. Using woocommerce_process_shop_order_meta – in my case, when working with my plugin, Order Sync for WooCommerce, I needed to add order actions dynamically for every connected WooCommerce store, and this hook was a perfect fit for me.

Let’s take a look at both of them.

add_action( 'woocommerce_order_action_sync_order', 'rudr_process_action' );

function rudr_process_action( $order ) {
	
	// do something here
	
	$order->add_order_note( 'Order action has been processed.' );
}

Using woocommerce_process_shop_order_meta is a little bit more complicated:

add_action( 'woocommerce_process_shop_order_meta', 'rudr_process_action', 9999 );

function rudr_process_action( $order_id, $post ) {
	// we need to check if order action parameter is available
	if( empty( $_POST[ 'wc_order_action' ] ) ) {
		return;
	}

	$action = wc_clean( wp_unslash( $_POST[ 'wc_order_action' ] ) );

	if( 'sync_order' !== $action ) {
		return;
	}
	// we need to get a WC_Order object after than
	$order = wc_get_order( $order_id );
	if( ! $order ) {
		return;
	}

	// now, we're ready to process our order action
	// do something here

	$order->add_order_note( 'Order action has been processed.' );
	
}

In this code, I have also added 9999 priority to the hook, it is not necessary, but if you want your order action to be processed after an order is fully updated, you can not use the standard priority of 10.

Step 3. Create a Custom Notice

This is going to be the trickiest part. I assume WooCommerce doesn’t fully support tapping into its order-updated messages.

But we still can do it. In two simple steps.

The first step is we need to use the woocommerce_redirect_order_location filter hook to add a custom message URL parameter values.

The important thing to remember is that we can only use integers! More than that, numbers from 0 to 11 are reserved by WooCommerce itself. In theory, we can use the number 12 but do you remember that other plugins can also do that? So, probably using 12 is not a good idea after all. I decided to use 9123 😁

This first piece of code should be added at the end of either woocommerce_order_action_{$action} or woocommerce_process_shop_order_meta callback function up here.

add_filter( 'woocommerce_redirect_order_location', function( $redirect_to ) {
	return add_query_arg( 'message', 9123, $redirect_to );
}, 9999 );

The second part of the code can be added as a regular filter hook.

add_filter( 'woocommerce_order_updated_messages', function( $messages ) {
	// our custom message goes here
	$messages[ 'shop_order' ][ 9123 ] = 'Order updated and successfully synced.';
	return $messages;
}, 20 );

Please, pay attention to the hook priority here. It won’t work with the default priority.

And here we go:

Creating a custom WooCommerce order action with notices
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 15 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