Shopify Collection Prices: How to Display In-Stock Variant Prices (A Community-Driven Fix)

Hey there, fellow store owners! Let's chat about something that's probably bugged more than a few of you: those pesky product prices on your collection pages. You know, when a product has multiple variants, and your store decides to show the absolute lowest price, even if that particular variant is out of stock? It's not just confusing for customers; it can actually hurt your sales by setting false expectations.

I recently saw a fantastic discussion in the Shopify Community that really dug into this, and I wanted to share the insights and the solution with you. Our friend, GamesRealm, brought up this exact issue, and the community rallied to help.

The Problem: Showing Unavailable Prices on Collection Pages

GamesRealm runs a store selling collectibles, specifically Pokémon singles. They noticed a common problem: on their collection page for Pokemon Singles – Games Realm, products were displaying the price of their lowest-priced variant, even if that variant (like a card in "Poor" condition for $2) was completely out of stock. Meanwhile, an available, higher-priced variant (say, "Excellent" condition for $2.40) was being overlooked in the displayed price. This is a classic case of the theme's default price logic not quite aligning with real-world inventory.

As GamesRealm put it, they were "looking for someone who can help me fix an issue with my store theme where it's showing the lowest variant price for a product in the collection pages instead of the highest." (Actually, they meant the lowest available, not necessarily the highest, but the intent was clear: show an accurate, buyable price).

Why This Happens (and How to Fix It!)

Often, the culprit is how your theme's price rendering snippet (usually price.liquid) calculates and displays the price. By default, many themes will look for product.price or product.price_min, which grabs the absolute lowest price across *all* variants, regardless of their availability. What we really need is to find the lowest price among the *available* variants.

Mustafa_Ali, a helpful expert in the community, stepped in with a brilliant and direct solution. The key is to modify the price.liquid snippet to explicitly filter for available variants before determining the price to display. Here’s how you can implement this fix:

Step-by-Step Instructions to Update Your Price Display Logic

Before you start, it's always a good idea to duplicate your theme. This creates a backup in case anything goes wrong, giving you peace of mind!

  1. Access Your Shopify Admin: Log in to your Shopify store admin panel.
  2. Navigate to Themes: Go to Online Store > Themes.
  3. Edit Theme Code: Find your current, active theme, click on Actions, and then select Edit code.
  4. Locate price.liquid: In the file search bar (usually on the left sidebar), type price.liquid. This file is typically located within the Snippets folder.
  5. Backup Your Existing Code: Crucial Step! Copy the entire content of your current price.liquid file and paste it into a simple text editor (like Notepad or TextEdit) or a Google Doc. Save this backup!
  6. Replace the Code: Delete all the existing code in price.liquid.
  7. Paste the New Code: Copy the following code snippet provided by Mustafa_Ali and paste it into the now-empty price.liquid file:
{%- comment -%}
    Renders a list of product's price (regular, sale)

    Accepts:
    - product: {Object} Product Liquid object (optional)
    - use_variant: {Boolean} Renders selected or first variant price instead of overall product pricing (optional)
    - show_badges: {Boolean} Renders 'Sale' and 'Sold Out' tags if the product matches the condition (optional)
    - price_class: {String} Adds a price class to the price element (optional)

    Usage:
    {% render 'price', product: product %}
{%- endcomment -%}

{%- liquid
    if use_variant
        assign target = product.selected_or_first_available_variant
    else
        assign target = product
    endif

    comment
      FIX: Instead of using product.price (which is price_min and can include
      unavailable variants), we find the cheapest AVAILABLE variant explicitly.
      This ensures collection pages show the correct in-stock starting price.
    endcomment

    assign available_variants = product.variants | where: 'available', true

    if available_variants.size > 0
        assign first_available = available_variants | sort: 'price' | first
        assign compare_at_price = first_available.compare_at_price
        assign price = first_available.price
        assign available = true
    else
        assign compare_at_price = target.compare_at_price
        assign price = target.price | default: 1999
        assign available = target.available | default: false
    endif

    if settings.currency_format_enable
        assign m | money_with_currency
    else
        assign m | money
    endif

    if target == product and product.price_varies
        assign m | t: price: money_price
    endif
-%}

{%- comment -%} Explanation of description list: - div.price__regular: Displayed when there are no variants on sale - div.price__sale: Displayed when a variant is on sale - div.price__availability: Displayed when the product is sold out {%- endcomment -%}
{{ money_price }}
{%- if settings.currency_format_enable -%} {{ compare_at_price | money_with_currency }} {%- else -%} {{ compare_at_price | money }} {%- endif -%}
{{ money_price }}
{%- if settings.show_saved_price and price != nil and price != blank and compare_at_price != nil and compare_at_price != blank -%} {%- assign saved_price = compare_at_price | minus: price | money -%}
{{ 'products.product.price.saved_price_html' | t: price: saved_price }}
{%- endif -%} {%- if settings.show_price_percent -%}
{%- liquid assign list_compare = product.variants | where: 'compare_at_price' assign compare = 0 for variant in list_compare assign saving = variant.compare_at_price | minus: variant.price | times: 100.0 | divided_by: variant.compare_at_price | round if saving > compare assign compare = saving endif endfor if compare < 1 assign compare = product.compare_at_price_max | minus: product.price_max | times: 100.0 | divided_by: product.compare_at_price_max | round endif -%} (-{{ compare | append: '%' }})
{%- endif -%}
{{ 'products.product.price.unit_price' | t }}
{{- product.selected_or_first_available_variant.unit_price | money -}}  {{ 'accessibility.unit_price_separator' | t }}  {%- if product.selected_or_first_available_variant.unit_price_measurement.reference_value != 1 -%} {{- product.selected_or_first_available_variant.unit_price_measurement.reference_value -}} {%- endif -%} {{ product.selected_or_first_available_variant.unit_price_measurement.reference_unit }}
  1. Save Your Changes: Click the Save button.
  2. Check Your Store: Clear your browser's cache and visit your collection pages. You should now see the prices correctly reflecting the lowest *available* variant! GamesRealm confirmed this solution worked perfectly for them, which is always great to hear.

A Deeper Dive: What the Code Does

The crucial part of Mustafa_Ali's code is this block:

    assign available_variants = product.variants | where: 'available', true

    if available_variants.size > 0
        assign first_available = available_variants | sort: 'price' | first
        assign compare_at_price = first_available.compare_at_price
        assign price = first_available.price
        assign available = true
    else
        assign compare_at_price = target.compare_at_price
        assign price = target.price | default: 1999
        assign available = target.available | default: false
    endif

It first creates a list of available_variants by filtering all product variants where available is true. Then, if there are any available variants, it sorts them by price and picks the first one – effectively finding the *cheapest available variant*. This first_available variant then dictates the price and compare_at_price that gets displayed.

Tim_1's Valuable Insight: Snippet Usage

Another community member, tim_1, chimed in with a really important point that's worth keeping in mind for general theme development. They highlighted that many themes use the same price.liquid snippet for both product cards (on collection pages) and the actual product detail page. While Mustafa_Ali's solution directly addresses the collection page issue, tim_1's advice serves as a good reminder to be aware of where your snippets are being used.

They suggested that if you're pulling from product.selected_or_first_available_variant, it ensures you're always getting an available variant. While Mustafa's solution is more specific to finding the *cheapest* available, tim_1's comment underscores the importance of considering availability across all contexts. In this specific case, Mustafa's approach is more robust for GamesRealm's exact problem.

So, there you have it! A common Shopify pricing headache, solved with a clever community-driven code edit. It's a great example of how a small tweak in your Liquid code can make a big difference in how your products are presented and ultimately, how your customers perceive your store. Don't let those out-of-stock prices mislead your shoppers anymore; get those collection pages showing accurate, available variant prices!

Share:

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools