Sort by stock, push out of stock to bottom of list :: Feature Request (and custom code)

Sort by stock, push out of stock to bottom of list :: Feature Request (and custom code)

cfc_webmaster
Explorer
47 0 118

Problem:

We want all out of stock items to show, but we want them at the bottom of every list for collection, search, tag and front end output. There is no default {{ collection.sort_by == "stock" }} option available within Shopify

 

Solution:

I wrote the code below.

I was extremely dissatisfied with all of the apps/plugins that "claim" to do this.

 

CODE SAMPLES:

In order to pull this off several sections of the template needed to be modified. For purposes of simplicity I will demonstrate with only the STATIC COLLECTION LIQUID template as it is most likely to commonly occur in most themes.

 

TEMPLATE: /sections/static-collection.liquid

Default code expected to be something like this: The standard "render my collection"

 

{% for product in collection.products %}
{% render 'product-grid-item', product: product %}
{% endfor %}

 

 

IDEAL 'NON EXISTENT' CUSTOMIZATION THEORY: 

Lets say we simply want our "out of stock" items to be at the bottom of the list.

We could try to accomplish this by SORTING the array as follows, but it does not work!

[correct me if I am wrong about this]

 

{% assign products = collection.products | sort: 'inventory_quantity' %}
{% for product in products %}
   {% render 'product-grid-item', product: product %}
{% endfor %}

 

This is because inventory is stored here and its not a choice for | sort:

*see: https://shopify.dev/api/liquid/filters#sort 

{{ product.selected_or_first_available_variant.inventory_quantity }}

 

WORKING CUSTOMIZATION EXAMPLE: 

Here is then a working example

the idea being to CAPTURE the low stock items and push them to the bottom of a list

 

  {% for product in collection.products %}
                  {% assign quantity = product.selected_or_first_available_variant.inventory_quantity %}
          
                  {% if quantity > 0 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_over_one = capture_over_one | append: captured_temp %}
                  {% endif %}
          
                  {% if quantity == 0 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_nostock = capture_nostock | append: captured_temp %}
                  {% endif %}

            {% endfor %}


          {{ capture_over_one }} 
          {{ capture_nostock }}

In this case we have simply captured anything with 1+ stock into the natural order, and then captured the out of stock items, and at the end we just dump out the capture.

 

 

BUT WAIT THERE IS MORE! 

Here is then a working example with more elaborate needs

Consider how we may want to see if the customer has CONTROLLED the sort

And if the customer wants to sort by Price, Title, or some filter, we needs to get creative

Lets also assume we want to push any inventory that's 1 (just 1 left), or "low stock" to the top to try to sell it out, we can do all this and more with the following methodology and creative thinking

 

 

        {% assign sort_active = false %}
        {% if collection.sort_by != blank %} {% assign sort_active = true %} {% endif %}
        {% if collection.sort_by == "manual" %} {% assign sort_active = false %} {% endif %}

           {% assign capture_default = "" %}
           {% assign capture_over_ten = "" %}
           {% assign capture_over_two = "" %}
           {% assign capture_only_one = "" %}
           {% assign capture_nostock = "" %}
           {% assign captured_temp = "" %}
        
            {% for product in collection.products %}

                    {% capture captured_customer_sort %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_default = capture_default | append: captured_customer_sort %}

                  {% assign quantity = product.selected_or_first_available_variant.inventory_quantity %}
          
                  {% if quantity > 9 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_over_ten = capture_over_ten | append: captured_temp %}
                  {% endif %}
          
                  {% if quantity > 1 and quantity < 10 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_over_two = capture_over_two | append: captured_temp %}
                  {% endif %}

          
                  {% if quantity == 1 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_only_one = capture_only_one | append: captured_temp %}
                  {% endif %}

          
                  {% if quantity < 1 %}
                    {% capture captured_temp %}
                    {% render 'product-grid-item', product: product %}
                    {% endcapture %}
                    {% assign capture_nostock = capture_nostock | append: captured_temp %}
                  {% endif %}

              
            {% endfor %}

        
        {% if sort_active == true %}
          {{ capture_default }} 
        {% else %} 
{{ capture_only_one }}
{{ capture_over_two }} {{ capture_over_ten }} {{ capture_nostock }} {% endif %}

Key notes here:

 

  • First, lets detect if collection.sort_by has been set, if so, then do not push down low stock items, the customer may want to know this immediately with their "sort by price" choice
  • Then, lets loop over the products and capture them into some brackets, in this case I want products that have only 1 left at the top, followed by 2-9 in stock, followed by 10+
  • The idea being I want to SELL OUT the low stock first...
  • From here, one can customize and control their brackets as needed

Closing thoughts:

This is but only the static-collection.liquid page, I needed to then customize several other modules and get rather creative with this tactic to achieve very unique and subjective results that would not apply to most peoples stores. I therefore understand why this feature has not really been addressed in the Shopify core...

 

However; 

  1. the ability to simply use the api/liquid/filters#sort by INVENTORY should indeed be an option for us in code
  2. and a selection should be available within collections via the drop menu to create collections ordered by inventor as follows in the feature request below

 

Feature Request 1:

I hope to attract enough attention to this issue that we can get Shopify to add a SORT BY STOCK/INVENTORY feature where as there are 3 sort options:

  • NATURAL (inventory does not change order)
  • STOCK_ASCENDING (highest stock first with out of stock items are pushed to the bottom of any list)
  • PROMOTE_LOW_STOCK (low stock items are pushed to the top of any list, out of stock 0 inventory at end)
  • STOCK_DESCENDING (out of stock items are pushed to the top of any list)
    • I see no reason to really have an option that pushes out of stock items to the top... but to be thorough may as well do it, its just the reverse of  {{ inventory_quantity }}
    • This however becomes critically important on the admin panel, hence it should exist.
      The idea being: "I want to see a list of all out of stock items"

Feature Request 2:

Upgrade the product collection array to allow something much like this:

 

{% assign products = collection.products | sort: 'inventory_quantity' %}
{% assign products = collection.products | sort: 'NATURAL' %}
{% assign products = collection.products | sort: 'STOCK_ASCENDING' %}
{% assign products = collection.products | sort: 'PROMOTE_LOW_STOCK' %}
{% assign products = collection.products | sort: 'STOCK_DESCENDING' %}

 

https://shopify.dev/api/liquid/filters#sort 

 

Feature Request 3:

Add these SORT OPTIONS into the admin panel so we can SORT our products by INVENTORY as well, this is a common task we need to accomplish under ADMIN->PRODUCTS within the FILTERS 

 

#end

 

QED:

I have thus demonstrated the usefulness of having STOCK SORTING filters and options for both the front end and back end. I have also demonstrated an overly elaborate method to do this, one that may be necessary for all the the extremely subjective usage cases out there that need custom code, but the core SORT BY STOCK option should still exist for us within the Shopify Core and Liquid Filters.

Replies 8 (8)

brickerking
Tourist
10 0 6

Yes, please!

antonkogan
Excursionist
30 1 8

I am trying to inset this into warehouse theme by maestroo and having no luck can you assist us?

thearchitect
Excursionist
40 3 15

Great work, this needs more likes!

And yeah, this should be in the default theme(working without a third party app)

I understand the upsell strategy with the apps, but this is a must have.

Redroot_Blades
Excursionist
23 3 4

This is exactly what I'm trying to do. Admin level sorting of products in a collection to display in stock items first by default. 

jtraverso
Shopify Partner
9 0 4

hi! good solution!

 

Worked ok when I tried on my site, but it orders the products in the same page only, if you have pagination enabled you can see in page 1 in stock then out of stock, in page 2 in stock and out of stock products, and so on (in stock first, out of stock second).

MullerMan
Shopify Partner
14 0 3

This is an excellent answer, very thorough. As a developer, I appreciate answers like this instead of those who just push to use apps. Keep it up my friend!

Redroot_Blades
Excursionist
23 3 4

Thanks again for this writeup! I was able to get it to work for the Pipeline theme. Slowly getting the functionality I need with on my store without Shopify. All the things I want are way obvious, and should come standard... 

 

Next on the list: When one variant of a unique/ one-of-a-kind item is sold, the other variant quantity goes to zero. I sell handmade knives, with the variant options being with or without a sheath, so if one knife sells with a sheath, for example, that unique product is gone! I have to jump in and manually change the remaining variant to zero or I could get a double purchase, which happened once. 

-Sean-
Excursionist
12 1 8

Hey cfc_webmaster,

I agree with everything you've suggested here, and thanks for the great work and analysis.

An additional suggestion or thought on what you have proposed:

  • Your Feature request, I feel this would have greater flexibility for admins if 'sorting out-of-stock to end of lists (Collections or Search lists)' could be set on/off globally with a toggle in the admin panel, and also the same feature to override/set each Collection individually, and this should support global and individual Collection Sort filter setting (which should include sort by Product title (default), Best selling, Created date, Discount, Price, Active date, Last updated, Quantity, and Manually, and with an additional choice for Descending or Ascending). I think admins should be able to set these settings globally (for all Collections and Search results) but then override for each individual Collection.

Could look something like this:

Sort feature.jpg

I suggest this for two reasons:

  1. A lot of admins, including me, need to be able to push Out-of-Stock products to the end of lists and collections independent of choosing an appropriate Sort order, and maybe in rare cases, not push Out-of-Stock products to the end at all. So, having these features separated will be more versatile.
  2. Having the feature to set a Sort filter globally as a default, and then override for each Collection if needed, will likely provide the quickest implementation setup and greatest flexibility for most Shopify admins.

But I definitely agree with you that this is a function needed for the core and it would be great if Shopify Product Management could please consider adding this as a priority.

Thanks.