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

  1. In your Shopify admin, go to Online Store > Themes > Customize
  2. Navigate to a Product page template
  3. Click Add block > search for PromoSync Tier Pricing
  4. Configure the settings (see below)
  5. Drag the block to your preferred position (typically below the price or above Add to Cart)
  6. Save

No theme code changes required.


Settings Reference

SettingIDTypeDefaultNotes
Layoutlayoutselecttabletable (vertical) or horizontal (two-row)
Show headingshow_headercheckboxtrueDisplays “Volume Pricing” heading above the table
Show unit columnshow_unitcheckboxtrueTable layout: adds a Unit column. Horizontal layout: shows unit as suffix on heading, e.g. “Volume Pricing (EA)“
Unit labelunit_labeltextEAThe unit label text (e.g. “EA”, “PC”, “Each”)
Table styletable_styleselectstandardstandard, 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:

StyleDescription
StandardClean borders, no row shading
StripedAlternating row background for readability
CompactReduced 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 tier
  • price — 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

  1. A hidden <script> tag (tier-pricing-data snippet) renders all variant price break data as JSON, keyed by variant ID
  2. The JavaScript ProductTierHandler listens for Shopify’s variant:change event
  3. 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)
  4. 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-breaks function 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

ClassElementLayout
.promo-tier-pricingOuter containerBoth
.promo-tier-pricing__heading”Volume Pricing” headingBoth
.promo-tier-pricing__table<table> elementTable
.promo-tier-pricing__table--stripedStriped modifierTable
.promo-tier-pricing__table--compactCompact modifierTable
.promo-tier-pricing--horizontalOuter container modifierHorizontal
.promo-tier-pricing__hscrollScroll wrapperHorizontal
.promo-tier-pricing__htable<table> elementHorizontal
.promo-tier-pricing__unit-suffix”(EA)” suffix on headingHorizontal

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

SymptomCauseFix
Block doesn’t appearProduct/variant has no part_price_array metafieldSync the product via PromoSync to populate metafields
Table appears but doesn’t update on variant changeJS not loading or variant event not firingVerify promo-pricing.js is loaded (check browser DevTools Network tab)
“Volume Pricing” heading shows raw translation keyLocale file missingThe 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 scrollContainer has overflow: hiddenCheck parent elements for overflow restrictions in your theme CSS
Table style setting has no effect in horizontal modeExpected behaviorTable 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 configuredVerify the theme’s money format is set correctly in Shopify admin
Block appears on non-product pagesBlock placed in wrong templateThe block requires a product object — only add it to product page templates