WooCommerce: Recently Viewed Products (Shortcode)

Currently, you can use a widget or a block to have the user see the list of products they recently viewed.

But for now, let’s create our own shortcode… and let’s take advantage of the existing [products] shortcode and learn how we can “pass” product IDs to it without the need of reinventing the wheel.

This snippet teaches you how to store data in a custom cookie, and also how to output a core shortcode… inside a custom shortcode. Enjoy!

“Recently viewed” section after using my brand new [recently_viewed_products] WooCommerce shortcode

PHP Snippet: [recently_viewed_products] Shortcode

/**
 * @snippet       [recently_viewed_products] Shortcode - WooCommerce
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 8
 * @community     https://businessbloomer.com/club/
 */

add_action( 'template_redirect', 'bbloomer_track_product_view', 9999 );

function bbloomer_track_product_view() {
	if ( ! is_singular( 'product' ) ) return;
	global $post;
	if ( empty( $_COOKIE['bbloomer_recently_viewed'] ) ) {
		$viewed_products = array();
	} else {
		$viewed_products = wp_parse_id_list( (array) explode( '|', wp_unslash( $_COOKIE['bbloomer_recently_viewed'] ) ) );
	}
	$keys = array_flip( $viewed_products );
	if ( isset( $keys[ $post->ID ] ) ) {
		unset( $viewed_products[ $keys[ $post->ID ] ] );
	}
	$viewed_products[] = $post->ID;
	if ( count( $viewed_products ) > 15 ) {
		array_shift( $viewed_products );
	}
	wc_setcookie( 'bbloomer_recently_viewed', implode( '|', $viewed_products ) );
}

add_shortcode( 'recently_viewed_products', 'bbloomer_recently_viewed_shortcode' );
 
function bbloomer_recently_viewed_shortcode() {
	$viewed_products = ! empty( $_COOKIE['bbloomer_recently_viewed'] ) ? (array) explode( '|', wp_unslash( $_COOKIE['bbloomer_recently_viewed'] ) ) : array();
	$viewed_products = array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) );
	if ( empty( $viewed_products ) ) return;
	$title = '<h3>Recently Viewed Products</h3>';
	$product_ids = implode( ",", $viewed_products );
	return $title . do_shortcode("[products ids='$product_ids']");
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

  • WooCommerce: Display All Products Purchased by User
    When a WooCommerce customer is logged in, you might want to show them the list of previously purchased products (maybe in a custom “My Account” tab). This is helpful when customers tend to buy the same products over and over again, and therefore you can help them “order again” without having them to search the […]
  • WooCommerce: Display Out of Stock Products (Shortcode)
    A client of mine wanted to show out of stock products on a separate page – so I coded a simple shortcode for you all! You can use this shortcode for different goals. For example, you might want to display what products you’ve sold to enhance customer trust / social proof. So let’s see (1) […]
  • WooCommerce: Exclude Category from ‘product_categories’ Shortcode
    Sometimes solutions are very simple, and you don’t need rocket science to fix your issue! A client of mine needed to hide a category from the Product Categories Shortcode ( BloomerArmada (1) WooCommerce Mini-Plugins (27) ); in fact, there is no parameter that allows you to “exclude” a given product category such as “uncategorized” or […]
  • WooCommerce: Display Product Reviews @ Custom Page (Shortcode)
    WooCommerce product reviews shows by default in the “Reviews” tab in the single product page. But what if, like me, you’re using custom sales pages and need to show such reviews elsewhere – by using a shortcode? I’ve spent some time doing this for two Business Bloomer pages, the contact page (beside the request a […]
  • WooCommerce: Exclude Category from ‘products’ Shortcode
    The WooCommerce Business Bloomer ClubRated 5.00 out of 5 $9.00 – $599.00 /once Whether you’re only starting with WooCommerce or you’re an experienced WordPress developer, we’ve got you covered. Enjoy day-to-day WooCommerce support, attend a Woo masterclass, view the member directory… joining the Club is really a no-brainer. Share your feedback View Plugin WooCommerce Toggle […]

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

59 thoughts on “WooCommerce: Recently Viewed Products (Shortcode)

  1. Hello dear Rodolfo! Thank you very much for this awesome piece of code!

    I would love it if it worked as well for cached products and had its own class. Still awesome for cases in which my claims are not requested.

    Best regards

  2. hi, it doesnt work anymore. adding it to snippet

    1. You’re right! Snippet updated

  3. hi how i use it?
    i just add code to function.php file.

    1. Hi Amin, you also need to place the related shortcode somewhere in your website – let me know

  4. hello,
    thank you for the nice code, i have implemented it into my website and it works nicely
    but the most recently viewed products seem to not be shown but only the oldest recently viewed products. and since i have limited the dislay to 5, i always see “old” products. is there a way to fix this?
    thanks
    maria

    1. add_shortcode( 'recently_viewed_products', 'bbloomer_recently_viewed_shortcode' );
       
      function bbloomer_recently_viewed_shortcode() {
       
         $viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', wp_unslash( $_COOKIE['woocommerce_recently_viewed'] ) ) : array();
         $viewed_products = array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) );
       
         if ( empty( $viewed_products ) ) return;
          
         $title = '<h6>Du hast dir zuletzt angesehen</h6><br>';
         $product_ids = implode( ",", $viewed_products );
       
         return $title . do_shortcode("[products ids='$product_ids' limit='5' columns='5' orderby='woocommerce_recently_viewed' order='asc' ]");
         
      }
      
      
      1. Try remove the “array_reverse(” call and the final “)” on that same line once you do that. Let me know

  5. For people who can’t filter the number of products displayed. You have to insert the restrictions in the function.php and not in the shortcode.
    Change for example the last line of the code given at the top of the page by :

    return $title . do_shortcode("[products ids='$product_ids' limit='4' columns='4' orderby='post__in' class='recentes-vues']");

    And to make it work, I personally had to add the code given in karolina’s comment.

    Here, good luck

  6. I just tried it on one of my stores, and didn’t worked as expected. It displayed all the products in the store, and wasn’t able to set a cookie either.
    Hopefully, someone will be able to suggest a work around? and if somehow it can be fixed to set the number of columns, that will be great!
    Thanks

    1. Hi Tanveer, that’s weird. Can you try with a different theme and no other plugins than Woo?

  7. Hi

    I needed to remove one of the double square brackets? (I’m not native english) in the return function.
    return $title . do_shortcode(“[[products ids='$product_ids']]“);
    ->

    return $title . do_shortcode("[products ids='$product_ids']");

    But really thanks for this code! (and other snippets! very usefull!)

    Kind regards

    1. Thanks! Fixing that now

  8. Hi,

    Thank you for putting this code free on this website. I am currently using it and am happy with its effect.
    There is just 1 thing I would like to know, or like to add: it would be really great if there was an “else” statement with a fallback shortcode to display when somebody hasn’t viewed any products yet.
    With the code as it is, it will display an empty field when a new visitor comes to the site. Maybe you could make it fallback to orderby=”popularity” with beste_selling=”true” for example?

    I don’t have the PHP knowledge to do this myself.

    1. Hello Vinnie, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  9. Hi,

    This code used to work on my site but all of a sudden not anymore. Is anyone experieing the same thing?

    Just updated to woocommerce 4.8.0

    Thanks.

      1. I find it strange. If you rollback to a previous version of WooCommerce does that work?

  10. How do you change the order of the products to be by the order they were viewed?
    So the last viewed product (excluding currently viewed product) is the first on the list.

    1. Is the current sorting the opposite i.e. last viewed is last?

      1. for me the order is kind of random.

        is where a way to limit the shown products to 5?
        How kann i change the display grid for the products from 3 to 5?

        Thank you for the help

  11. I did so [recently_viewed_products limit = “4” columns = “3”] but it didn’t work properly. what should I do. Thank you

    1. Hello Viet, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

      1. This tutorial feels incomplete with no clear way for a non coder to display the amount of products desired.
        Without being able to control the amount of items the code can not be of any real use.

        You are sending everyone to the WordPress codex that talks about short codes but the answer is not there.

        I am pretty sure a lot of people including myself tired: [recently_viewed_products limit = “4” columns = “3”] .

        Consider updating your tutorial so that it is friendly to us who are new to coding.

        1. No tutorial is incomplete 🙂 I do my best

  12. hey, its working but it just showing the product ID , not showing the product image

    1. Disable all plugins but Woo and try again please

  13. $product_ids = implode( “,”, $viewed_products= array_slice($viewed_products, 0, 4) );

    This show the latest item, how to do display view item from left to right?

    1. Hi Allan, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  14. hello,

    Can you tell me how to display the recently viewed products on a single page as Amazon is doing ?

    It seems better to have only 1 page than a widget, and exclude this page from cache.

    Thank you.

    1. Hi, can you use my shortcode on that page?

  15. Great snippet! I tried to limit the number of products to 4, but I didn’t succeed.
    Can anyone help me?

    Thanks!

    1. You should study this and change the “return” part of the snippet accordingly: https://docs.woocommerce.com/document/woocommerce-shortcodes/#section-6

  16. Hi,
    i have added your code, but when i see my website and without viewing any products today the history tab will be blank, that means when i visit some products yesterday , they will not showup in history tab, only the today’s viewed products is seen, otherwise the page getting blank . please help me as soon as possible.

    1. WooCommerce sets a cookie, so if your browser clears cookies or such cookie lasts for only 24 hours, there is no solution to your problem. Sorry

  17. You should add `orderby=’post__in’` to the shortcode attributes, otherwise it will sort posts by title. There is an `array_reverse` used in code but it’s pointless without this attribute

    1. Ah nice, good to know Nick! Thank you

  18. You are just awesome!
    Thank you so much for this website…helped me out so many times! 🙂

    1. Great!

  19. Hi Rodolfo :), great snippet!

    I’ve discovered that the “woocommerce_recently_viewed” cookie is stored only when the Recently viewed products widget is in use. If you want to use your code without the widget, you need to track the viewed products by your own: https://github.com/woocommerce/woocommerce/issues/9724 So you might add a note about it to the post 😉

    Cheers from Prague!
    Karolína

    1. Ahoy Karolina! Thanks so much for this, I will add it in the notes 🙂

  20. Hi there,

    I just added the code to my child functions.php file. But in several browsers the recently viewed product does not show up.
    I added the shortcode into the html of my homepage to make them visible over there. But not showing.

    What am I doing wrong?

    Thank you in advance.

    1. Hi Steff, maybe you have cookies disabled?

  21. Hello, Rodolfo
    I added the code in funcions.php and it is working, but I would like to control the quantity of products displayed and limit the 1 line, since it is showing all products recently viewed and this is loading the page a lot. In case I added it to the cart page! how to control the boundaries of displayed products and limiting the display to only 01 line on desktop and Mobile (with arrows for side drag) ?? thank you

    1. Hi Joao, just add parameters to the returned shortcode: https://docs.woocommerce.com/document/woocommerce-shortcodes/#section-8

  22. Thanks for the code. When I echo the [recently_viewed_products] shortcode it orders the products by name in ASC. Is this normal behaviour? When I var_dump $product_ids the order is ok, but $product_ids are used in [products ids='$product_ids'] shortcode, the order changes to product name. Is there any solution for ordering by view?

    1. Not perfect solution, but I have limited the number of products in the $viewed_products array.
      $viewed_products = array_slice($viewed_products, 0, 5);
      Now the [recently_viewed_products] shortcode displays the latest 5 recently viewed products. Order is not correct but now it shows the latest 5 products.

      1. Cool!

      2. Thanks Karesz and Rodolfo, I have add Karesz line:
        “$viewed_products = array_slice($viewed_products, 0, 5);” and it have limit viewed product to 5, but I don’t know how to adjust the amount of product per line. Can you provide a code to adjust that? Thanks!

  23. How can I display only image of “Recently Viewed Products”, without Titles and Prices?

    1. Hello Valentine, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  24. Thanks for the code. The shortcode only works for me when I have the WooCommerce recently viewed widget active on a sidebar somewhere in my site. Otherwise it seems the cookie doesn’t get created. Is this normal behaviour?
    Thanks

    1. Hi Nick. By looking at the function wc_track_product_view(), this triggers on the single product page OR if the widget is active, so it should work no matter what. Let me know

  25. how do i put it on widget sidebar ?

    1. Hello Arie, in the sidebar you can actually use the WooCommerce “Recently Viewed” widget

  26. I am using Widgets to show Recent Viewed Product on right side on the shop page.

    1. Cool! This, instead, is a shortcode than can be used on a page/post too

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

Your email address will not be published. Required fields are marked *