The Order Action Context
I was recently working on a new plugin that we are going to release soon that will add support for order fulfillment through Amazon FBA to WooCommerce and I ran into a question: How can I add a custom Order Action at the top right of the edit order page? Generally, WooCommerce has pretty good developer documentation, and there are a lot of tutorials on other customizations out there, but I could not find an answer in my searches. One problem is that the search term "action" is loaded. It can mean many things in the WooCommerce and WordPress context and there are a ton of hook-releated results for that term. But in this case, the phrase Order Action meant a very specific item in the metabox drop-down of the edit order page that triggers some additional code with the apply or save order button is clicked.
Hopefully this will save you more time than I spent chasing down and experimenting with the solution. My example code is based on the assumption that you will also be working inside the context of your own class. If you are just adding similar code to something like your theme's functions.php file then the format of the add_action() call will be slightly different and you will want to just pass in a string as the second parameter for the function name rather than the array that I'm using.
How to add your custom Order Action Step 1
Actually, once you know the right hooks to use, this is a pretty easy modification to make. The first thing we need to do is get something in that drop-down menu. There are 2 parts to accomplishing this. Part 1 - hook the woocommerce_order_actions action like this:
// add our own item to the order actions meta box
add_action( 'woocommerce_order_actions', array( $this, 'add_order_meta_box_actions' ) );
Part 2 - we need to define the function add_order_meta_box_actions that will actually put the item or items in there like this:
// define the item in the meta box by adding an item to the $actions array
function add_order_meta_box_actions( $actions ) {
$actions['ns_fba_send_to_fulfillment'] = __( 'Send to Amazon FBA', $this->text_domain );
return $actions;
}
What is happening here is that the add_order_meta_box_actions hook automatically receives an array from WooCommerce called $actions that contains everything that is already in the drop-down. We're just adding a new element to that array with our own key (ns_fba_send_to_fulfillment in our example) and value. You'll need to remember the key for the next step.
How to add your custom Order Action Step 2
Next, we need to tell WooCommerce what to do when our custom action is selected and the apply button (or save order button) is clicked. We accomplish this by adding another action handler like this:
// process the custom order meta box order action
add_action( 'woocommerce_order_action_ns_fba_send_to_fulfillment', array( $this, 'process_order_meta_box_actions' ) );
This one is a little trickier. If you notice what is going on, WooCommerce automatically generates hooks per action item in the order actions array. There might be several hooks named like woocommerce_order_action_* and in order to hook into your custom order action item this is where you need to remember and append your key name to the action prefix. So this:
$actions['ns_fba_send_to_fulfillment'] = __( 'Send to Amazon FBA', $this->text_domain );
Led to this:
add_action( 'woocommerce_order_action_ns_fba_send_to_fulfillment', array( $this, 'process_order_meta_box_actions' ) );
Finally, all that is left is to define our process_order_meta_box_actions function like this:
// run the code that should execute with this action is triggered
function process_order_meta_box_actions( $order ) {
// we have the current $order object from the edit order page that we're currently on and can do additional things with it
$this->do_something_else( $order->ID );
}
You could define do_something_else() or you could take additional measures on the $order object right inside your handler.
Avoiding Issues with custom Order Actions
WooCommerce has an extensive structure of hooks (both actions and filters), which is normally a fantastic thing. But once in a while it can have unintended consequences if you aren't aware of all the implications. One thing that I ran into was an infinite loop when my custom action fired. It turned out that this was because one of the things I was doing in my custom order action was updating the order status by calling $order->update_status. I never traced the issue all the way to the source, but I suspect this might be a bug in WooCommerce. The action hooks on update_status() were probably triggering a post_updated status which in turn triggered another update_status and so on. To get around this, since WooCommerce order statues are just normal terms in the taxonomy shop_order_status I just used the normal WP way of doing this:
wp_set_post_terms( $order_id, 'status-name', 'shop_order_status', false );
Since this does not have any WooCommerce hooks attached to it there was no infinite loop implication, but the outcome was identical.
Follow up
What will you do with your custom order actions now that you know how?
Do you run a WooCommerce store and already use Amazon FBA for fulfillment? Or, are you looking for a way to automate your shipping? You can connect Woocommerce to Amazon FBA for a 100% automated shipping solution! Check out our powerful integration that makes it super easy to automatically send your orders to Amazon for fulfillment through WooCommerce FBA.