Guide to WooCommerce Order Status Change Hooks

In this post, I look at all the different action hooks that fire when an WooCommerce order status changes. There are four hooks you can use:

  1. woocommerce_order_status_$NAME
  2. woocommerce_order_status_$FROM_to_$TO
  3. woocommerce_order_status_changed
  4. woocommerce_order_payment_status_changed

Read on for detailed example of how to use each one:

1. woocommerce_order_status_$NAME

This is the first action hook that fires when an order status is changed in WooCommerce.

To use it, simply replace $NAME with the slug of the status name it is changing to.

For the default WooCommerce statuses, here is how the hook would look:

  • woocommerce_order_status_pending – When an order status is changed to “Pending”
  • woocommerce_order_status_processing – When an order status is changed to “Processing”
  • woocommerce_order_status_on-hold – When an order status is changed to “On-hold”
  • woocommerce_order_status_completed – When an order status is changed to “Completed”
  • woocommerce_order_status_cancelled – When an order status is changed to “Pending”
  • woocommerce_order_status_refunded – When an order status is changed to “Refunded”
  • woocommerce_order_status_failed – When an order status is changed to “Failed”

You can also use it with any custom status you have created. For example, if we have created a “Shipped” custom status, the hook would look like:

  • woocommerce_order_status_shipped

The hook provides the Order ID ($order_id), and Order object ($order) as a parameters.

Example 1:

In this simple example, when an order status is changed to “Processing”, we will add an order note.

add_action( 'woocommerce_order_status_processing', 'add_processing_note', 10, 2 );

function add_processing_note( $order_id, $order) {

    // add a note
    $order->add_order_note( "Cash money!" );



woocommerce order status change hook 1

2. woocommerce_order_status_$FROM_to_$TO

The woocommerce_order_status_$FROM_to_$TO hook allows you to target more specific situations.

You must specify the order status that it is changing FROM, as well as the status it is changing TO.

For example, if you want run a function when the order status changes from “Processing” back to “Pending”, it would look like:

  • woocommerce_order_status_processing_to_pending

This hook also provides the Order ID, and Order object as parameters.

Example 2:

In this snippet, we will send an email when an order status is changed from “Completed” back to “Pending”.

add_action( 'woocommerce_order_status_completed_to_pending', 'completed_to_pending_email', 10, 2 );

function completed_to_pending_email($order_id, $order) {
    // 1. get some order data if you want
    $edit_order_url = $order->get_edit_order_url();

    // 2. send an email
        "[email protected]", // recipient email
        "Something weird happened to Order #$order_id", //subject
        "Order #$order_id was changed from Completed to Pending.  <a href=$edit_order_url>Check it out</a>", //message
        array('Content-Type: text/html; charset=UTF-8'), // email headers



woocommerce order status change hook - woocommerce_order_status_FROM_to_TO
Email that’s sent out

3. woocommerce_order_status_changed

The woocommerce_order_status_changed hook fires on every possible order status change.

That means your custom function will also be triggered for every status change.

woocommerce_order_status_changed provides three parameters to your function — the Order ID, ‘from’, and ‘to’ statuses.

Example 3:

We will copy the basic snippet from the first example and adapt it to use the woocommerce_order_status_changed hook instead.

Using the provided $from and $to parameters, we can specify to add a note only if the order is going from “Pending” to “Processing”.

add_action( 'woocommerce_order_status_changed', 'add_processing_note_v2', 10, 3 );

function add_processing_note_v2( $order_id, $from, $to ) { // 3 parameters provided

    // 1. return if status is not changing from pending->processing
    if( $from!=='pending' && $to!=='processing' ) return;

    // 2. get order object
    $order = wc_get_order( $order_id );

    // 3. add a note
    $order->add_order_note( "Cash money again!" );



woocommerce order status change hook - woocommerce_order_status_changed

Since this hook fires later than the woocommerce_order_status_$NAME hook (from Example 1), our custom note (i.e. “Cash money again!”) is also added later.

The default WooCommerce note (i.e. “Order status changed from Pending payment to Processing”) is added before it. Compare this to Example 1, where the default note is added after.

4. woocommerce_order_payment_status_changed

The woocommerce_order_payment_status_changed hook is fired only when an order is changed from “Pending” to a paid status (i.e. either “Processing” or “Completed”).

It provides two parameters, the order ID and order object

Example snippet

We will again add a custom order note as a basic use example.

add_action( 'woocommerce_order_payment_status_changed', 'add_payment_note', 10, 2 );

function add_payment_note( $order_id, $order ) { 

    // add a note
    $order->add_order_note( "Cash money again, again!" );



Woocommerce order status change hook - woocommerce_order_payment_status_changed


When an order status changes in WooCommerce, there are four possible action hooks you can use depending on your needs. They are triggered in this order:

  1. woocommerce_order_status_NAME
  2. woocommerce_order_status_FROM_to_TO
  3. woocommerce_order_status_changed
  4. woocommerce_order_payment_status_changed

Hope this helps!

WooCommerce Code Reference

Get Weekly WordPress tips

Was this helpful? Every week, I post a useful tip about WordPress and general web development. Subscribe below to get updates by email. (It's free 🙂)

Leave a Comment