I m using the built-in query short codes to be able to display a visitor's most recently viewed products like this:

 <?=do_shortcode('[recent_products limit="4"]'); ?>

The issue I'm seeing, when you first get to the site you may have less then 4 results and grid doesn't look that great. I would much rather just hide the whole section all together.

I reviewed the documentation and couldn't think of a solution other them replicating the entire query as PHP. Any one have any ideas?

1 Answer 1


I don't think there is a native shortcode for recently viewed products but, again, there are two options here. One is to use the widget with a unique sidebar, wrapped in a condition, or you can create your own function/shortcode.

1. Conditional sidebar

Add the following code to your functions.php file. This will enable a new sidebar (widget area) and create a helper function for later use.


function register_custom_sidebar()
    // Register new sidebar
    register_sidebar( array(
        'name' => __( 'Custom Sidebar', 'stack-exchange' ),
        'id' => 'custom-sidebar',
        'description' => __( 'This sidebar is used only for recently view products.', 'stack-exchange' ),
        'before_widget' => '<section id="%1$s" class="widget %2$s">',
        'after_widget'  => '</section>',
        'before_title'  => '<h2 class="widget-title">',
        'after_title'   => '</h2>',
    ) );    
add_action( 'widgets_init', 'register_custom_sidebar' );

function get_recently_viewed_products_count()
    // Create helper function to check number of recently viewed products
    $viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] ) : array();  
    return count( $viewed_products );

In your template, use our new function to check whether there are enough recently viewed items. If there are, load the sidebar and widget.

You'll need to add the widget in the admin area by going to Appearance > Widgets and looking for the Recently Viewed Products widget. Drag this into your newly created sidebar (Custom Sidebar by example).

Template file

// Use our function to check count of viewed products
// If true (i.e. >= 4) load the sidebar/widget
if ( get_recently_viewed_products_count() >= 4 ) {
    dynamic_sidebar( 'custom-sidebar' );

2. Custom shortcode

Create a new function in your functions.php file as below. This is more or less an extension of /woocommerce/includes/widgets/class-wc-widget-recently-viewed.php


function recently_viewed_products_function( $atts )
    // Get viewed products
    $viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] ) : array();

    // Reverse array (order of view)
    $viewed_products = array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) );

    // If there are no $viewed_products return;
    if ( empty( $viewed_products ) ) {

    // Get limit, if not found set to 4
    ( isset( $atts['limit'] ) ? $limit = $atts['limit'] : $limit = 4 );

    // If number of $viewed_products is greater than or equal to $limit carry on
    if ( count( $viewed_products ) >= $limit ) {


        // Set query args using $limit and $viewed_products
        $query_args = array(
            'posts_per_page' => $limit,
            'no_found_rows'  => 1,
            'post_status'    => 'publish',
            'post_type'      => 'product',
            'post__in'       => $viewed_products,
            'orderby'        => 'post__in',

        $query = new WP_Query( $query_args );

        if ( $query->have_posts() ) :
            echo '<ul class="products">';

            while ( $query->have_posts() ) : $query->the_post();

                // Output product content
                // I've used the default as standard but you can do anything here
                wc_get_template_part( 'content', 'product' );


            echo '</ul>';


        $content = ob_get_clean();

        echo $content;

    } else {
add_shortcode( 'recently_viewed_products', 'recently_viewed_products_function' );

// This function is required to set the cookie for recently viewed products
// Thanks for @louis-w for the heads-up (https://github.com/woocommerce/woocommerce/issues/9724#issuecomment-160618200)
function custom_track_product_view() {
    if ( ! is_singular( 'product' ) ) {

    global $post;

    if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) )
        $viewed_products = array();
        $viewed_products = (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] );

    if ( ! in_array( $post->ID, $viewed_products ) ) {
        $viewed_products[] = $post->ID;

    if ( sizeof( $viewed_products ) > 15 ) {
        array_shift( $viewed_products );

    // Store for session only
    wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );

add_action( 'template_redirect', 'custom_track_product_view', 20 );

Echo the shortcode in your template and you're good to to.

Template file

<?= do_shortcode( '[recently_viewed_products limit="2"]' ); ?>
  • Thank you for such a well thought through solution. In reading what you have written I'm realizing I totally misunderstood [recent_products] though, I am trying to add a "Your Most Recently Viewed" feed. Too much late night computing I guess!
    – Louis W
    Dec 19, 2017 at 16:58
  • Haha, no worries, we've all been there. I've updated the question accordingly. Dec 20, 2017 at 10:25
  • Thanks again, very helpful. I'm going about with the "Custom shortcode" route as I don't use Widgets. I've added the code and nothing appears. Debugging $viewed_products always seems to return an empty array. Do I need to do something to add products to this or is that supposed to happen automatically?
    – Louis W
    Dec 20, 2017 at 16:38
  • $viewed_products should populate once you've viewed, and navigated away from, a product. If you have Google Chrome installed it's worth checking the Developer Tools. On the Application tab, you'll see a Cookie section (left-hand side, beneath the Storage heading). Search for woocommerce_recently_viewed and make sure it has a value saved. Dec 20, 2017 at 16:58
  • 1
    Looks like the cookie is set by the widget, so if using the "Custom Shortcode" route it looks like you need to add it yourself: github.com/woocommerce/woocommerce/issues/… I can add this to my PHP.
    – Louis W
    Dec 20, 2017 at 20:32

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.