Shopify Product Badge Generator
Sale, New, sold out and your own tag-driven badges, on product cards and product pages.
Your details
Your snippet file (snippets/product-badges.liquid)
{%- comment -%}
Product badges: sale, sold out, new and tag-driven. Render inside a position:relative wrapper around your product image.
{%- endcomment -%}
{%- style -%}
.ea-badges2{position:absolute;left:.5rem;top:.5rem;display:flex;flex-direction:column;gap:.25rem;z-index:2;pointer-events:none}
.ea-badge{display:inline-block;padding:.25em .6em;border-radius:4px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.02em;color:#fff;background:#111;width:max-content}
.ea-badge--sale{background:#b3352c}
.ea-badge--soldout{background:#555}
.ea-badge--new{background:#1c6b4a}
.ea-badge[hidden]{display:none}
{%- endstyle -%}
{%- liquid
assign ea_variant = product.selected_or_first_available_variant
assign ea_show_sale = false
if ea_variant.compare_at_price > ea_variant.price
assign ea_show_sale = true
assign ea_sale_percent = ea_variant.compare_at_price | minus: ea_variant.price | times: 100 | divided_by: ea_variant.compare_at_price
endif
-%}
<span class="ea-badges2">
{%- if ea_show_sale -%}
<span class="ea-badge ea-badge--sale">-{{ ea_sale_percent }}%</span>
{%- endif -%}
{%- unless product.available -%}
<span class="ea-badge ea-badge--soldout">Sold out</span>
{%- endunless -%}
<span class="ea-badge ea-badge--new" hidden data-new-badge data-created="{{ product.created_at | date: '%s' }}" data-days="14">New</span>
{%- if product.tags contains "bestseller" -%}
<span class="ea-badge" style="background:#111111">Bestseller</span>
{%- endif -%}
{%- if product.tags contains "limited" -%}
<span class="ea-badge" style="background:#8a3b2b">Limited</span>
{%- endif -%}
</span>
<script>
document.querySelectorAll('[data-new-badge]').forEach(function (el) {
var created = Number(el.dataset.created) * 1000;
var days = Number(el.dataset.days) || 14;
if (Date.now() - created <= days * 86400000) el.hidden = false;
});
</script>To install: in Shopify admin go to Online Store → Themes, click … next to your theme → Edit code. Under Snippets choose Add a new snippet, name it as shown above, paste this code and save. Wrap your product image in a container with position: relative, then add {% render 'product-badges', product: product %} inside it.
Live preview
One snippet, several kinds of badge
The Sale badge compares compare_at_price to price and shows a percentage off or a fixed "Sale" label, computed at render time since a product's price doesn't change without the page being re-rendered. The Sold out badge reads product.available the same way.
The New badge is different: since Shopify caches product pages, checking "is this within 14 days of created_at" only in Liquid could keep showing New on a stale cached page long after it's no longer new. This badge is compared against today's date in the shopper's browser instead, so it always turns off on time.
Tag badges map any product tag to a label and color you choose (for example bestseller → "Bestseller"), read directly from product.tags.
Adding it to your theme
- 01
Add the snippet
Online Store → Themes → Edit code → Snippets → Add a new snippet named
product-badges, paste the code, then add{% render 'product-badges', product: product %}to your product card snippet and/or your product template.
Questions people ask
Why isn't my Sale badge showing?
It only appears when compare_at_price is set and higher than the current price. Check that field is filled in on the product or its variants.
Can I stack more than one badge?
Yes, all the badges you turn on can appear together; set a corner or position for each to control the layout.
Does the New badge use the product's creation date or publish date?
Its creation date (created_at), which is when it was first added to Shopify, not necessarily when it went live on your storefront.
Will this conflict with my theme's own sale badge?
It might duplicate it. Check your theme's product card settings for a built-in badge and turn it off there first.
Related tools
Last reviewed 30 September 2026.
