Here’s a great customization that all store managers should implement on their WooCommerce website!
For some reason you can refine the backend orders table if you are an admin, but logged in customers can’t filter by order status under My Account > Orders!
This is pretty bad, especially if you run a store where customers place many orders and the My Account Orders tab is full of entries. It may be helpful for customers to search all “Pending” orders for example, or maybe access al their “Completed” ones to download their files again.
So, here’s the fix – you’re welcome!
PHP Snippet: Display Order Status Filters @ WooCommerce My Account > Orders Tab
/**
* @snippet Status Filters @ My Account Orders - WooCommerce
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @compatible WooCommerce 9
* @community https://businessbloomer.com/club/
*/
// ------------
// 1. Let orders query listen to URL parameter
add_filter( 'woocommerce_my_account_my_orders_query', 'bbloomer_my_account_orders_filter_by_status' );
function bbloomer_my_account_orders_filter_by_status( $args ) {
if ( isset( $_GET['status'] ) && ! empty( $_GET['status'] ) ) {
$args['status'] = array( $_GET['status'] );
}
return $args;
}
// ------------
// 2. Display list of filters
add_action( 'woocommerce_before_account_orders', 'bbloomer_my_account_orders_filters' );
function bbloomer_my_account_orders_filters() {
echo '<p>Filter by: ';
$customer_orders = 0;
foreach ( wc_get_order_statuses() as $slug => $name ) {
$status_orders = count( wc_get_orders( [ 'status' => $slug, 'customer' => get_current_user_id(), 'limit' => -1 ] ) );
if ( $status_orders > 0 ) {
if ( isset( $_GET['status'] ) && ! empty( $_GET['status'] ) && $_GET['status'] == $slug ) {
echo '<b>' . $name . ' (' . $status_orders . ')</b><span class="delimit"> - </span>';
} else echo '<a href="' . add_query_arg( 'status', $slug, wc_get_endpoint_url( 'orders' ) ) . '">' . $name . ' (' . $status_orders . ')</a><span class="delimit"> - </span>';
}
$customer_orders += $status_orders;
}
if ( isset( $_GET['status'] ) && ! empty( $_GET['status'] ) ) {
echo '<a href="' . remove_query_arg( 'status' ) . '">All statuses (' . $customer_orders . ')</a>';
} else echo '<b>All statuses (' . $customer_orders . ')</b>';
echo '</p>';
}
// ------------
// 3. My Account Orders Pagination fix
add_action( 'woocommerce_before_account_orders', function() {
add_filter( 'woocommerce_get_endpoint_url', 'bbloomer_my_account_orders_filter_by_status_pagination', 9999, 4 );
});
function bbloomer_my_account_orders_filter_by_status_pagination( $url, $endpoint, $value, $permalink ) {
if ( 'orders' == $endpoint && isset( $_GET['status'] ) && ! empty( $_GET['status'] ) ) {
return add_query_arg( 'status', $_GET['status'], $url );
}
return $url;
}
Thank you for this amazing snippet! There is just a problem and I hope you can solve it.
When someone filters their orders by status, they discover that the My Orders tab URL base has changed. Let me give you an example.
I’ve filtered orders by status “Cancelled”, and the page URL is now: /my-account/orders/?status=wc-cancelled, but now also the URL base for the My Orders tab is: /my-account/orders /?status= wc-cancelled instead of /my-account/orders, I can’t understand what’s causing this problem.
Very good point, I’ve now added an edit to part #3, let me know if it works!