Add Custom Order Statuses to WooCommerce (HPOS Compatible)

WooCommerce ships with seven core order statuses: Pending Payment, Processing, On Hold, Completed, Cancelled, Refunded, and Failed. They cover the basics, but real fulfillment workflows usually need more. Awaiting customer reply. Quality check. Awaiting supplier. Backordered. Every business has its own gaps.

You can add custom statuses with a few hooks. Most tutorials online predate High-Performance Order Storage (HPOS) and miss the pieces that make new statuses behave like first-class citizens: showing up in admin filter tabs, in bulk action dropdowns, and styled with a color of their choice. The snippet below works on both HPOS and legacy storage and lets you add as many statuses as you need.

/**
 * Register custom WooCommerce order statuses.
 *
 * Each entry in $statuses creates one new order status with its own label,
 * admin filter tab, and color. Add or remove entries to fit your workflow.
 */
add_action('init', function () {

    $statuses = array(
        'wc-awaiting-review' => array(
            'label' => _x('Awaiting Review', 'Order status', 'woocommerce'),
            'label_count_singular' => 'Awaiting Review',
            'label_count_plural'   => 'Awaiting Review',
        ),
        'wc-quality-check' => array(
            'label' => _x('Quality Check', 'Order status', 'woocommerce'),
            'label_count_singular' => 'In Quality Check',
            'label_count_plural'   => 'In Quality Check',
        ),
    );

    foreach ($statuses as $slug => $config) {
        register_post_status($slug, array(
            'label'                     => $config['label'],
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop(
                $config['label_count_singular'] . ' (%s)',
                $config['label_count_plural']   . ' (%s)',
                'woocommerce'
            ),
        ));
    }
});

Status slugs must start with the wc- prefix. WooCommerce strips it when displaying the status name and uses it internally to identify core vs custom statuses. Skip the prefix and the status will register, but WooCommerce won’t recognize it as an order status.

Add the Statuses to the WooCommerce Dropdowns

Registering the status with WordPress is step one. To make it appear in the order status dropdown on the edit-order screen and in the bulk actions menu, hook into wc_order_statuses.

/**
 * Add custom statuses to the WooCommerce order status dropdowns.
 */
add_filter('wc_order_statuses', function ($statuses) {
    $statuses['wc-awaiting-review'] = _x('Awaiting Review', 'Order status', 'woocommerce');
    $statuses['wc-quality-check']   = _x('Quality Check', 'Order status', 'woocommerce');
    return $statuses;
});

Style the Status Badges

Built-in statuses have distinct colors. New statuses default to grey, which makes them hard to spot in long order lists. Add a few CSS rules to your admin stylesheet (or echo them in admin_head) to give each status its own color. The badge class is status-{slug-without-wc-prefix}, so wc-awaiting-review becomes .order-status.status-awaiting-review.

.order-status.status-awaiting-review {
    background-color: #fff8e5;
    color: #94660c;
}

.order-status.status-quality-check {
    background-color: #e5f5fa;
    color: #0073aa;
}

Why HPOS Compatibility Matters

Older tutorials often register the status only with register_post_status() and rely on the legacy custom-post-type behavior. On HPOS stores, orders live in dedicated database tables, not the wp_posts table. The good news: WooCommerce still reads register_post_status() to know which statuses exist, and the wc_order_statuses filter still controls dropdowns. Both code paths above work identically on legacy and HPOS storage.

The one thing that does not work on HPOS is querying orders by status with WP_Query. Always use wc_get_orders() instead, which routes through the correct data store regardless of where orders are stored.

Verification

  1. Add the snippet to your child theme’s functions.php or a custom plugin
  2. Navigate to WooCommerce > Orders
  3. The new statuses should appear as filter tabs at the top of the list (Awaiting Review, Quality Check)
  4. Open any order, click the status dropdown, and confirm the new options appear
  5. Change an order to one of the new statuses and confirm the badge displays with the color you set

Need Help?

Learn how to add custom code to WordPress or reach out for custom development help.


About the Author

Ali Khallad

Ali Khallad

I’m Ali Khallad, a WordPress developer who’s been building custom plugins and WooCommerce solutions for over 10 years. I created Mega Forms and several extensions you’ll find on Carticy. I love solving tricky WordPress problems and sharing what I learn along the way. When I’m not coding, you’ll find me travelling, riding horses, or hunting down the best local food wherever I am.


More Code Snippets