I want to do this with WooCommerce product categories, but I guess it should be the same for post categories. I want all categories to display their products, but then i want one category "For free" to display products from all other categories where price is zero.

How can I change it? Should i create some filter? I'm working on child theme to Storefront.

Cheers, Trawa ;)

1 Answer 1


There are three ways you can do this:

1) Create "For Free" category and assign it to all products which have price "0". Then place "Product Categories" widget in sidebar so that user can click on "For Free" category and it will show all products from all categories where price is zero.

2) This option involves some code but does not give only free products. Rather, it lists Free products from all categories whose Sale price is set to zero followed by paid products in ascending order of their Sale price.

In second option you don't need to go and edit all products to assign "For Free" category. Simply paste following code in your theme's functions.php file.

Once you have this code in place it will show Sort by "For Free" option in sorting drop down on the shop page. Selecting it will give you the results as explained above.

//Adds WooCommerce catalog sorting options using postmeta, such as custom fields
    function pn_add_postmeta_ordering_args( $sort_args ) {

        $orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
        // $orderby_value = wc_clean( $_GET['orderby'] ) ;

        switch( $orderby_value ) {

            // Name your sortby key whatever you'd like; must correspond to the $sortby in the next function
            case 'free':
                $sort_args['orderby']  = '_price';
                $sort_args['meta_key'] = '_price';
                $sort_args['meta_value'] = '0';


        return $sort_args;
    add_filter( 'woocommerce_get_catalog_ordering_args', 'pn_add_postmeta_ordering_args' );

    // Add the new sorting arguments to the sortby options on the frontend
    function pn_add_new_postmeta_orderby( $sortby ) {

        // Adjust the text as desired
        $sortby['free'] = __( 'Sort by "For Free"', 'woocommerce' );

        return $sortby;
    add_filter( 'woocommerce_default_catalog_orderby_options', 'pn_add_new_postmeta_orderby' );
    add_filter( 'woocommerce_catalog_orderby', 'pn_add_new_postmeta_orderby' );

3) You can create a shortcode [free_products columns="4"] which will list only Free Products, and mention it in the documentation for Vendors that they can use that shortcode in a page to list free products. Below is the code for the shortcode. You can place this in your theme's functions.php file.

add_shortcode('free_products', 'pn_free_products');

function pn_free_products( $atts ) {
    $atts = shortcode_atts( array(
      'columns' => '4',
      'orderby' => 'title',
      'order'   => 'asc',
    ), $atts );

    $query_args = array(
      'post_type'           => 'product',
      'post_status'         => 'publish',
      'ignore_sticky_posts' => 1,
      'orderby'             => $atts['orderby'],
      'order'               => $atts['order'],
      'posts_per_page'      => 12,
      'meta_query'          => array(
        'key'     => '_price',
        'value'   => 0,
        'compare' => '=',
        'type'    => 'NUMERIC'

    $products = new WP_Query($query_args);

        $columns = $atts['columns'] ;
        $woocommerce_loop['columns'] = $columns;


        if ( $products->have_posts() ) {

            <?php woocommerce_product_loop_start(); ?>

                <?php while ( $products->have_posts() ) : $products->the_post(); ?>

                    <?php wc_get_template_part( 'content', 'product' ); ?>

                <?php endwhile; // end of the loop. ?>

            <?php woocommerce_product_loop_end(); ?>

        } else {
      echo __( 'No products found' );


        return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
  • was supposed to be one comment ;) the thing is, this site is going to have multiple vendor, so you cant expect them to put always additional 'for free' category. sorting should work, but i would prefer sth like this: if category for free, override default loop and go with custom query where price = 0. I dont know wordpress good enough to figure it out. Can you help?
    – Traweczka
    Commented Oct 13, 2016 at 6:42
  • In that case I think you can simply create a shortcode which lists the free products and mention it in the documentation for Vendors that they can use that shortcode in a page to list free products. Commented Oct 13, 2016 at 15:15
  • I have edited my answers and have added 3rd option as probable solution :) Commented Oct 13, 2016 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.