How to Show Variations as Single Products in WooCommerce
In this tutorial, I will show you an example of how you can configure your WooCommerce store to display variations as single products.
If you’re wondering how it may look on your store pages, below is a screenshot for you:

Ok, how can we achieve that?
Below, I will show you both programmatic and plugin approaches.
Show Variations as Single Products on Shop and Archive Pages Programmatically
woocommerce_product_query
Honestly, it is easier than you think – you can just use the standard WooCommerce woocommerce_product_query action hook, which is kind of similar to pre_get_posts.
/**
* @snippet Show variations as single products in WooCommerce
* @author Misha Rudrastyh
*/
add_action( 'woocommerce_product_query', 'rudr_variations_as_single_products', 25 );
function rudr_variations_as_single_products( $query ) {
$query->set( 'post_type', array( 'product','product_variation' ) );
}Read this if you don’t know how to use this code snippet.
WooCommerce product pages are already fully compatible with variations, and more than that, the WC_Product_Variation PHP class extends the WC_Product one.
In other words, simply using the code snippet mentioned above on your store is enough to display variations as single products:

Example of using using pre_get_posts (not recommended)
But can we use the pre_get_posts action hook for this purpose? In theory, yes, but I’d recommend avoiding that since we have a WooCommerce-specific action hook. Plus, when using thepre_get_posts hook, you need to keep in mind that it is going to be fired everywhere, even in the WordPress admin dashboard.
Does it mean that variations will start to be displayed as single products in the admin dashboard as well? Surely, no, you just get an error and empty table rows just like on the screenshot:

But if you add a bunch of conditions like this, maybe it will work out well for you:
// better use woocommerce_product_query
add_action( 'pre_get_posts', 'rudr_variations_as_single_products', 25 );
function rudr_variations_as_single_products( $query ) {
// first of all, check if we're in the admin dashboard
if( is_admin() ) {
return;
}
// second, on what pages we want to display variations as single products
if( is_shop() || is_product_category() || is_product_tag() ) {
$query->set( 'post_type', array( 'product', 'product_variation' ) );
}
}Using woocommerce_shortcode_products_query for the [products] shortcode
I am not sure if anyone is still using the old-fashioned [products] shortcodes. If yes, these shortcodes aren’t covered by the woocommerce_product_query hook, and we need to additionally use woocommerce_shortcode_products_query:
add_filter( 'woocommerce_shortcode_products_query', 'rudr_variations_as_single_products_in_shortcode', 25, 2 );
function rudr_variations_as_single_products_in_shortcode( $query_args, $atts ) {
$query_args[ 'post_type' ] = array( 'product', 'product_variation' );
return $query_args;
}Hiding variable products (but not variations) from the product loop
However, I still have a question in my mind: since now we’re showing variations in the product loops just like normal products, why do we ever need to show their parent variable products?
For example, you can see that along with the “Hoodie – Blue, Yes,” we still have the “Hoodie” product displayed. I think it would be quite logical to exclude them from the loop now, right?
Luckily, we can do it quite easily, just by modifying the Tax_Query value inside our woocommerce_product_query hook’s callback function because a product type is just a taxonomy product_type, and we need to exclude the products that have the variable term.
/**
* @snippet Show variations as single products, hide variable products from the loop
* @author Misha Rudrastyh
*/
add_action( 'woocommerce_product_query', 'rudr_variations_as_single_products', 25 );
function rudr_variations_as_single_products( $query ) {
$query->set( 'post_type', array( 'product', 'product_variation' ) );
// let's exclude variable products now
$tax_query = $query->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => 'variable',
'operator' => 'NOT IN',
);
$query->set( 'tax_query', $tax_query );
}If, for some reason, you don’t want to modify the tax_query in your WooCommerce product query, you also have another option – you can exclude variable products by filtering them out by a specific custom field, _variations. So, we just need to modify the Meta_Query value in the WooCommerce product loop.
add_filter( 'woocommerce_product_query_meta_query', function( $meta_query ) {
$meta_query[] = array(
'key' => '_variations',
'compare' => 'NOT EXISTS',
);
return $meta_query;
} );Displaying Variations on Shop Pages Using a Plugin
If you want exactly the same functionality that was described above in this tutorial, then I would recommend you to take a look at this plugin I uploaded on GitHub.
However, if your sole purpose is to allow your store customers to add product variations to the cart directly from the shop and product category pages, then maybe you don’t even need them to be displayed as single products.
What about just allowing to select a variation directly from the shop and category pages?

It can be achieved with my Simple Variation Swatches for WooCommerce plugin
Misha Rudrastyh
Hey guys and welcome to my website. For more than 15 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me