Updated September 2026
If you've spent any time on Shopify forums you've seen this question. Someone asks how to show an “only 3 left” message on the product page. Five replies, five different apps suggested. Nobody mentions that Dawn already does this.
So this is about the part of the conversation that keeps getting skipped. Three tiers, in order: what Dawn gives you for free, where the built-in block stops being enough, and the snippet that covers most of what's left.
What Dawn already does
Open the theme editor, go to your product template, and add an Inventory status block to the product information section. It has three settings: Text style, Low inventory threshold (0 to 100) and an Inventory count checkbox that adds the number to the message.
Out of the box it shows “In stock” above the threshold, “Low stock” at or below it, and “Out of stock” at zero, with a small colored dot. Tick Inventory count and those become “12 in stock” and “Low stock: 3 left”. It already handles products set to continue selling when out of stock (they keep showing “In stock”), and it only appears for variants whose inventory Shopify tracks. When a customer switches variants, Dawn swaps in the new variant's message without a page reload.
Quick test before going further: open a product page, pick a variant with two units in stock, and see if the message appears. If it does and you're happy with the wording, you don't need the snippet below. You don't need an app either. You can close this tab.
Where the built-in block stops being enough
Four cases come up often enough that they're worth naming.
- Tiered messaging. The built-in block has one threshold and one low-stock message. “Low stock: 5 left” reads the same whether stock is at five or at one. Some stores want a softer note at ten, a sharper one at three, and nothing at all when stock is healthy.
- Conditional logic. Maybe you only want low-stock messages on certain collections, above a certain price, or for logged-in customers. The theme editor has no setting for any of that.
- Presentation. The block inherits theme typography and a fixed icon. Stores with a more designed product page often want it styled differently.
- Other surfaces. Collection cards, the cart, quick-add modals. The block lives in the product information section and stays there.
If none of those describe your store, stop here. The default block is doing its job.
The snippet
<div id="StockMsg-{{ product.id }}">
{%- liquid
assign variant = product.selected_or_first_available_variant
assign stock = variant.inventory_quantity
assign tracked = variant.inventory_management
-%}
{%- if tracked == 'shopify' and variant.inventory_policy != 'continue' -%}
{%- if stock <= 0 -%}
<p class="stock-msg out">Sold out. Back in soon.</p>
{%- elsif stock <= 3 -%}
<p class="stock-msg critical">Only {{ stock }} left.</p>
{%- elsif stock <= 10 -%}
<p class="stock-msg low">Low stock. {{ stock }} remaining.</p>
{%- endif -%}
{%- endif -%}
</div>
<script>
if (typeof subscribe === 'function' && typeof PUB_SUB_EVENTS !== 'undefined') {
subscribe(PUB_SUB_EVENTS.variantChange, function (event) {
var id = 'StockMsg-{{ product.id }}';
var fresh = event.data.html.getElementById(id);
var current = document.getElementById(id);
if (fresh && current) current.innerHTML = fresh.innerHTML;
});
}
</script>
A few things going on that are worth flagging.
selected_or_first_available_variant is the right reference. Not variants.first, which is whichever variant was created first in the admin and has nothing to do with what your customer is looking at. On a single-variant product they're the same thing. On anything multi-variant, they're not.
The inventory_policy != 'continue' check is the one most snippets online forget. Some stores keep selling after stock hits zero and fulfill later. Showing “sold out” on those products is wrong, because they aren't sold out. With the policy set to continue, the snippet stays quiet and lets the customer order. (If that's you, our guide to handling backordered items in the cart covers the other half.)
The short script is there because of how current versions of Dawn switch variants. Dawn fetches the product section for the new variant, but only copies across specific pieces (the price, SKU, inventory status and a few others), not Custom Liquid blocks. Without the script, the message would keep showing the stock of the variant the page loaded with. The script listens for Dawn's own variant-change event and copies the fresh message across. If your theme isn't Dawn or a Dawn-based theme, the if check simply skips it.
Where to put it
In the theme editor, add a Custom Liquid block to the product information section and paste the snippet in. Drag it where you want it, usually under the price or above the add-to-cart button, and remove Dawn's Inventory status block so you don't show two messages. Then style the three classes (out, critical, low) in your theme's custom CSS so each tier has its own visual weight.
Why a block instead of editing main-product.liquid directly: block content is stored as a setting, and Shopify copies theme editor customizations across when you update the theme to a new version. Edits to theme files only come along if they don't conflict with the update; when they do, they're dropped and you have to redo them. Worth the ten extra seconds.
Test it on a variant with 2 units, one with 8, one with 0 and one set to continue selling, switching between them without reloading.
When you actually need an app
There are real cases: messaging that depends on which location has stock, stock that should count incoming purchase orders or scheduled restocks, A/B tests on urgency copy, or different messages by country. If your store is one of those, an app or a custom build is the right answer, and it's worth choosing carefully, because every storefront app adds code to your pages. We explain the trade-off in why a Shopify app can slow down your store and apps, custom code or something in between.
Most stores aren't one of those. Most stores are choosing between the built-in block and a snippet, and the answer comes down to whether tiered messaging matters enough to justify twenty lines of code. That's a more useful question than “which app should I install.”
Pasilobus builds Shopify apps and does storefront engineering for Shopify stores. If your low-stock problem is more complicated than the one in this post, tell us about it.