Adding a Featured Image Filter in WooCommerce Admin Product Screen


Hello folks! Today we are going to tackle an interesting problem related to WooCommerce customization. Often, while managing a WooCommerce store, you might want to filter your products based on whether they have a featured image or not. Sadly, as of the time of writing, WooCommerce doesn't provide this functionality out of the box. But, worry not. We will create a small PHP script to do exactly that.

Before we dive into the code, let's understand our strategy. We'll be adding a new dropdown filter to the WooCommerce admin products screen. This filter will allow you to select products that either have a featured image or don't have one.

To accomplish this, we'll use two WordPress hooks. First is restrict_manage_posts, which allows us to add new elements in the filters row. The second one is pre_get_posts, enabling us to alter the main query based on the selected filter option.

Now, let's get into the code.

add_action('restrict_manage_posts', 'filter_products_by_thumbnail');

In this line, we are hooking our function filter_products_by_thumbnail to restrict_manage_posts action. This function will add a new dropdown filter to the products screen.

function filter_products_by_thumbnail() {
    global $typenow;

    if ('product' === $typenow) {
        $selected = isset($_GET['featured_image']) ? $_GET['featured_image'] : '';
        ?>
        <select name="featured_image" id="featured_image">
            <option value=""><?php _e('All products', 'woocommerce'); ?></option>
            <option value="with_thumb" <?php echo selected('with_thumb', $selected); ?>><?php _e('With featured image', 'woocommerce'); ?></option>
            <option value="without_thumb" <?php echo selected('without_thumb', $selected); ?>><?php _e('Without featured image', 'woocommerce'); ?></option>
        </select>
        <?php
    }
}

Inside this function, we are checking if the current post type is 'product' (our WooCommerce products). If yes, we are creating a new select element with three options: "All products", "With featured image", and "Without featured image".

The selected function in PHP is used to retain the selected option after the filter is applied. The $_GET['featured_image'] gets the value of our custom filter from the URL.

add_action('pre_get_posts', 'filter_products_by_thumbnail_query');

Now, we are hooking another function filter_products_by_thumbnail_query to pre_get_posts action. This function will modify the query based on the selected filter.

function filter_products_by_thumbnail_query($query) {
    global $pagenow;
    $type = 'product';
    if (isset($_GET['post_type'])) {
        $type = $_GET['post_type'];
    }
    if ('product' == $type && is_admin() && $pagenow=='edit.php' && isset($_GET['featured_image']) && $_GET['featured_image'] != '') {
        $query->query_vars['meta_key'] = '_thumbnail_id';
        if ('with_thumb' == $_GET['featured_image']) {
            $query->query_vars['meta_compare'] = 'EXISTS';
        }
        if ('without_thumb' == $_GET['featured_image']) {
            $query->query_vars['meta_compare'] = 'NOT EXISTS';
        }
    }
}

Inside this function, we're first checking if the current screen is the admin products screen and if our custom filter is set. If yes, we adjust the query based on the selected filter. We are looking for a meta key _thumbnail_id which is used by WooCommerce to store the featured image. If the selected filter is 'with_thumb', we adjust the query to return only products where this meta key exists. If 'without_thumb' is selected, we adjust the query to return only products where this meta key does not exist.

And voila! Now, we have our custom filter for products based on their featured image.

Remember to backup your code before making any changes and always test new code in a staging environment first. Also, try to avoid making changes directly to your theme files. Use a child theme or custom plugin to add this code so you won't lose your changes when you update your theme.

The whole code would be like this! You can use this together with a plugin like snippets to add php scripts to your site.

add_action('restrict_manage_posts', 'filter_products_by_thumbnail');

function filter_products_by_thumbnail() {
    global $typenow;

    if ('product' === $typenow) {
        $selected = isset($_GET['featured_image']) ? $_GET['featured_image'] : '';
        ?>
        <select name="featured_image" id="featured_image">
            <option value=""><?php _e('All products', 'woocommerce'); ?></option>
            <option value="with_thumb" <?php echo selected('with_thumb', $selected); ?>><?php _e('With featured image', 'woocommerce'); ?></option>
            <option value="without_thumb" <?php echo selected('without_thumb', $selected); ?>><?php _e('Without featured image', 'woocommerce'); ?></option>
        </select>
        <?php
    }
}

add_action('pre_get_posts', 'filter_products_by_thumbnail_query');

function filter_products_by_thumbnail_query($query) {
    global $pagenow;
    $type = 'product';
    if (isset($_GET['post_type'])) {
        $type = $_GET['post_type'];
    }
    if ('product' == $type && is_admin() && $pagenow=='edit.php' && isset($_GET['featured_image']) && $_GET['featured_image'] != '') {
        $query->query_vars['meta_key'] = '_thumbnail_id';
        if ('with_thumb' == $_GET['featured_image']) {
            $query->query_vars['meta_compare'] = 'EXISTS';
        }
        if ('without_thumb' == $_GET['featured_image']) {
            $query->query_vars['meta_compare'] = 'NOT EXISTS';
        }
    }
}

That's all for today. Stay tuned for more WooCommerce tips and tricks! Happy coding, and don't forget to donate!

Did you find this article valuable?

Support Theo van der Sluijs by becoming a sponsor. Any amount is appreciated!