Sort And Display All Products By Most Viewed In WooCommerce

Inspired by the thread Sort Woocommerce products by most viewed using Post View Counter, here is my code below, that changes the product sorting option to show products most viewed products:

 * Setting post count on each visit
add_action( 'woocommerce_before_single_product', 'prefix_save_product_views' );
function prefix_save_product_views(  ) {

    $product_id = get_the_ID();
    $increment = 1;
    $current_visit_count = get_post_meta( $product_id, 'product_visit_count', true );

    $total_visit_count = (int)$current_visit_count + $increment;
    update_post_meta( $product_id, 'product_visit_count', $total_visit_count );


 * Change the display order based on visit count only in Catalog
add_filter('woocommerce_get_catalog_ordering_args', 'prefix_woocommerce_catalog_orderby');
function prefix_woocommerce_catalog_orderby( $args ) {
    $args['meta_key'] = 'product_visit_count';
    $args['orderby'] = 'meta_value_num';
    $args['order'] = 'desc';
    return $args;

However it does not show all other products which do not have any page views yet.

Is there a way to prioritize sorting by page views and at the same time, after, to show other products (that haven't page views yet) as well.

Any idea please?



For that all other products (not viewed yet) should need to have product_visit_countmeta key with a meta value of 0.

You can do that by adding this simple function, that you will run once (always make a database backup):

// Function that set "product_visit_count" metakey with a zero value on non visited products
function set_zero_product_visit_count_on_not_visited_products() {
    // Only for admin user role
    if( ! current_user_can('edit_products')) return;

    // Get all products that doesn't have "product_visit_count" as metakey (not visited)
    $product_ids = wc_get_products( array(
        'limit'         => -1,
        'return'        => 'ids',
        'meta_key'      => 'product_visit_count',
        'meta_compare'  => 'NOT EXISTS',
    ) );
    // Loop through product ids
    foreach( $product_ids as $product_id ) {
        // Add 'product_visit_count' meta key with a value of 0 (zero)
        update_post_meta( $product_id, 'product_visit_count', 0 );

// Triggers the function

Code goes in functions.php file of your active child theme (or active theme).

Once saved, as an administrator user role, browse any page of your web site, this execute the function. Now you can remove it(delete it). Tested and works.

Now for your new upcoming products, when you will add a new product, the following script will add product_visit_countmeta key with a meta value of 0:

add_action( 'woocommerce_admin_process_product_object', 'init_product_visit_count_on_new_prodct' );
function init_product_visit_count_on_new_prodct( $product ) {
    // Get 'product_visit_count' meta value
    $meta_value = $product->get_meta( 'product_visit_count' );
    // If meta value doesn't exist
    if ( empty($meta_value) ) {
        // Set the 'product_visit_count' to zero
        $product->update_meta_data( 'product_visit_count', 0 );

Code goes in functions.php file of your active child theme (or active theme). It should work.