Replace "Save $X" collection sale badges with stock availability

Topic summary

A user wants to replace “Save $X” sale badges on product collection pages with stock availability indicators: “Ready to ship” for in-stock items or “Made to order” for items with zero/low stock.

Initial Implementation:

  • EBOOST provided code modifications to the card-product.liquid snippet file
  • First version used product availability (if card_product.available) to determine badge display

Refinement Issues:

  • Products with stock still showed “Made to order” incorrectly
  • User needed logic based on actual inventory quantity, not just availability status
  • Many products have “continue selling when out of stock” enabled, complicating the logic

Evolving Requirements:

  • Changed threshold from 0 stock to 150 units: products with <150 pieces per variant should show “Made to order”
  • Problem persists: items with 100 pieces per variant still display “Ready to ship”

Current Status:

  • EBOOST identified the issue: collection pages only show first variant’s inventory
  • Provided updated code using variantfirst.inventory_quantity to check stock levels
  • User granted store access (password: “staoto”) for troubleshooting
  • Discussion remains open as implementation is being refined
Summarized with AI on November 7. AI used: claude-sonnet-4-5-20250929.

I am trying to replace the “Save $X” badges on my collections to either display the text “Ready to ship” or “Made to order” based on whether the item I’m selling has 0 stock and is custom made to order, or has stock ready to ship.

This is my website 578f0e-a2.myshopify.com for refernce

Hi @sibouss ,

This is not free theme. So could you please share code? this file snippets/card-product.liquid code. I will help to update code for you.

how can i share it? screenshot?

Hi,

  1. Go to Store Online-> theme → edit code

  1. snippets/card-product.liquid

Hi,

Could you share code of this file?

{% comment %}
  Renders a product card

  Accepts:
  - card_product: {Object} Product Liquid object (optional)
  - media_aspect_ratio: {String} Size of the product image card. Values are "square" and "portrait". Default is "square" (optional)
  - show_secondary_image: {Boolean} Show the secondary image on hover. Default: false (optional)
  - show_vendor: {Boolean} Show the product vendor. Default: false
  - show_rating: {Boolean} Show the product rating. Default: false
  - extend_height: {Boolean} Card height extends to available container space. Default: true (optional)
  - lazy_load: {Boolean} Image should be lazy loaded. Default: true (optional)
  - show_quick_add: {Boolean} Show the quick add button.
  - section_id: {String} The ID of the section that contains this card.
  - horizontal_class: {Boolean} Add a card--horizontal class if set to true. Default: false (optional)
  - horizontal_quick_add: {Boolean} Changes the quick add button styles when set to true. Default: false (optional)

  Usage:
  {% render 'card-product', show_vendor: section.settings.show_vendor %}
{% endcomment %}

{%- if card_product and card_product != empty -%}
  {%- liquid
      assign ratio = 1
      if card_product.featured_media and media_aspect_ratio == 'portrait'
          assign ratio = 0.8
      elsif card_product.featured_media and media_aspect_ratio == 'adapt'
          assign ratio = card_product.featured_media.aspect_ratio
      endif
      if ratio == 0 or ratio == null
          assign ratio = 1
      endif
  -%}
  

    

      

        {%- if card_product.featured_media -%}
          {% comment %} Variants Wise Change Product Image {% endcomment %}
          

              {%- assign media = card_product.selected_or_first_available_variant.featured_media -%}
            

                {% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
                
                  
                    {%- if card_product.media[1] != nil and show_secondary_image -%}
                      
                    {%- endif -%}
                
            

            {%- liquid
              assign media_to_render = card_product.featured_media.id
              for variant in card_product.variants
                  assign media_to_render = media_to_render | append: variant.featured_media.id | append: ' '
              endfor
            -%}
            {%- for media in card_product.media -%}
              {%- if media_to_render contains media.id and media.id != card_product.selected_or_first_available_variant.featured_media.id -%}
                
                  
                  
                    {%- if card_product.media[1] != nil and show_secondary_image -%}
                      
                      {%- endif -%}
                  
                

              {%- endif -%}
            {%- endfor -%}
          

        {%- else -%}
          
            

              ### 
                
                  {{ card_product.title | escape }}
                
              
            

          

        {%- endif -%}

        {%- liquid
          if show_variants
            assign target = card_product.selected_or_first_available_variant
          else
            assign target = card_product
          endif
          assign compare_at_price = target.compare_at_price
          assign price = target.price | default: 1999
          if compare_at_price > price
            assign price_difference_percent = compare_at_price | minus: price | times: 100 | divided_by: compare_at_price | round
            assign price_difference_amount = compare_at_price | minus: price | money_with_currency
          endif
        -%}
        
          {% for tags in card_product.tags %}
            {% assign new_badge = tags | downcase %}
            {% if new_badge == 'new' %}
              
                {%- if settings.new_icon != 'none' -%}
                  {% render 'icon-accordion', icon: settings.new_icon %}
                {%- endif -%}
                {{- 'products.product.new' | t -}}
              
            {% endif %}
          {% endfor %}
          {%- if card_product.available == false -%}
            
              {%- if settings.sold_icon != 'none' -%}
                {% render 'icon-accordion', icon: settings.sold_icon %}
              {%- endif -%}
              {{- 'products.product.sold_out' | t -}}
            
          {%- endif -%}
          {% if settings.percentage == true %}
            
              {%- if settings.percentage_icon != 'none' -%}
                {% render 'icon-accordion', icon: settings.percentage_icon %}
              {%- endif -%}
              {{ price_difference_percent }}{{ 'products.product.off_price' | t }}
            
          {% endif %}
          {% if settings.diff_price == true %} 
            
              {%- if settings.sale_icon != 'none' -%}
                {% render 'icon-accordion', icon: settings.sale_icon %}
              {%- endif -%}
              {{- 'products.product.save' | t -}} {{ price_difference_amount }}
            
          {%- endif -%}
        

        
          {%- if show_quick_add -%}
            

              {%- assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id -%}
              
              
            

          {%- endif -%}
          
            {% unless card_product.has_only_default_variant or show_variants != true %}
              
            {% else %}
              

                {%- liquid
                  assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id
                  assign qty_rules = false
                  if card_product.selected_or_first_available_variant.quantity_rule.min > 1 or card_product.selected_or_first_available_variant.quantity_rule.max != null or card_product.selected_or_first_available_variant.quantity_rule.increment > 1
                    assign qty_rules = true
                  endif
                -%}
                {%- if card_product.variants.size > 1 or qty_rules -%}
                  
                  
                {%- else -%}
                  
                {%- endif -%}
              

            {% endunless %}
          

        

      

        
          

            {% if show_count_timer %}
              {% if card_product.metafields.custom.product_timer %}
                

                  
 
                    

                      00
                      {{ 'wbcustomlabel.wballtext.time_days' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_hour' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_min' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_sec' | t }}
                    

                  

                

              {% endif %}
            {% endif %}

        

    

  

{%- else -%}
  
     

      

        

          

            {%- if placeholder_image -%}
              {{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
            {%- else -%}
              {{ 'product-apparel-2' | placeholder_svg_tag: 'placeholder-svg' }}
            {% endif %}
          

        

      

        
      
        

          {%- if show_vendor -%}
              {{ 'accessibility.vendor' | t }}
              
{{ 'products.product.vendor' | t }}

          {%- endif -%}
          ### 
            
                {{ 'onboarding.product_title' | t }}
            
           
          
            {{ block.settings.description | escape }}
            

              {%- render 'price', product: card_product, use_variant: true, show_badges: true -%}
            

          

        

      

    

  

{%- endif -%}

Hi,

May I suggest code below:

{% comment %}
  Renders a product card

  Accepts:
  - card_product: {Object} Product Liquid object (optional)
  - media_aspect_ratio: {String} Size of the product image card. Values are "square" and "portrait". Default is "square" (optional)
  - show_secondary_image: {Boolean} Show the secondary image on hover. Default: false (optional)
  - show_vendor: {Boolean} Show the product vendor. Default: false
  - show_rating: {Boolean} Show the product rating. Default: false
  - extend_height: {Boolean} Card height extends to available container space. Default: true (optional)
  - lazy_load: {Boolean} Image should be lazy loaded. Default: true (optional)
  - show_quick_add: {Boolean} Show the quick add button.
  - section_id: {String} The ID of the section that contains this card.
  - horizontal_class: {Boolean} Add a card--horizontal class if set to true. Default: false (optional)
  - horizontal_quick_add: {Boolean} Changes the quick add button styles when set to true. Default: false (optional)

  Usage:
  {% render 'card-product', show_vendor: section.settings.show_vendor %}
{% endcomment %}

{%- if card_product and card_product != empty -%}
  {%- liquid
      assign ratio = 1
      if card_product.featured_media and media_aspect_ratio == 'portrait'
          assign ratio = 0.8
      elsif card_product.featured_media and media_aspect_ratio == 'adapt'
          assign ratio = card_product.featured_media.aspect_ratio
      endif
      if ratio == 0 or ratio == null
          assign ratio = 1
      endif
  -%}
  
    

      

        {%- if card_product.featured_media -%}
          {% comment %} Variants Wise Change Product Image {% endcomment %}
          

              {%- assign media = card_product.selected_or_first_available_variant.featured_media -%}
            

                {% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
                
                  
                    {%- if card_product.media[1] != nil and show_secondary_image -%}
                      
                    {%- endif -%}
                
            

            {%- liquid
              assign media_to_render = card_product.featured_media.id
              for variant in card_product.variants
                  assign media_to_render = media_to_render | append: variant.featured_media.id | append: ' '
              endfor
            -%}
            {%- for media in card_product.media -%}
              {%- if media_to_render contains media.id and media.id != card_product.selected_or_first_available_variant.featured_media.id -%}
                
                  
                  
                    {%- if card_product.media[1] != nil and show_secondary_image -%}
                      
                      {%- endif -%}
                  
                

              {%- endif -%}
            {%- endfor -%}
          

        {%- else -%}
          
            

              ### 
                
                  {{ card_product.title | escape }}
                
              
            

          

        {%- endif -%}

        {%- liquid
          if show_variants
            assign target = card_product.selected_or_first_available_variant
          else
            assign target = card_product
          endif
          assign compare_at_price = target.compare_at_price
          assign price = target.price | default: 1999
          if compare_at_price > price
            assign price_difference_percent = compare_at_price | minus: price | times: 100 | divided_by: compare_at_price | round
            assign price_difference_amount = compare_at_price | minus: price | money_with_currency
          endif
        -%}
        
          {% for tags in card_product.tags %}
            {% assign new_badge = tags | downcase %}
            {% if new_badge == 'new' %}
              
                {%- if settings.new_icon != 'none' -%}
                  {% render 'icon-accordion', icon: settings.new_icon %}
                {%- endif -%}
                {{- 'products.product.new' | t -}}
              
            {% endif %}
          {% endfor %}
          {%- if card_product.available == false -%}
            
              {%- if settings.sold_icon != 'none' -%}
                {% render 'icon-accordion', icon: settings.sold_icon %}
              {%- endif -%}
              {{- 'products.product.sold_out' | t -}}
            
          {%- endif -%}
          {% if settings.percentage == true %}
            
              {%- if settings.percentage_icon != 'none' -%}
                {% render 'icon-accordion', icon: settings.percentage_icon %}
              {%- endif -%}
              {{ price_difference_percent }}{{ 'products.product.off_price' | t }}
            
          {% endif %}
           
            {%- if card_product.available-%}
               Made to order
            {%- else -%}  
              Ready to ship
            {%- endif -%}
            
        

        
          {%- if show_quick_add -%}
            

              {%- assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id -%}
              
              
            

          {%- endif -%}
          
            {% unless card_product.has_only_default_variant or show_variants != true %}
              
            {% else %}
              

                {%- liquid
                  assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id
                  assign qty_rules = false
                  if card_product.selected_or_first_available_variant.quantity_rule.min > 1 or card_product.selected_or_first_available_variant.quantity_rule.max != null or card_product.selected_or_first_available_variant.quantity_rule.increment > 1
                    assign qty_rules = true
                  endif
                -%}
                {%- if card_product.variants.size > 1 or qty_rules -%}
                  
                  
                {%- else -%}
                  
                {%- endif -%}
              

            {% endunless %}
          

        

      

        
          

            {% if show_count_timer %}
              {% if card_product.metafields.custom.product_timer %}
                

                  
 
                    

                      00
                      {{ 'wbcustomlabel.wballtext.time_days' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_hour' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_min' | t }}
                    

                    
                      00
                      {{ 'wbcustomlabel.wballtext.time_sec' | t }}
                    

                  

                

              {% endif %}
            {% endif %}

        

    

  

{%- else -%}
  
     

      

        

          

            {%- if placeholder_image -%}
              {{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
            {%- else -%}
              {{ 'product-apparel-2' | placeholder_svg_tag: 'placeholder-svg' }}
            {% endif %}
          

        

      

        
      
        

          {%- if show_vendor -%}
              {{ 'accessibility.vendor' | t }}
              
{{ 'products.product.vendor' | t }}

          {%- endif -%}
          ### 
            
                {{ 'onboarding.product_title' | t }}
            
           
          
            {{ block.settings.description | escape }}
            

              {%- render 'price', product: card_product, use_variant: true, show_badges: true -%}
            

          

        

      

    

  

{%- endif -%}

I added it, but products that do have stock are still displaying as “made to order” - could you please check

https://jwlcrate.com/collections/bracelets?sort_by=best-selling&filter.v.availability=1&filter.v.price.gte=0&filter.v.price.lte=1187.00&filter.v.price.gte=0&filter.v.price.lte=1187

And is it possible to create a stock limit cut off, for example if a product has less than 2 pieces in stock to make it just display as “made to order”

Hi,

Sorry, I checked wrong conditions

Updated from

to

You can get content new here https://github.com/eboost10/2640367/blob/main/jwlcrate/card-product.liquid

can the basis of the tag be whether the product has either 0 stock or more than 0 stock

for example most of our product have 0 stock but have the “continue selling when out of stock” option turn one - those are referred to our “Made to order” products.

Our other products which do have stock added in our backend, should be shown as “ready to ship”

because with the current rules of “if available” it still still sets products that have 0 stock as “ready to ship” rather than “made to order”

Hi,

I updated new code to check base on quantity. Could you get code here https://github.com/eboost10/2640367/blob/main/jwlcrate/card-product.liquid

thanks, should i change it to “qty < 1” if I want to be the basis whether there is 0 stock or more than 0 /or at least 1 in stock?

I suggested code to include this request

EBOOST_0-1719956307379.png

You can adjust it depends on yourself

1 Like

thanks, yea I decided to change that. Should the quantity set be “qty < 1” or “qty <0” for the request above?

Hi,

It should be "qty < 1 "

1 Like

hey i just made a change so i need it to display the “made to order” tag when the stock is under 150. I’ve changed the number in the code where previous indicated but some products with under 150 stock still show the “ready to ship” tag

could you help?