Bulk Change Custom Order Statuses

WooCommerce already allows to bulk change default order statuses. But what if you registered your own custom order status and now you would like to add it to bulk actions on the orders page.

Bulk set your custom order status Awaiting Shipment to orders.

You can find the tutorials, where new options for this dropdown select are added via jQuery – these tuts are outdated because since WordPress 3.5.0 you can do it using the hook bulk_actions-{screen_id}.

 * Add your custom bulk action in dropdown
 * @since 3.5.0
add_filter( 'bulk_actions-edit-shop_order', 'misha_register_bulk_action' ); // edit-shop_order is the screen ID of the orders page
function misha_register_bulk_action( $bulk_actions ) {
	$bulk_actions['mark_awaiting_shipment'] = 'Mark awaiting shipment'; // <option value="mark_awaiting_shipment">Mark awaiting shipment</option>
	return $bulk_actions;
 * Bulk action handler
 * Make sure that "action name" in the hook is the same like the option value from the above function
add_action( 'admin_action_mark_awaiting_shipment', 'misha_bulk_process_custom_status' ); // admin_action_{action name}
function misha_bulk_process_custom_status() {
	// if an array with order IDs is not presented, exit the function
	if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
	foreach( $_REQUEST['post'] as $order_id ) {
		$order = new WC_Order( $order_id );
		$order_note = 'That\'s what happened by bulk edit:';
		$order->update_status( 'misha-shipment', $order_note, true ); // "misha-shipment" is the order status name (do not use wc-misha-shipment)
	// of course using add_query_arg() is not required, you can build your URL inline
	$location = add_query_arg( array(
    		'post_type' => 'shop_order',
		'marked_awaiting_shipment' => 1, // markED_awaiting_shipment=1 is just the $_GET variable for notices
		'changed' => count( $_REQUEST['post'] ), // number of changed orders
		'ids' => join( $_REQUEST['post'], ',' ),
		'post_status' => 'all'
	), 'edit.php' );
	wp_redirect( admin_url( $location ) );
 * Notices
add_action('admin_notices', 'misha_custom_order_status_notices');
function misha_custom_order_status_notices() {
	global $pagenow, $typenow;
	if( $typenow == 'shop_order' 
	 && $pagenow == 'edit.php'
	 && isset( $_REQUEST['marked_awaiting_shipment'] )
	 && $_REQUEST['marked_awaiting_shipment'] == 1
	 && isset( $_REQUEST['changed'] ) ) {
		$message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $_REQUEST['changed'] ), number_format_i18n( $_REQUEST['changed'] ) );
		echo "<div class=\"updated\"><p>{$message}</p></div>";

Actually the replacements that must be made are on lines: 10 (bulk action label and value), 19 (action name in the hook) and 31 (your custom order status slug). Other changes are optional.

The code can be used in the functions.php or in your plugin files.

Order note from line 30 (you can find it on the edit order page):

Note that order status changed by bulk actions.

The notice after the bulk order status change has been processed:

The notice that appears when you change order statuses by bulk edit.

If you have any question – leave it in comments below, I will be glad to help you.

More about WooCommerce order statuses

Misha Rudrastyh

Misha Rudrastyh

I love WordPress, WooCommerce and Gutenberg so much. 11 yrs of experience.

Need some custom developer help? Let me know

Follow Misha

Need some help with WooCommerce?

If you need some professional developer help, I will be happy to assist you.

Contact me Who I am?

Comments — 34

Leave a comment

php js HTML CSS Code

I will only use your personal information to contact you. Privacy Policy