The tiered price is free with Shopify’s built-in discounts.
The visible 1 / 6 / 24 table on the product page needs one small Custom Liquid section (or a volume app).
I built and tested on a Dawn store.
Right now a product shows one price for any quantity:
Part 1 - the tiered price (free, built in)
Go to Discounts > Create discount > Amount off products.
First discount:
- Discount value: Fixed amount, 1.00 off, and leave “Only apply discount once per order” unchecked (so it comes off each item).
- Applies to: your product.
- Minimum purchase requirements: Minimum quantity of items = 6. Save.
Second discount: make it the same way, with 3.00 off and Minimum quantity of items = 24. Save.
You now have two automatic discounts:
How it behaves:
- 1 to 5 items: $12 each
- 6 to 23 items: $11 each
- 24 or more: $9 each
Shopify applies the best tier for the quantity in the cart on its own - they do not stack. This only shows in the cart and at checkout:
To cover many products at once, pick a collection under “Applies to” instead of a single product.
Part 2 - show the price table on the product page
The discounts above are invisible until the cart. To show the 1 / 6 / 24 table on the product page, add one Custom Liquid section.
Online Store > Themes > Customize > open your product template > Add section > Custom Liquid.
Paste this, then edit only the top two lines to your own quantities and prices. Save.
{%- comment -%}
Volume pricing table - paste into a Custom Liquid section on the product template.
Edit the two lines below to match your discounts. Keep the counts equal.
tier_qty = the "buy this many or more" break points (lowest first)
tier_price = the per-item price at each break point
{%- endcomment -%}
{%- assign tier_qty = '1,6,24' -%}
{%- assign tier_price = '12,11,9' -%}
{%- assign qtys = tier_qty | split: ',' -%}
{%- assign prices = tier_price | split: ',' -%}
<div class="vptable" data-qtys="{{ tier_qty }}" data-prices="{{ tier_price }}">
<p class="vptable__title">Buy more, save more</p>
<table class="vptable__grid">
<thead>
<tr><th>Quantity</th><th>Price each</th><th>You save</th></tr>
</thead>
<tbody>
{%- for q in qtys -%}
{%- assign i = forloop.index0 -%}
{%- assign unit = prices[i] | plus: 0 -%}
{%- assign base = prices[0] | plus: 0 -%}
{%- assign saved = base | minus: unit -%}
{%- assign nextq = qtys[forloop.index] -%}
<tr class="vptable__row" data-min="{{ q }}">
<td>
{%- if forloop.last -%}{{ q }}+
{%- elsif forloop.first and nextq -%}{{ q }}-{{ nextq | minus: 1 }}
{%- elsif nextq -%}{{ q }}-{{ nextq | minus: 1 }}
{%- else -%}{{ q }}+{%- endif -%}
</td>
<td>{{ unit | times: 100 | money }}</td>
<td>{%- if saved > 0 -%}{{ saved | times: 100 | money }} each{%- else -%}-{%- endif -%}</td>
</tr>
{%- endfor -%}
</tbody>
</table>
<p class="vptable__note">Discount applies automatically in the cart.</p>
</div>
<style>
.vptable{margin:1.5rem 0;font-size:1.4rem}
.vptable__title{font-weight:600;margin:0 0 .6rem}
.vptable__grid{width:100%;border-collapse:collapse}
.vptable__grid th,.vptable__grid td{padding:.7rem 1rem;text-align:left;border-bottom:1px solid rgba(0,0,0,.12)}
.vptable__grid th{font-size:1.2rem;text-transform:uppercase;letter-spacing:.04em;opacity:.7}
.vptable__row{cursor:pointer;transition:background .15s}
.vptable__row:hover{background:rgba(0,0,0,.04)}
.vptable__row.is-active{background:rgba(0,0,0,.07);font-weight:600}
.vptable__note{margin:.7rem 0 0;font-size:1.2rem;opacity:.7}
</style>
<script>
(function(){
function init(box){
if(box.dataset.vpReady) return; box.dataset.vpReady='1';
var mins=box.dataset.qtys.split(',').map(Number);
var rows=[].slice.call(box.querySelectorAll('.vptable__row'));
var qtyInput=document.querySelector('form[action*="/cart/add"] input[name="quantity"]')
||document.querySelector('input[name="quantity"]');
function tierIndex(q){var idx=0;for(var i=0;i<mins.length;i++){if(q>=mins[i])idx=i;}return idx;}
function paint(){
var q=qtyInput?parseInt(qtyInput.value,10)||1:1;
var idx=tierIndex(q);
rows.forEach(function(r,i){r.classList.toggle('is-active',i===idx);});
}
rows.forEach(function(r){
r.addEventListener('click',function(){
if(!qtyInput) return;
qtyInput.value=r.dataset.min;
qtyInput.dispatchEvent(new Event('change',{bubbles:true}));
qtyInput.dispatchEvent(new Event('input',{bubbles:true}));
paint();
});
});
if(qtyInput){
qtyInput.addEventListener('change',paint);
qtyInput.addEventListener('input',paint);
}
paint();
}
function run(){document.querySelectorAll('.vptable').forEach(init);}
if(document.readyState!=='loading')run();else document.addEventListener('DOMContentLoaded',run);
document.addEventListener('shopify:section:load',run);
})();
</script>
The table shows on the page. The row for the current quantity is highlighted, and clicking a row sets the quantity:
Keep the numbers in Part 1 and Part 2 the same, so the page matches what the cart charges. Prices use your store’s own currency automatically (my test store shows the rupee sign).
Prefer no code? A quantity-break app shows the table and applies the tiers together: Wide Bundles, Bundler, or VolumeBoost.
Regards,
Ploqo