A merchant wants to display a “SALE” badge on product cards when any variant is on sale, but their current code only shows the badge when all variants are discounted.
The Problem:
Current logic compares product.compare_at_price vs product.price (both represent the lowest values across all variants)
This fails when only some variants have sale pricing
Example: A thermal imager has bundled variants on sale but one standalone variant at full price
Technical Issues Identified:
The product in question may not have compare_at_price set at all
Shopify’s product-level price properties can come from different variants, making savings calculations unreliable
False positives can occur if compare_at_price is set lower than the actual price
Recommended Solution:
Loop through all variants individually to check if any have variant.compare_at_price > variant.price. Set a flag (has_sale_variant) when found, then display the badge based on that flag. A complete code snippet using this approach was provided, which breaks the loop once a sale variant is detected for efficiency.
Summarized with AI on October 29.
AI used: claude-sonnet-4-5-20250929.
I’ve configured a “ON SALE” badge to show when a product is on sale.
However this seems to only work when ALL variants are on sale. I have a product where one of the variants is not on sale but the rest of the variants are. I’d still like the SALE badge to show on the product card (not product page).
This is the code snippet I’m currently using (yes it’s messy as I was playing around with showing the $ off)
One of the variants is $7750 CAD and not on sale; but the bundled items are on sale and because of that I’d like to have the “SALE” badge show on the card level.
This logic is a bit flawed, because, lowest price can be on one variant and lowest compare_at_price can be on another variant.
One would expect that if there is a compare_at_price on one variant, then this variant price should be even lower.
However, Shopify does not prevent you from entering compare_at_price lower than price on one of your variants and in this case there will be a false positive.
For the same reason, your savings math is flawed – it will take price from the cheapest variant but compare_at_price can come from another variant.
For this reason, code from @MARKLOIS is a more precise approach, kinda like this:
{%- elsif card_product.compare_at_price > card_product.price and card_product.available -%}
{% for variant in product.variants %}
{% if variant.compare_at_price > variant.price %}
Save {{ card_product.compare_at_price | minus: card_product.price | money -}}
{% break %}
{% endif %}
{% endfor %}
{%- endif -%}
Often this was a problem for people who have a very cheap sampler as variant on product with other, full-priced variants – your code will display unreal savings in this case.
Sets a variable has_sale_variant to false by default
Loops through all product variants
If any variant has a compare-at price greater than its actual price AND is available, sets has_sale_variant to true and breaks out of the loop
Shows the sale badge if has_sale_variant is true
This should display the “ON SALE” badge on your product card as long as at least one variant is on sale, which is exactly what you’re looking for with your thermal imager product.
Feel free to reach out if you’ve any more questions for us, cheers!
Shubham | Untechnickle