Volume Pricing Theme Extension
Looking for the Liquid approach? See Storefront Widgets — Tier Pricing Block for a manual Liquid implementation.
Overview
The PromoSync Tier Pricing block displays quantity-based price breaks on product pages. It reads per-variant pricing data from the psrestful.part_price_array metafield and renders an interactive table that updates automatically when the customer switches variants.
Two layout modes are available:
- Table (vertical) — Traditional rows: one row per price break with Quantity, Price, and optional Unit columns. Supports Standard, Striped, and Compact table styles.
- Horizontal rows — Compact two-row layout: quantities across the top, prices below. Ideal for products with many price breaks. Scrolls horizontally when needed.
Both layouts update dynamically on variant change without a page reload.
How to Add the Block
- In your Shopify admin, go to Online Store > Themes > Customize
- Navigate to a Product page template
- Click Add block > search for PromoSync Tier Pricing
- Configure the settings (see below)
- Drag the block to your preferred position (typically below the price or above Add to Cart)
- Save
No theme code changes required.
Settings Reference
| Setting | ID | Type | Default | Notes |
|---|---|---|---|---|
| Layout | layout | select | table | table (vertical) or horizontal (two-row) |
| Show heading | show_header | checkbox | true | Displays “Volume Pricing” heading above the table |
| Show unit column | show_unit | checkbox | true | Table layout: adds a Unit column. Horizontal layout: shows unit as suffix on heading, e.g. “Volume Pricing (EA)“ |
| Unit label | unit_label | text | EA | The unit label text (e.g. “EA”, “PC”, “Each”) |
| Table style | table_style | select | standard | standard, striped, or compact. Applies to table layout only |
Layout Comparison
Table (vertical)
Best for: fewer price breaks (2-5 tiers), when you want a traditional readable format.
Volume Pricing
┌──────────┬─────────┬──────┐
│ Quantity │ Price │ Unit │
├──────────┼─────────┼──────┤
│ 24+ │ $12.50 │ EA │
│ 48+ │ $11.00 │ EA │
│ 100+ │ $9.50 │ EA │
│ 250+ │ $8.00 │ EA │
└──────────┴─────────┴──────┘Table style options:
| Style | Description |
|---|---|
| Standard | Clean borders, no row shading |
| Striped | Alternating row background for readability |
| Compact | Reduced padding for tighter vertical space |
Horizontal rows
Best for: many price breaks (5+ tiers), compact product layouts, mobile-friendly display.
Volume Pricing (EA)
┌────────┬────────┬────────┬────────┬────────┐
│ 24+ │ 48+ │ 100+ │ 250+ │ 500+ │
├────────┼────────┼────────┼────────┼────────┤
│ $12.50 │ $11.00 │ $9.50 │ $8.00 │ $7.25 │
└────────┴────────┴────────┴────────┴────────┘When price breaks exceed the available width, the table scrolls horizontally.
Data Format
The block reads variant.metafields.psrestful.part_price_array, which must be a JSON array of price break objects:
[
{"quantityMin": 24, "price": 1250},
{"quantityMin": 48, "price": 1100},
{"quantityMin": 100, "price": 950},
{"quantityMin": 250, "price": 800}
]quantityMin— Minimum quantity to qualify for this tierprice— Price per unit in cents (e.g.1250= $12.50)
Each variant can have different price breaks. The block automatically switches data when the customer selects a different variant.
How Variant Switching Works
- A hidden
<script>tag (tier-pricing-datasnippet) renders all variant price break data as JSON, keyed by variant ID - The JavaScript
ProductTierHandlerlistens for Shopify’svariant:changeevent - On variant change, it looks up the new variant’s price breaks and rebuilds the table:
- Table layout: rebuilds
<tbody>rows - Horizontal layout: rebuilds both
<thead>columns and<tbody>columns (since different variants may have different numbers of tiers)
- Table layout: rebuilds
- If the new variant has no price breaks, the table is hidden
Interaction with Volume Pricing (Shopify Functions)
The tier pricing block is display-only — it shows the customer what prices they will receive at different quantities. The actual price enforcement happens separately:
- Shopify Functions (Plus stores or stores with Functions access): The
quantity-price-breaksfunction automatically applies the correct discount at checkout based on cart quantities. No additional theme work needed. - Draft Orders (non-Plus stores): Checkout is intercepted and a Draft Order is created with the correct line item prices.
The tier pricing table and the checkout discount use the same psrestful.part_price_array metafield, so they are always in sync.
Active Tier Highlighting
When a quantity input is present on the product page, the JavaScript can highlight the currently active tier row. The active row receives the CSS class promo-tier--active, which can be styled via:
.promo-tier-pricing__table tbody tr.promo-tier--active {
background-color: rgba(0, 128, 96, 0.08);
font-weight: 600;
}This only applies to the table (vertical) layout.
CSS Customization
All spacing and border values use CSS custom properties that can be overridden in your theme:
:root {
--promo-spacing-xs: 0.25rem;
--promo-spacing-sm: 0.5rem;
--promo-spacing-md: 1rem;
--promo-spacing-lg: 1.5rem;
--promo-radius: 0.5rem;
--promo-radius-sm: 0.25rem;
}The block intentionally inherits fonts, colors, and text sizes from the active theme — no font overrides are applied.
Key CSS Classes
| Class | Element | Layout |
|---|---|---|
.promo-tier-pricing | Outer container | Both |
.promo-tier-pricing__heading | ”Volume Pricing” heading | Both |
.promo-tier-pricing__table | <table> element | Table |
.promo-tier-pricing__table--striped | Striped modifier | Table |
.promo-tier-pricing__table--compact | Compact modifier | Table |
.promo-tier-pricing--horizontal | Outer container modifier | Horizontal |
.promo-tier-pricing__hscroll | Scroll wrapper | Horizontal |
.promo-tier-pricing__htable | <table> element | Horizontal |
.promo-tier-pricing__unit-suffix | ”(EA)” suffix on heading | Horizontal |
Cart Integration
The same promo-pricing.js file that powers the product page tier table also handles cart tier pricing display. When a customer has items in the cart that qualify for volume pricing, the cart page/drawer can show:
- Strikethrough of the original price
- The volume-discounted unit price
- A savings label
This is handled by the CartTierHandler and the PromoSync Cart Tier Pricing embed block. See the cart integration documentation for setup details.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Block doesn’t appear | Product/variant has no part_price_array metafield | Sync the product via PromoSync to populate metafields |
| Table appears but doesn’t update on variant change | JS not loading or variant event not firing | Verify promo-pricing.js is loaded (check browser DevTools Network tab) |
| “Volume Pricing” heading shows raw translation key | Locale file missing | The block falls back to promo.tier_pricing.heading — add this key to your locale file or uncheck “Show heading” and add your own heading |
| Horizontal table doesn’t scroll | Container has overflow: hidden | Check parent elements for overflow restrictions in your theme CSS |
| Table style setting has no effect in horizontal mode | Expected behavior | Table style (Standard/Striped/Compact) only applies to the vertical table layout |
| Price shows as cents (e.g. “1250”) instead of “$12.50” | money filter issue or JS formatMoney not configured | Verify the theme’s money format is set correctly in Shopify admin |
| Block appears on non-product pages | Block placed in wrong template | The block requires a product object — only add it to product page templates |