Blog

How to Add WooCommerce Custom Order Actions

If you’re building a plugin or internal tools for WooCommerce, it’s helpful to be able to run actions or shortcuts for order records, as this is what much of your day-to-day management is concerned with.

Today we’ll look at how to add WooCommerce custom order actions so that you could modify order data, add information to orders, send order data externally, or run any general action that requires order details.

This tutorial requires beginner PHP and WordPress development skills.

What’s Your Action, Action?

First, let’s determine what this action will do, and we can determine if it should always be shown, or if there are some conditions around when it should be added to the actions list.

I’m going to use a pretty simple example here: let’s have an action that adds an internal order note. This note will say the order has been printed and is being packaged. This could be helpful if a couple store managers are working on prepping orders for shipment, as a note ensures others are informed of the order being prepped.

So are there any conditions around this action? I’d like to only show it for paid orders, as we don’t want to be shipping unpaid merchandise.

I’m also going to use a meta key as a flag — this way, I can ensure that my action can only be run once. This may not apply to your use case, but it’s a good process to keep in mind for actions that should have a limited number of runs.

Now that I know when I want my action to run, I know that I want some conditions before I add it to the actions list, both of which depend on the order object. Let’s add it!

Add the Action to the List

Adding a WooCommerce custom order action is pretty straight-forward. The woocommerce_order_actions filter gives us what we need (for the most part) to add our action into the order dropdown.

However, you’ll notice that, while it filters the list of order actions, it doesn’t give us an $order object to work with directly. We do have access to $theorder global, though, so we can use this to run some checks on the order, such as: $order->is_paid() (WooCommerce 2.5+).

Let’s add a function that checks if the order (1) has been paid for, and (2) doesn’t have a flag set that we’ve already used the action — we’ll use a meta key for this.

/**
 * Add a custom action to order actions select box on edit order page
 * Only added for paid orders that haven't fired this action yet
 *
 * @param array $actions order actions array to display
 * @return array - updated actions
 */
function sv_wc_add_order_meta_box_action( $actions ) {
    global $theorder;

    // bail if the order has been paid for or this action has been run
    if ( ! $theorder->is_paid() || get_post_meta( $theorder->id, '_wc_order_marked_printed_for_packaging', true ) ) {
        return $actions;
    }

    // add "mark printed" custom action
    $actions['wc_custom_order_action'] = __( 'Mark as printed for packaging', 'my-textdomain' );
    return $actions;
}
add_action( 'woocommerce_order_actions', 'sv_wc_add_order_meta_box_action' );

That’s all it takes! This will add our custom action for paid orders:

WooCommerce Custom Order Actions Added for Paid Order

Action Added for Paid Order

And this action will not be added for unpaid orders:

WooCommerce Custom Order Actions Hidden for Unpaid Order

Action Hidden for Unpaid Order

Process the Action

Now we need to actually do something when that action is run. While this looks great, it’s not functional yet. We haven’t given WooCommerce any code to know what to do for that action.

So we can write up some code for what that action should do, but where do we hook the code into? That’s where WooCommerce also gives you a tool you can use: each action will have a woocommerce_order_action_{action_id} action added to let you hook into when your custom action is being processed.

In our case, this means the action will be called:
woocommerce_order_action_wc_custom_order_action

This action gives us access to the order object, so it’s pretty straight-forward to hook into it and add some information to the order record.

/**
 * Add an order note when custom action is clicked
 * Add a flag on the order to show it's been run
 *
 * @param \WC_Order $order
 */
function sv_wc_process_order_meta_box_action( $order ) {
    
    // add the order note
    // translators: Placeholders: %s is a user's display name
    $message = sprintf( __( 'Order information printed by %s for packaging.', 'my-textdomain' ), wp_get_current_user()->display_name );
    $order->add_order_note( $message );
    
    // add the flag
    update_post_meta( $order->id, '_wc_order_marked_printed_for_packaging', 'yes' );
}
add_action( 'woocommerce_order_action_wc_custom_order_action', 'sv_wc_process_order_meta_box_action' );

Now we have some code that will run when our action is used so we can execute our WooCommerce custom order action. As you could add multiple custom actions, you’ll need to hook into the action generated for each one separately.

Final Results

So how’d we do? We already saw that our custom action was displayed correctly based on the order status. Now let’s see if it does anything.

When this code is run, our order note is indeed added correctly. Also note that, while this order is paid, the action doesn’t show up again, which means our flag setting and checking is also working as expected.

WooCommerce Custom Order Actions Run

Custom Action Run

That’s it! You can add your own WooCommerce custom order actions within a plugin to add order data, send order data elsewhere, or perform other actions that require order information.

You can also see a full gist of the code above here.

2 Comments

Submit a Comment