How to Add Products Per Page Dropdown to Woocommerce

Posted by & filed under Tutorials, Web Design Tutorials.

This is going to be a very quick tutorial that will show you how to add the ability to Woocommerce for users to select the amount of products shown per page.

We will be using the built in Woocommerce hooks and filters and set a cookie via php so the browser can remember the selection across the website. We will be trying to add this into a plugin in the near future but until that time, follow along and edit as you see fit.
Major thanks to bcworkz for his help with setting the cookies and just being awesome!

so here we go, in your themes functions.php file let’s add the following little snippet:

// Lets create the function to house our form
remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );

function woocommerce_catalog_page_ordering() {
?>
<?php echo '<span class="itemsorder">Items Per Page:' ?>
    <form action="" method="POST" name="results" class="woocommerce-ordering">
    <select name="woocommerce-sort-by-columns" id="woocommerce-sort-by-columns" class="sortby" onchange="this.form.submit()">
<?php
 
//Get products on page reload
if  (isset($_POST['woocommerce-sort-by-columns']) && (($_COOKIE['shop_pageResults'] <> $_POST['woocommerce-sort-by-columns']))) {
        $numberOfProductsPerPage = $_POST['woocommerce-sort-by-columns'];
          } else {
        $numberOfProductsPerPage = $_COOKIE['shop_pageResults'];
          }
 
//  This is where you can change the amounts per page that the user will use  feel free to change the numbers and text as you want, in my case we had 4 products per row so I chose to have multiples of four for the user to select.
			$shopCatalog_orderby = apply_filters('woocommerce_sortby_page', array(
			//Add as many of these as you like, -1 shows all products per page
			  //  ''       => __('Results per page', 'woocommerce'),
				'20' 		=> __('20', 'woocommerce'),
				'-1' 		=> __('All', 'woocommerce'),
			));

		foreach ( $shopCatalog_orderby as $sort_id => $sort_name )
			echo '<option value="' . $sort_id . '" ' . selected( $numberOfProductsPerPage, $sort_id, true ) . ' >' . $sort_name . '</option>';
?>
</select>
</form>

<?php echo ' </span>' ?>
<?php
}
 
// now we set our cookie if we need to
function dl_sort_by_page($count) {
  if (isset($_COOKIE['shop_pageResults'])) { // if normal page load with cookie
     $count = $_COOKIE['shop_pageResults'];
  }
  if (isset($_POST['woocommerce-sort-by-columns'])) { //if form submitted
    setcookie('shop_pageResults', $_POST['woocommerce-sort-by-columns'], time()+1209600, '/', 'www.your-domain-goes-here.com', false); //this will fail if any part of page has been output- hope this works!
    $count = $_POST['woocommerce-sort-by-columns'];
  }
  // else normal page load and no cookie
  return $count;
}
 
add_filter('loop_shop_per_page','dl_sort_by_page');
add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_page_ordering', 20 );

 

I tried to keep it well documented so if you have any questions feel free to let me know and I can make the edits as they come. I hope this helps, Because I wanted this located next to the “Sort by” dropdown I used the “before_shop_loop” action then styled it in place via css. You can always change this depending on your needs by just changing that hook.

Like this? Share it with your friends!
Facebook Twitter Linkedin Email

68 Responses to “How to Add Products Per Page Dropdown to Woocommerce”

  1. James

    Great piece of code. this was very helpful. Thanks.

    Is there a way for the drop down to display the current selection amount. meaning if i changed it to display 36 per page and it reloads the page to display that amount, can the drop down now show 36 as the “current” selection instead of showing the first/base number?

    Thanks

    Reply
    • Derek Schmidt

      Hey James, Yes there is definitely a way, it would be very similar to the way Woocommerce does it in their ‘sort-by’ select. I thought I had already implemented that in there but if you want to double check, look in your woocommerce files -> templates and in one of those folders is the sorting.php file. Going off memory here but if you open that up you will see how Woo did it with their drop-down. I know the code above is setup for that but there must be a small error in there somewhere or within setting the cookie and that is why their choice is not present in the dropdown when the screen reloads. As soon as I get some free time I will put Woo back on local host and get that worked out but I do not have any active installs with Woocommerce still on them. I will trouble shoot and let you know and likewise if you get this resolved before me. Many thanks!

      Reply
      • James

        Hi Derek,

        Did you ever get a chance to look at having the dropdown display the currently selected option instead of the first option?

        I have looked at the sorting.php and it looks very close to your code and I did not see any particular difference that would indicate what is having it display the current selection. perhaps it is just not working on my site. if so how would I find out why?

        Thanks again!

        Reply
        • Derek Schmidt

          You can try it with javascript, something similar to the below

          var select_id = document.getElementById("woocommerce-sort-by-columns");
          
          select_id.options[select_id.selectedIndex].value;
          < \pre>
          
          Hope this helps
          Reply
  2. Marcel

    Hi Thanks for this code. I am also curious of the solution to show the current selected number. In my case it does not store the cookie value som somehow it resets to the default 10 all the time with page switches. Do you have a hin were to find this issue?

    Reply
    • Derek Schmidt

      Other users have reported this issue and it has typically been a theme or plugin conflict. Try switching to the default twenty twelve and see if that fixex it, if not then try deactivating all plugins and enable one at a time until you find the problem. If you find the conflicting theme/plugin then post here so we can work on resolving it.

      Reply
  3. Marcel

    Have done some debugging and found that the cookie simply did not store… then I saw the ‘your-web-address.com’, replaced it with mine….

    and it worked like a charm… Now the only wish is to get the default value in… I’ll check if I can find a solution for that.

    Reply
  4. Marcel

    Found the issue… don’t know if it is the best solution but it works for me.. Have added checks for my new display_count vars and used this one to match the selected value. Defaulted to 24 and took out the blank one. Works perfect for me. Hope it helps you. Had to add the post check because the session var was one lap behind the real value.

    Thanks for your effort and sharing…!

    // Lets create the function to house our form
    function woocommerce_catalog_page_ordering() {
    ?>

    __(’24 per pagina’, ‘woocommerce’),
    ’48′ => __(’48 per pagina’, ‘woocommerce’),
    ‘-1′ => __(‘Alles tonen’, ‘woocommerce’),
    ));

    foreach ( $shopCatalog_orderby as $sort_id => $sort_name )
    echo ” . $sort_name . ”;
    ?>

    <?php
    ….. rest of code is still the same

    Reply
  5. luke

    Thanks for this it is great, except it is messing up my pagination. When I select next page, or page 2 etc.. I get a 404 error…

    Any ideas what is happening there?

    Luke

    Reply
  6. Zach

    Hey guy’s this code works great. I have the same issues as everyone else when it resets back to 10 items i would like the default to be 12. Would be great to see this working 100% the smallest things seem to be the biggest headaches in wordpress lol. Other then that the plugin/hack is pretty nice and does do the job. I did change the web addy and tried to add the folder url also. But that did nothing still does not work. All I really need is for it to show 12 items and not 10.

    Reply
  7. Derek Schmidt

    Hey Zach, try adding this to your themes functions.php file:

    // change default number of products per page
    add_filter( 'loop_shop_per_page', create_function( '$cols', 'return 12;' ), 20 );

    Reply
  8. Zach

    I did that but the dropdown stops working. It will show 12 items but it will not let me change to 20 or 30 if i wanted.

    Reply
  9. Zach

    yes the plugin works cookies work find. but if you clear your cookies or start on a new browser default still shows 10. i was wondering how i can get that to show 12 and still have it so the dropdown works.

    Reply
  10. Zach

    You can delete my previous comment above this. I figured out how to allways display 12 items in your store. The default is set to 10 so what you should do is go into your admin dashboard. Locate settings,reading and change posts and items to 12 or whatever default number you may want. This has saved me and this plugin works great! No need to add the default woocommerce one this one works like a charm and without that annoying code they provided us lol.

    Reply
    • Derek Schmidt

      Wow, lol I have been pecking away at it this morning trying to over complicate things and sometimes it is the most simplest solution that ends up working out. Thanks for sharing Zach, take care!

      Reply
  11. Zach

    Same Derek i over think on coding and bam its all ways the simplest thing all ready coded for you. But those cookies you figured out work like a charm for when people select certain numbers. Thats one bad thing with me in coding i think it has to be hard then turns out it’s a 1,2 punch type of deal lol.

    Reply
  12. Adrian

    Hey guys!
    First of all, Derek, thank you so much for this awesome tweak!

    Second, I would like to share my workaround/hack for the number of products/page select value resetting every time the page refreshes.

    So, at first, I tried passing the $_COOKIE['shop_pageResults'] var via javaScript and forcing the select to keep the cookie value.

    The issue here was that, by sending the value using $_POST, the $_COOKIE['shop_pageResults'] was always updating one step behind.

    So, I added some if/then/else magic inside your woocommerce_catalog_page_ordering function like so:

    if (isset($_POST['woocommerce-sort-by-columns']) && (($_COOKIE['shop_pageResults'] $_POST['woocommerce-sort-by-columns']))) {
    $currentProductsPerPage = $_POST['woocommerce-sort-by-columns'];
    } else {
    $currentProductsPerPage = $_COOKIE['shop_pageResults'];
    }

    Then I forced the value of $currentProductsPerPage into the select option via javascript.

    Of course, you can customize this to your own needs, but basically this does the trick.

    Happy coding!

    Reply
    • Chris

      Adrian,

      Thanks for the hint on how to make this work. I get a parse error in the first line of your code:

      if (isset($_POST['woocommerce-sort-by-columns']) && ($_COOKIE['shop_pageResults']
      $_POST['woocommerce-sort-by-columns']))) {

      which makes it fail.

      Also, if you dont mind me asking? What was the javascript you used to change the selected state?

      Thanks!

      Reply
      • Derek Schmidt

        Hey Chris, the JS should be in the line of code from above.. The reason you are getting the parse error is because there is nothing separating the $_COOKIE and the $_POST.. Try adding the & in between like so:
        if (isset ($_POST['woocommerce-sort-by-columns']) && (($_COOKIE['shop_pageResults'] & $_POST['woocommerce-sort-by-columns']))) {
        $currentProductsPerPage = $_POST['woocommerce-sort-by-columns'];
        } else {
        $currentProductsPerPage = $_COOKIE['shop_pageResults'];
        }

        You just need to add Adrians snippet to the function woocommerce_catalog_page_ordering().. Probably before the closing bracket that closes the function.

        Reply
        • Adrian

          Thanks a lot, Derek, you’re right! That’s the issue because probably the comment area of your website probably doesn’t process “greater than” and “lower than” characters put together.

          The main if statement should look like this:

          if (isset($_POST['woocommerce-sort-by-columns']) && (($_COOKIE['shop_pageResults'] [] $_POST['woocommerce-sort-by-columns']))) {

          Without the brakets around the gt and lt chars. Basically you wanna test if you’re on the first page refresh after applying a product per page number.

          If the $_POST is set and $_POST is not equal to what you have stored in the $_COOKIE, then echo $_POST, else echo $_COOKIE.

          Also, Chris, I used jQuery’s .attr method to force the select:

          $(‘select.sortby>option:eq(1)’).attr(‘selected’, true);

          Here’s the reference:
          http://api.jquery.com/attr/

          And you can find a working example over here:
          http://jsfiddle.net/gaby/CWvwn/

          Have fun!

          Reply
  13. Chris

    Thanks Derek! That works.. !

    Odd though, I dont see the JS in that post from Adrian.. Wonder if it is being filtered?

    Reply
  14. andres

    There is an easiest way to fix the number of products per page…. change the number of posts in blog… settings –> Reading (sorry im spanish, not sure if that is what it says on english wordpress) and that is it

    Reply
    • Derek Schmidt

      thx andres, this is aimed towards having the front end user select the amount of product they want displayed per page, but your answer works for changing the default number of products per page.

      Reply
  15. daniel

    Hi, this is just what iv been looking for but i cant get it working!
    iv added your code to functions.php and changed the website to mine but still nothing?

    do you have any idea why this might be ?

    http://www.onestopdive.com/shop/

    could really do with some help thanks…

    Reply
  16. James Kember

    Thanks guys, awesome work around. Why this isnt already a plugin is beyond me. Can anyone tell me how instead of 24, 35, 48 etc, I can just have 20, 40, 60 and the most importantly ‘show all’ and it actually returns all my products?

    Reply
    • Derek Schmidt

      You should just be able to change the numbers from 24, 35, 48, .. to 20, 40, 60, 80, …

      There should not be anything else you have to do. Let me know if it works.

      Reply
  17. James Kember

    Thanks Derek, but how do i actually have the text saying ‘show all’ rather than putting in a high number. For example if have 140 products in total I don’t want to put 80 in as it won’t show them all. If I put in 140 sure it will show them all but i don’t want to have to keep adjusting that everytime I add a product. Hope the makes sense.

    Reply
    • Derek Schmidt

      Should be something like this I believe:

      apply_filters('woocommerce_sortby_page', array(
      			    ''       => __('Results per page', 'woocommerce'),
      				'20' 	=> __('20 per page', 'woocommerce'),
      				'40' 		=> __('40 per page', 'woocommerce'),
      				'60' 		=> __('60 per page', 'woocommerce'),
      				'-1' 		=> __('Show All', 'woocommerce'),
      			));
      
      Reply
    • Derek Schmidt

      Sure, assuming this is still for woocommerce shop you can just put this anywhere you want it to display:

      < ?php woocommerce_catalog_page_ordering() ?>
      
      Reply
  18. Scott Weiss

    Derek, I ran into an issue. Let’s say you have 49 results, and each page has 12 results, and you’re on the last page (page 5). So you’re viewing the 49th result. Then you select show all (or show 64). It doesn’t bring you back to the first page. It stays on page 5 and shows page not found. Is there a way to make it go back to the first page or previous page that has results?

    Reply
    • Derek Schmidt

      I dont have anywhere to test this with Woocommerce isntalled at the moment but you can try something like this:

      // now we set our cookie if we need to
      function dl_sort_by_page($count) {
        if (isset($_COOKIE['shop_pageResults'])) { // if normal page load with cookie
           $count = $_COOKIE['shop_pageResults'];
        }
        if (isset($_POST['woocommerce-sort-by-columns'])) { //if form submitted
        	$shop_page_url = get_permalink( woocommerce_get_page_id( 'shop' ) );
          setcookie('shop_pageResults', $_POST['woocommerce-sort-by-columns'], time()+1209600, '/', $shop_page_url, false); //this will fail if any part of page has been output- hope this works!
          $count = $_POST['woocommerce-sort-by-columns'];
        }
        // else normal page load and no cookie
        return $count;
      }
      

      Note the $shop_page_url variable we defined in the function that handles the cookies. Make sure the above replaces the similar code in the markup. If that doesnt work 100% possible try the wp_redirect within that function.

      Good luck

      Reply
      • Scott Weiss

        Well, the shop page wasn’t the issue that would solve it, and in fact in order for the cookie to be set properly the shop page url needs to just be the domain name (like originally) which i was dynamically able to get by using $domain_name = preg_replace(‘/^www\./’,”,$_SERVER['SERVER_NAME']);

        But this still leads me to that redirect after the count is set. I just don’t think it will work, and i’m not an expert in this, but i’ll get some help and see what i can do. I’ll let you know.

        Reply
  19. Dave

    This doesn’t work for me :( Select the drop down and nothing happens, still showing “Showing 1-12 of 200 results”

    Reply
  20. gayatri

    Hi, Derek i have read comments & try to solve issue but not get result what i have issues is it takes value 10 from “the default Blog pages show at most” & “posts Syndication feeds show the most recent” i have changed the it’s value but it takes the value of wordpress blog post set valued not our drop down selected value . please help me to solve this issue .

    site url : http://elementalwebdesign.co.uk/clients/thornhill-galleries/product-category/marble-fireplaces/

    Reply
  21. Peej

    So I had success with this snippet on my default theme, but once I switch on my custom theme (its called Salient), the dropdown menu does not reload the page with the appropriate number of items. I just get the default 12. Any ideas?

    Reply
    • Derek Schmidt

      Hmm, do you have cookies and JS enabled on your browser? Have you changed the url in the snippet to be the new url you are loading it too? Have you checked your developer console for any other javascript conflicts? If yes then you may have a JS conflict which is preventing the rest of the JS on the page to load. I personally use Firebug to debug.

      Reply
      • Peej

        Hi Derek, thanks for your reply. I confirmed all the things you mentioned and agree that it is a js conflict. I’m recommending to check the console errors between the two themes and further, the js versions between the two. If you have any other ideas, please feel free to reply. Otherwise, I will report back with my findings. Thanks!

        Reply
  22. daniel

    can not seem to get the select to show what you have selected on reload always defaults to the first one even tho the page is showing “all”

    any idea ?

    Reply
  23. Annie

    Hi and thanks for this code! However things dont go as they should?
    Standard it shows 12 items, and as long as you keep that and hit next everytime it works fine, also just selecting show all works fine too.

    However, as soon as you select lets say 8 then on the bottom select next, it resets every time to 12 again. I suppose it should keep showing 8 even after hitting next.

    But where it really messes up is if at first it shows 8, then after hitting next its adds 12 again, if you hit/select 8 per page again, it messes the count up. If it was at 12 items and you select then lets say 32 the next page it skips from 13 to 33, so it does not show numbers 13 to 32 all of the sudden it starts showing 33 to 64.

    So it is all messed up and misguides clients for they dont see/skip a lot of products this way.

    Reply
  24. Annie

    I used this code by the way:

    // User selects how many products to view per page

    // via http://designloud.com/how-to-add-products-per-page-dropdown-to-woocommerce/

    function woocommerce_catalog_page_ordering() {

    ?>

    __(‘Producten per pagina’, ‘woocommerce’),

    ’8′ => __(’8 per pagina’, ‘woocommerce’),

    ’16′ => __(’16 per pagina’, ‘woocommerce’),

    ’32′ => __(’32 per pagina’, ‘woocommerce’),

    ‘-1′ => __(‘Alle producten’, ‘woocommerce’),

    ));

    foreach ( $shopCatalog_orderby as $sort_id => $sort_name )

    echo ” . $sort_name . ”;

    ?>

    <?php // Adrian's code

    if (isset($_POST['woocommerce-sort-by-columns']) && (($_COOKIE['shop_pageResults'] $_POST['woocommerce-sort-by-columns']))) {

    $currentProductsPerPage = $_POST['woocommerce-sort-by-columns'];

    } else {

    $currentProductsPerPage = $_COOKIE['shop_pageResults'];

    }

    ?>

    jQuery(‘select.sortby>option[value=""]‘).attr(‘selected’, true);

    <?php

    }

    // now we set our cookie if we need to

    function dl_sort_by_page($count) {

    if (isset($_COOKIE['shop_pageResults'])) { // if normal page load with cookie

    $count = $_COOKIE['shop_pageResults'];

    }

    if (isset($_POST['woocommerce-sort-by-columns'])) { //if form submitted

    setcookie('shop_pageResults', $_POST['woocommerce-sort-by-columns'], time()+1209600, '/', 'annadee.nl/', false); //this will fail if any part of page has been output- hope this works!

    $count = $_POST['woocommerce-sort-by-columns'];

    }

    // else normal page load and no cookie

    return $count;

    }

    add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_page_ordering', 20 );

    add_filter('loop_shop_per_page','dl_sort_by_page');

    Reply
    • Derek Schmidt

      Hey Annie, did you get your issue resolved? Maybe I can package this into a plugin soon — just been super busy lately which is why I am a bit late approving and replying to my comments ;-)

      Reply
      • Annie

        Hi Derek,

        Thx for your reaction, I did not get a notification so just found it by accident!

        No, it is not resolved, I use the code, see link above in test site please, but it does not work properly. As soon as I click on next it messes up the count.

        I know a lot of people would like this as a plugin, because in large shop, this is a must have.

        If you could develop a plugin, I am pretty sure lots of users would like to pay for this option if it is per license and affordable.

        It would mean a lot to me if you would concider developing this in the near future. Do you think you might want to take time to do this?

        Thx,
        Annie

        Reply

Leave a Reply