PHPwoocommerceadvanced
WooCommerce Custom Order Status
Create and manage custom order statuses in WooCommerce with email notifications
Faisal Yaqoob
December 23, 2025
#woocommerce#order-status#workflow#order-management#automation
Code
php
1 // Register custom order statuses 2 add_action('init', 'register_custom_order_statuses'); 3 function register_custom_order_statuses() { 4 // Awaiting Shipment status 5 register_post_status('wc-awaiting-shipment', array( 6 'label' => _x('Awaiting Shipment', 'Order status', 'woocommerce'), 7 'public' => true, 8 'exclude_from_search' => false, 9 'show_in_admin_all_list' => true, 10 'show_in_admin_status_list' => true, 11 'label_count' => _n_noop('Awaiting Shipment <span class="count">(%s)</span>', 12 'Awaiting Shipment <span class="count">(%s)</span>', 13 'woocommerce') 14 )); 15
16 // Quality Check status 17 register_post_status('wc-quality-check', array( 18 'label' => _x('Quality Check', 'Order status', 'woocommerce'), 19 'public' => true, 20 'exclude_from_search' => false, 21 'show_in_admin_all_list' => true, 22 'show_in_admin_status_list' => true, 23 'label_count' => _n_noop('Quality Check <span class="count">(%s)</span>', 24 'Quality Check <span class="count">(%s)</span>', 25 'woocommerce') 26 )); 27
28 // Ready for Pickup status 29 register_post_status('wc-ready-pickup', array( 30 'label' => _x('Ready for Pickup', 'Order status', 'woocommerce'), 31 'public' => true, 32 'exclude_from_search' => false, 33 'show_in_admin_all_list' => true, 34 'show_in_admin_status_list' => true, 35 'label_count' => _n_noop('Ready for Pickup <span class="count">(%s)</span>', 36 'Ready for Pickup <span class="count">(%s)</span>', 37 'woocommerce') 38 )); 39
40 // Partially Shipped status 41 register_post_status('wc-partially-shipped', array( 42 'label' => _x('Partially Shipped', 'Order status', 'woocommerce'), 43 'public' => true, 44 'exclude_from_search' => false, 45 'show_in_admin_all_list' => true, 46 'show_in_admin_status_list' => true, 47 'label_count' => _n_noop('Partially Shipped <span class="count">(%s)</span>', 48 'Partially Shipped <span class="count">(%s)</span>', 49 'woocommerce') 50 )); 51 }
WooCommerce Custom Order Status
Create custom order statuses for WooCommerce to better manage your order workflow (e.g., Awaiting Shipment, Quality Check, Custom Processing).
// Register custom order statuses
add_action('init', 'register_custom_order_statuses');
function register_custom_order_statuses() {
// Awaiting Shipment status
register_post_status('wc-awaiting-shipment', array(
'label' => _x('Awaiting Shipment', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Awaiting Shipment <span class="count">(%s)</span>',
'Awaiting Shipment <span class="count">(%s)</span>',
'woocommerce')
));
// Quality Check status
register_post_status('wc-quality-check', array(
'label' => _x('Quality Check', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Quality Check <span class="count">(%s)</span>',
'Quality Check <span class="count">(%s)</span>',
'woocommerce')
));
// Ready for Pickup status
register_post_status('wc-ready-pickup', array(
'label' => _x('Ready for Pickup', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Ready for Pickup <span class="count">(%s)</span>',
'Ready for Pickup <span class="count">(%s)</span>',
'woocommerce')
));
// Partially Shipped status
register_post_status('wc-partially-shipped', array(
'label' => _x('Partially Shipped', 'Order status', 'woocommerce'),
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop('Partially Shipped <span class="count">(%s)</span>',
'Partially Shipped <span class="count">(%s)</span>',
'woocommerce')
));
}
Add Custom Statuses to WooCommerce
// Add custom statuses to order status list
add_filter('wc_order_statuses', 'add_custom_order_statuses');
function add_custom_order_statuses($order_statuses) {
$new_order_statuses = array();
// Add custom statuses in specific positions
foreach ($order_statuses as $key => $status) {
$new_order_statuses[$key] = $status;
// Add custom statuses after processing
if ('wc-processing' === $key) {
$new_order_statuses['wc-quality-check'] = _x('Quality Check', 'Order status', 'woocommerce');
$new_order_statuses['wc-awaiting-shipment'] = _x('Awaiting Shipment', 'Order status', 'woocommerce');
$new_order_statuses['wc-partially-shipped'] = _x('Partially Shipped', 'Order status', 'woocommerce');
$new_order_statuses['wc-ready-pickup'] = _x('Ready for Pickup', 'Order status', 'woocommerce');
}
}
return $new_order_statuses;
}
Add Custom Status to Bulk Actions
// Add custom order status to bulk actions dropdown
add_filter('bulk_actions-edit-shop_order', 'add_custom_status_bulk_actions');
function add_custom_status_bulk_actions($bulk_actions) {
$bulk_actions['mark_awaiting_shipment'] = __('Mark as Awaiting Shipment', 'woocommerce');
$bulk_actions['mark_quality_check'] = __('Mark as Quality Check', 'woocommerce');
$bulk_actions['mark_ready_pickup'] = __('Mark as Ready for Pickup', 'woocommerce');
$bulk_actions['mark_partially_shipped'] = __('Mark as Partially Shipped', 'woocommerce');
return $bulk_actions;
}
// Handle bulk action
add_filter('handle_bulk_actions-edit-shop_order', 'handle_custom_status_bulk_actions', 10, 3);
function handle_custom_status_bulk_actions($redirect_to, $action, $post_ids) {
$status_actions = array(
'mark_awaiting_shipment' => 'wc-awaiting-shipment',
'mark_quality_check' => 'wc-quality-check',
'mark_ready_pickup' => 'wc-ready-pickup',
'mark_partially_shipped' => 'wc-partially-shipped',
);
if (array_key_exists($action, $status_actions)) {
$changed = 0;
foreach ($post_ids as $post_id) {
$order = wc_get_order($post_id);
if ($order) {
$order->update_status($status_actions[$action]);
$changed++;
}
}
$redirect_to = add_query_arg('changed', $changed, $redirect_to);
}
return $redirect_to;
}
Add Custom Status to Order Actions
// Add custom status to order actions dropdown
add_filter('woocommerce_order_actions', 'add_custom_status_to_order_actions');
function add_custom_status_to_order_actions($actions) {
global $theorder;
// Add actions based on current order status
if ($theorder->has_status('processing')) {
$actions['move_to_quality_check'] = __('Move to Quality Check', 'woocommerce');
}
if ($theorder->has_status('quality-check')) {
$actions['move_to_awaiting_shipment'] = __('Move to Awaiting Shipment', 'woocommerce');
}
if ($theorder->has_status('awaiting-shipment')) {
$actions['move_to_partially_shipped'] = __('Mark as Partially Shipped', 'woocommerce');
}
return $actions;
}
// Handle custom order actions
add_action('woocommerce_order_action_move_to_quality_check', 'process_order_to_quality_check');
function process_order_to_quality_check($order) {
$order->update_status('quality-check', __('Order moved to quality check.', 'woocommerce'));
}
add_action('woocommerce_order_action_move_to_awaiting_shipment', 'process_order_to_awaiting_shipment');
function process_order_to_awaiting_shipment($order) {
$order->update_status('awaiting-shipment', __('Order awaiting shipment.', 'woocommerce'));
}
add_action('woocommerce_order_action_move_to_partially_shipped', 'process_order_to_partially_shipped');
function process_order_to_partially_shipped($order) {
$order->update_status('partially-shipped', __('Order partially shipped.', 'woocommerce'));
}
Email Notifications for Custom Status
// Add custom status to emails
add_filter('woocommerce_email_actions', 'add_custom_status_email_actions');
function add_custom_status_email_actions($actions) {
$actions[] = 'woocommerce_order_status_pending_to_awaiting-shipment';
$actions[] = 'woocommerce_order_status_processing_to_awaiting-shipment';
$actions[] = 'woocommerce_order_status_quality-check_to_awaiting-shipment';
$actions[] = 'woocommerce_order_status_awaiting-shipment_to_ready-pickup';
return $actions;
}
// Send email when order moves to "Awaiting Shipment"
add_action('woocommerce_order_status_awaiting-shipment', 'send_awaiting_shipment_email', 10, 2);
function send_awaiting_shipment_email($order_id, $order) {
$mailer = WC()->mailer();
$recipient = $order->get_billing_email();
$subject = sprintf(__('Your order #%s is awaiting shipment', 'woocommerce'), $order->get_order_number());
$message = sprintf(
__('Hi %s,<br><br>Your order #%s has been prepared and is awaiting shipment. We will notify you once it ships.<br><br>Thank you!', 'woocommerce'),
$order->get_billing_first_name(),
$order->get_order_number()
);
$email = $mailer->emails['WC_Email_Customer_Processing_Order'];
$email->send($recipient, $subject, $message, $email->get_headers(), $email->get_attachments());
}
// Send email when order is ready for pickup
add_action('woocommerce_order_status_ready-pickup', 'send_ready_pickup_email', 10, 2);
function send_ready_pickup_email($order_id, $order) {
$to = $order->get_billing_email();
$subject = sprintf(__('Your order #%s is ready for pickup!', 'woocommerce'), $order->get_order_number());
$message = '
<html>
<body>
<h2>Hi ' . $order->get_billing_first_name() . ',</h2>
<p>Great news! Your order #' . $order->get_order_number() . ' is ready for pickup.</p>
<p><strong>Pickup Location:</strong> 123 Main Street, City, State</p>
<p><strong>Hours:</strong> Monday - Friday, 9am - 5pm</p>
<p>Please bring your order confirmation email or ID.</p>
<p>Thank you!</p>
</body>
</html>
';
$headers = array('Content-Type: text/html; charset=UTF-8');
wp_mail($to, $subject, $message, $headers);
}
Display Custom Status in My Account
// Show custom status messages in My Account
add_filter('woocommerce_my_account_my_orders_actions', 'add_custom_status_my_account_actions', 10, 2);
function add_custom_status_my_account_actions($actions, $order) {
if ($order->has_status('awaiting-shipment')) {
$actions['awaiting_info'] = array(
'url' => '#',
'name' => __('Awaiting Shipment', 'woocommerce'),
);
}
if ($order->has_status('ready-pickup')) {
$actions['pickup_info'] = array(
'url' => get_permalink(get_option('woocommerce_myaccount_page_id')) . 'pickup-info/',
'name' => __('Pickup Information', 'woocommerce'),
);
}
return $actions;
}
Status Color Coding in Admin
// Add custom CSS for order status colors in admin
add_action('admin_head', 'custom_order_status_colors');
function custom_order_status_colors() {
?>
<style>
.order-status.status-awaiting-shipment {
background: #ffba00;
color: #000;
}
.order-status.status-quality-check {
background: #a46497;
color: #fff;
}
.order-status.status-ready-pickup {
background: #33ccff;
color: #000;
}
.order-status.status-partially-shipped {
background: #ff9800;
color: #fff;
}
mark.awaiting-shipment {
background: #ffba00;
color: #000;
font-weight: 600;
}
mark.quality-check {
background: #a46497;
color: #fff;
font-weight: 600;
}
mark.ready-pickup {
background: #33ccff;
color: #000;
font-weight: 600;
}
mark.partially-shipped {
background: #ff9800;
color: #fff;
font-weight: 600;
}
</style>
<?php
}
Reports and Analytics for Custom Status
// Add custom status to reports
add_filter('woocommerce_reports_order_statuses', 'add_custom_status_to_reports');
function add_custom_status_to_reports($statuses) {
$statuses[] = 'awaiting-shipment';
$statuses[] = 'quality-check';
$statuses[] = 'ready-pickup';
$statuses[] = 'partially-shipped';
return $statuses;
}
Mark Custom Status as Paid
// Mark custom statuses as paid (for payment complete)
add_filter('woocommerce_order_is_paid_statuses', 'add_custom_status_to_paid_statuses');
function add_custom_status_to_paid_statuses($statuses) {
$statuses[] = 'awaiting-shipment';
$statuses[] = 'quality-check';
$statuses[] = 'ready-pickup';
$statuses[] = 'partially-shipped';
return $statuses;
}
Automatic Status Transition
// Automatically move orders to custom status after certain conditions
add_action('woocommerce_order_status_processing', 'auto_transition_to_quality_check', 10, 2);
function auto_transition_to_quality_check($order_id, $order) {
// Check if order total is over $500
if ($order->get_total() > 500) {
$order->update_status('quality-check', __('High-value order sent to quality check.', 'woocommerce'));
}
}
// Automatically move to ready for pickup if local pickup shipping
add_action('woocommerce_order_status_processing', 'auto_transition_to_ready_pickup', 10, 2);
function auto_transition_to_ready_pickup($order_id, $order) {
$shipping_method = $order->get_shipping_method();
if (stripos($shipping_method, 'local pickup') !== false) {
$order->update_status('ready-pickup', __('Order ready for local pickup.', 'woocommerce'));
}
}
Features
- Multiple Custom Statuses: Awaiting Shipment, Quality Check, Ready for Pickup, Partially Shipped
- Full Integration: Works seamlessly with WooCommerce order system
- Bulk Actions: Change status for multiple orders at once
- Email Notifications: Automatic emails when status changes
- Color Coding: Visual distinction in admin panel
- My Account Integration: Custom status displayed to customers
- Order Actions: Quick status changes from order edit page
- Reports Integration: Custom statuses included in WooCommerce reports
- Payment Status: Mark custom statuses as paid
- Automatic Transitions: Rule-based status changes
- Extensible: Easy to add more custom statuses
Dependencies
- WooCommerce
Related Snippets
WooCommerce Custom Email Notifications
Create custom email notifications for WooCommerce events and triggers
PHPwoocommerceadvanced
phpPreview
// Create custom email class
if (!class_exists('WC_Custom_Order_Email')) {
class WC_Custom_Order_Email extends WC_Email {
...#woocommerce#email#notifications+2
12/23/2025
View
WooCommerce Bulk Discounts and Quantity Pricing
Implement bulk discounts, quantity-based pricing, and tiered discounts in WooCommerce
PHPwoocommerceadvanced
phpPreview
// Apply bulk discount based on quantity
add_action('woocommerce_before_calculate_totals', 'apply_bulk_discount');
function apply_bulk_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
...#woocommerce#pricing#discounts+2
12/23/2025
View
WooCommerce Custom Checkout Fields
Add custom fields to WooCommerce checkout with validation and order display
PHPwoocommerceintermediate
phpPreview
// Add custom fields to checkout page
add_action('woocommerce_after_order_notes', 'custom_checkout_fields');
function custom_checkout_fields($checkout) {
echo '<div id="custom_checkout_fields"><h3>' . __('Additional Information') . '</h3>';
...#woocommerce#checkout#custom-fields+2
12/23/2025
View