Shopify Low Stock Counter Snippet
"Only X left" that reads real inventory and updates per variant.
Your details
Your snippet file (snippets/low-stock-counter.liquid)
{%- comment -%}
Low stock counter. Render inside the product form, near the variant picker:
{% render 'low-stock-counter', product: product %}
It shows the count for the selected variant and updates when the shopper picks a different
variant, as long as your theme fires a "change" event on the hidden variant id input (the
standard most Online Store 2.0 themes use). If it doesn't update on your theme, it will still
show the right count for whichever variant loaded the page.
inventory_quantity is only meaningful for variants with inventory tracked by Shopify: if
tracking is off, that field instead returns units sold, so this only renders when
inventory_management is "shopify".
{%- endcomment -%}
{%- style -%}
.ea-lsc{color:#b3261e;font-size:.9em;font-weight:600;margin:.4rem 0}
.ea-lsc[hidden]{display:none}
{%- endstyle -%}
{%- liquid
assign current = product.selected_or_first_available_variant
assign show = false
if current and current.inventory_management == 'shopify' and current.inventory_quantity > 0 and current.inventory_quantity <= 5
assign show = true
endif
assign text = "Only [count] left in stock" | replace: '[count]', current.inventory_quantity
-%}
<span id="LowStock-{{ product.id }}" class="ea-lsc" data-threshold="5" data-template="Only [count] left in stock" {% unless show %}hidden{% endunless %}>{{ text }}</span>
<script>
window.__eaLowStock = window.__eaLowStock || {};
window.__eaLowStock[{{ product.id | json }}] = {
qty: { {%- for variant in product.variants -%}{{ variant.id }}: {{ variant.inventory_quantity | default: 0 }}{% unless forloop.last %}, {% endunless %}{%- endfor -%} },
tracked: { {%- for variant in product.variants -%}{{ variant.id }}: {{ variant.inventory_management | json }}{% unless forloop.last %}, {% endunless %}{%- endfor -%} }
};
(function () {
var el = document.getElementById('LowStock-{{ product.id }}');
if (!el || el.dataset.wired) return;
el.dataset.wired = '1';
var form = el.closest('form');
var input = form ? form.querySelector('[name="id"]') : null;
if (!input) return;
var threshold = Number(el.getAttribute('data-threshold'));
var template = el.getAttribute('data-template');
function render() {
var data = window.__eaLowStock[{{ product.id | json }}];
var id = input.value;
var tracked = data.tracked[id] === 'shopify';
var qty = data.qty[id];
if (tracked && qty > 0 && qty <= threshold) {
el.textContent = template.replace('[count]', qty);
el.hidden = false;
} else {
el.hidden = true;
}
}
input.addEventListener('change', render);
})();
</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. Then add {% render 'low-stock-counter', product: product %} inside your product template, near the variant picker or Add to cart button.
Sold out products already show their own "Sold out" state from your theme, so this stays hidden at zero on purpose.
Live preview
Reads real inventory, per variant
The snippet checks variant.inventory_quantity, but only trusts it when variant.inventory_management is shopify: if a variant's inventory isn't tracked, that field returns units sold instead of stock on hand, which would show a nonsense count. Untracked variants simply don't trigger the counter.
Every variant's quantity and tracking status is embedded on the page as data, so when a shopper switches size or color, the count can update to match, without another server request.
- It listens for a
changeevent on the variant ID field, which is how most Online Store 2.0 themes signal a variant switch. If your theme uses a different mechanism, the count still shows correctly for whichever variant loaded the page, it just won't live-update when the shopper switches. - Sold-out variants (0 in stock) are left to your theme's own "Sold out" state; this counter stays hidden at zero on purpose.
Adding it to a product page
- 01
Add the snippet
Online Store → Themes → Edit code → Snippets → Add a new snippet named
low-stock-counter, paste the code, then add{% render 'low-stock-counter', product: product %}inside your product template, near the variant picker or Add to cart button.
Questions people ask
Why doesn't it show for some products?
Either that variant has more stock than your threshold, has 0 left (your theme's own sold-out state applies instead), or inventory isn't tracked on it, in which case there's no reliable number to show.
Does it update instantly when someone else buys the last few?
No. It reads inventory as of when the page loaded, not in real time across other shoppers' purchases. Refreshing the page shows the current count.
Can I show it on collection cards too?
This snippet is written for the product page, where a specific variant is selected. On collection cards, you'd need to decide which variant's count to show (usually the first available one), which needs a small edit to the render call.
Will it work with 100+ variants?
Yes, the inventory map is built once from product.variants regardless of count, though a very large variant count adds a small amount of page weight.
Related tools
Last reviewed 30 September 2026.
Sources: Shopify: variant object, inventory_quantity and inventory_management
