By default, WooCommerce allows sorting products by date, price, popularity, and more, but it does not provide an easy way to display products in a custom order within a category. If you’re looking to showcase specific products first while displaying the rest of the category items below, this guide is for you!

We’ll create a shortcode that:

  • Displays selected products in a custom order.
  • Lists all remaining products from a specified category below them.
  • Ensures correct column spacing for a neat and responsive layout.

Let’s dive in!

Step 1: Add the Custom Shortcode in Your Theme’s functions.php File

Copy and paste the following PHP code into your functions.php file:

function custom_product_order_shortcode($atts) {
    $atts = shortcode_atts([
        'ids' => '',       // Custom product IDs (comma-separated)
        'category' => '',  // Product category slug
        'columns' => '3'   // Default to 3 columns
    ], $atts, 'custom_order_products');

    $custom_ids = !empty($atts['ids']) ? array_map('intval', explode(',', $atts['ids'])) : [];
    $columns = intval($atts['columns']); // Convert columns to integer

    // Set WooCommerce columns dynamically
    add_filter('loop_shop_columns', function () use ($columns) {
        return $columns;
    });

    // Base query args
    $args = [
        'post_type'      => 'product',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'orderby'        => 'post__in', // Maintain custom order
        'post__in'       => $custom_ids,
        'tax_query'      => []
    ];

    // Add category filter if provided
    if (!empty($atts['category'])) {
        $args['tax_query'][] = [
            'taxonomy' => 'product_cat',
            'field'    => 'slug',
            'terms'    => $atts['category']
        ];
    }

    // Get remaining products from the category (if custom IDs are provided)
    if (!empty($custom_ids)) {
        $remaining_products = get_posts([
            'post_type'      => 'product',
            'post_status'    => 'publish',
            'posts_per_page' => -1,
            'fields'         => 'ids',
            'exclude'        => $custom_ids,
            'tax_query'      => [
                [
                    'taxonomy' => 'product_cat',
                    'field'    => 'slug',
                    'terms'    => $atts['category'],
                ],
            ],
        ]);

        // Merge selected and remaining products while keeping the custom order
        $args['post__in'] = array_merge($custom_ids, $remaining_products);
    }

    // Start WooCommerce output buffering
    ob_start();

    // Force WooCommerce grid classes
    echo '<div class="woocommerce"><ul class="products columns-' . esc_attr($columns) . ' products-' . esc_attr($columns) . '">';

    // Custom WooCommerce Query
    $query = new WP_Query($args);
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            wc_get_template_part('content', 'product'); // WooCommerce default product template
        }
        wp_reset_postdata();
    } else {
        echo '<p>No products found.</p>';
    }

    echo '</ul></div>'; // Close wrapper

    return ob_get_clean();
}

add_shortcode('custom_product_order', 'custom_product_order_shortcode');

Step 2: Adjust the CSS for Proper Product Columns

Ensure that the products are displayed correctly in a three-column layout. Add the following CSS to your theme’s stylesheet (style.css):

ul.products .product {
    padding: calc((var(--woocommerce_archive_grid_column_spacing)) / 2);
}

.products-3 > li {
    width: 33.3333%;
}

.product {
    position: relative;
}

Step 3: Modify WooCommerce’s Default Column Setting (Optional)

If you’re building a theme, you might want to force WooCommerce to display three products per row. Add the following snippet to functions.php:

add_filter('loop_shop_columns', 'loop_columns', 999);
if (!function_exists('loop_columns')) {
    function loop_columns() {
        return 3; // 3 products per row
    }
}

Step 4: Use the Shortcode in Your Page or Post

You can now use the following shortcode to display products in a custom order followed by the rest of the category:

[custom_product_order ids="1067, 1058, 1121, 1400, 1136" category="category name" columns="3"]

How It Works:

  • The first five products (IDs: 1067, 1058, 1121, 1400, 1136) will appear first.
  • The remaining products from the “planter-boxes” category will be displayed after them.
  • The products will be arranged in 3 columns

Conclusion

With this simple function, you now have full control over the product display order while maintaining a clean, organized layout. This approach is especially useful for featured products, landing pages, or promotional sections in your WooCommerce store.

Have any questions? Feel free to ask in the comments below!