How to Filter WooCommerce Orders by Custom Fields in the Admin List

In the WooCommerce admin order list, we can already filter by order status, date, and customer. However, often we need to filter orders based on custom metadata fields. In this article, we’ll implement a custom dropdown filter that works seamlessly with both the classic Custom Post Type (CPT) storage and the newer High-Performance Order Storage (HPOS).

Custom order filter in WooCommerce admin

Step 1: Adding the Filter UI

First, we need to inject our custom dropdown menu into the order filtering form. We’ll use two hooks to ensure compatibility: woocommerce_order_list_table_restrict_manage_orders for HPOS and restrict_manage_posts for the legacy post-based system.

add_action( 'woocommerce_order_list_table_restrict_manage_orders', 'wprs_add_order_filter_dropdown', 25, 2 );
add_action( 'restrict_manage_posts', 'wprs_add_order_filter_dropdown', 25, 2 );

function wprs_add_order_filter_dropdown( $post_type, $which ) {
    if( 'shop_order' !== $post_type ) {
        return;
    }
    
    $current_val = isset( $_GET[ 'wprs_custom_field' ] ) ? $_GET[ 'wprs_custom_field' ] : '';
    ?>
    <select name="wprs_custom_field">
        <option value="">Filter by Custom Field</option>
        <option value="value-1" <?php selected( $current_val, 'value-1' ) ?>>Value 1</option>
        <option value="value-2" <?php selected( $current_val, 'value-2' ) ?>>Value 2</option>
    </select>
    <?php
}

Step 2: Processing the Filter Query

Now that the UI is in place, we need to tell WooCommerce and WordPress how to use this value to filter the results. Again, we use two separate hooks for HPOS and CPT compatibility.

For HPOS (High-Performance Order Storage)

add_action( 'woocommerce_order_list_table_prepare_items_query_args', function( $query_args ) {
    if( ! empty( $_GET[ 'wprs_custom_field' ] ) ) {
        $query_args[ 'meta_query' ][] = array(
            'key'   => 'wprs_custom_field',
            'value' => sanitize_text_field( $_GET[ 'wprs_custom_field' ] ),
        );
    }
    return $query_args;
} );

For Legacy CPT Storage

add_action( 'pre_get_posts', function( $query ) {
    if( ! is_admin() || ! $query->is_main_query() ) {
        return;
    }

    global $pagenow;
    if( 'edit.php' !== $pagenow || 'shop_order' !== $query->get( 'post_type' ) ) {
        return;
    }
    
    if( ! empty( $_GET[ 'wprs_custom_field' ] ) ) {
        $query->set( 'meta_query', array(
            array(
                'key'   => 'wprs_custom_field',
                'value' => sanitize_text_field( $_GET[ 'wprs_custom_field' ] ),
            )
        ) );
    }
} );

By implementing both sets of hooks, you ensure that your admin customizations remain functional regardless of the store’s “Features” settings, providing a consistent experience for store managers.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *