SSR Live Pricing
Eliminate the flash of original prices by rendering Hype discount prices server-side in your Shopify theme Liquid templates. Requires editing your theme price snippet.
Overview
Hype can update prices client-side after the page loads using the Live Storefront Pricing schema. While this works well, it means customers briefly see the original price before JavaScript replaces it with the discounted price. SSR Live Pricing eliminates that flash by rendering the correct discounted price at the server level, before the HTML reaches the browser.
This feature works by writing the active campaign's discount rules to a shop-level metafield (shop.metafields.hype.discount_rates). Your theme's price snippet reads this metafield and calculates the discounted price during Liquid rendering.
When to use this
- You want discounted prices visible immediately on page load with zero flash
- You need discounted prices to appear in the initial HTML for SEO
- Your campaign uses the Automatic + Multi Product Discount type
Requirements
- An active campaign with Automatic discount mode and Multi Product Discount type
- Dynamic Pricing toggled ON for that campaign
- A one-time theme code edit (detailed below)
How it works
- When you toggle Dynamic Pricing ON for an eligible campaign, Hype writes the campaign's discount rules to
shop.metafields.hype.discount_rates - When toggled OFF, the metafield is cleared
- Only one automatic campaign's rates are stored at a time
- Your theme's price snippet reads this metafield and matches the current product against the discount rules
- If a match is found, the original price becomes the compare-at (strikethrough) price and the discounted price is rendered as the sale price
Metafield shape
| Field | Description |
|---|---|
campaignId |
The campaign this data belongs to |
discounts[] |
Array of discount rules from the campaign |
type |
"percentage" or "amount" |
value |
For percentage: a number (e.g. 20 means 20% off). For amount: an object keyed by market ID, with "primary" as the default key |
allProducts |
If true, this rule applies to all products |
productIds |
Numeric product IDs that match this rule |
collectionIds |
Numeric collection IDs that match this rule |
excludedProductIds |
Numeric product IDs excluded from this rule |
excludedCollectionIds |
Numeric collection IDs excluded from this rule |
All IDs are numeric strings stripped from Shopify GIDs (e.g. gid://shopify/Product/123 becomes "123").
Theme integration
The integration requires editing your theme's price snippet — the Liquid file responsible for rendering product prices across your storefront (product pages, collection pages, product cards, etc.).
Step 1: Locate your price snippet
Find the snippet in your theme that renders product prices. Common locations:
| Theme | File |
|---|---|
| Dawn | snippets/price.liquid |
| Prestige | snippets/product-price.liquid |
| Impulse | snippets/price.liquid |
Look for the file that contains your theme's price CSS classes and outputs product.price or variant.price with the money filter.
Step 2: Add the Hype SSR code
Insert the following Liquid code after the existing price and compare_at_price variable assignments, but before the money_price formatting lines (the | money filter calls).
The code does three things:
- Reads the metafield and matches the current product against discount rules
- Derives a currency exchange rate for multi-market amount discounts
- Overrides
priceandcompare_at_priceso the rest of your theme's existing price markup works without changes
comment
Hype SSR Discount: check shop metafield for active discount rules
and override price/compare_at_price if the product matches a rule.
endcomment
assign hype_data = shop.metafields.hype.discount_rates.value
assign hype_matched_discount = nil
if hype_data and hype_data.discounts.size > 0
assign pid_string = product.id | append: ''
for hype_discount in hype_data.discounts
assign hype_is_excluded = false
for excluded_pid in hype_discount.excludedProductIds
if pid_string == excluded_pid
assign hype_is_excluded = true
break
endif
endfor
unless hype_is_excluded
for excluded_cid in hype_discount.excludedCollectionIds
for col in product.collections
assign col_id_string = col.id | append: ''
if col_id_string == excluded_cid
assign hype_is_excluded = true
break
endif
endfor
if hype_is_excluded
break
endif
endfor
endunless
if hype_is_excluded
continue
endif
if hype_discount.allProducts
assign hype_matched_discount = hype_discount
break
endif
for pid in hype_discount.productIds
if pid_string == pid
assign hype_matched_discount = hype_discount
break
endif
endfor
if hype_matched_discount
break
endif
for cid in hype_discount.collectionIds
for col in product.collections
assign col_id_string = col.id | append: ''
if col_id_string == cid
assign hype_matched_discount = hype_discount
break
endif
endfor
if hype_matched_discount
break
endif
endfor
endfor
endif
comment
Derive the currency exchange rate from a money-type metafield.
The metafield stores 1000000 (in cents) in the shop's primary currency.
Shopify auto-converts it to the presentment currency when read in Liquid.
Dividing the converted value by the known base gives us the rate.
endcomment
assign hype_currency_base = shop.metafields.custom.hype_money_primary.value | times: 1.00
assign hype_exchange_rate = hype_currency_base | divided_by: 1000000.00
if hype_matched_discount
assign compare_at_price = price
if hype_matched_discount.type == 'percentage'
assign hype_multiplier = 100 | minus: hype_matched_discount.value
assign price = price | times: hype_multiplier | divided_by: 100
else
assign hype_market_id = localization.market.id | append: ''
assign hype_discount_amount = hype_matched_discount.value[hype_market_id]
if hype_discount_amount
assign hype_discount_cents = hype_discount_amount | times: 100
else
assign hype_discount_cents = hype_matched_discount.value.primary | times: hype_exchange_rate | times: 100
endif
assign price = price | minus: hype_discount_cents | at_least: 0
endif
endif
Step 3: Verify placement
After adding the code, your price snippet's variable flow should look like this:
1. Theme assigns: price, compare_at_price (from product/variant)
2. --> Hype SSR code goes here <--
3. Theme assigns: money_price = price | money
4. Theme renders: HTML with money_price, compare_at_price
The Hype code overrides price and compare_at_price before they are formatted, so the theme's existing sale/regular price markup, CSS classes (like --on-sale), and strikethrough styling all work automatically.
Multi-market currency handling
Amount-type discounts store values in the shop's primary currency by default, with optional market-specific overrides. The SSR code handles this with a two-step fallback:
- Market-specific amount exists — use it directly (already in the correct currency)
- No market-specific amount — convert the primary market's amount using a derived exchange rate
How the exchange rate is derived
Shopify does not expose currency conversion rates in Liquid. To work around this, Hype creates a metafield (custom.hype_money_primary) with type money and a known base value of 1000000 (cents) in the shop's primary currency.
When Liquid reads a money-type metafield, Shopify automatically converts it to the visitor's presentment currency. By dividing the converted value by the known base, we derive the exchange rate:
assign hype_currency_base = shop.metafields.custom.hype_money_primary.value | times: 1.00
assign hype_exchange_rate = hype_currency_base | divided_by: 1000000.00
For example, if the shop currency is USD and a visitor is browsing in EUR (rate 0.92):
- Shopify converts
1000000to920000 920000 / 1000000 = 0.92- A $5 USD discount becomes
5 * 0.92 = 4.60EUR
Note: The derived rate includes Shopify's currency conversion markup (typically ~2%), which is correct behavior —
product.pricein Liquid includes the same markup, so the discount amount should too.
Percentage-type discounts are not affected by currency — 20% off is 20% off regardless of currency.
Product matching logic
A product matches a discount rule if:
allProductsistrue, OR- The product's ID is in
productIds, OR - The product belongs to a collection whose ID is in
collectionIds
AND the product is NOT in excludedProductIds or a collection in excludedCollectionIds.
When multiple discount rules exist, the first match wins.
Important notes
product.priceis in cents. For example,2000= $20.00. Amount discount values in the metafield are in base currency units (e.g.5= $5.00), so they are multiplied by 100 before subtracting.product.idandcollection.idare numeric in Liquid. The code uses| append: ''to coerce them to strings for comparison with the JSON string values in the metafield.product.collectionsis available everywhere — product pages, collection pages, product cards, search results, and cart. The SSR pricing works globally, not just on the product detail page.- Only one campaign at a time. The dynamic pricing toggle enforces that only one automatic campaign's rates are stored in the metafield. Enabling it on a new campaign disables it on the previous one.
Data freshness
The metafield is synced when the merchant toggles dynamic pricing ON. If you later edit the campaign's discount rules without re-toggling, the metafield will not auto-update. Toggle dynamic pricing OFF and ON again to re-sync.
Relationship to client-side Live Storefront Pricing
SSR Live Pricing and the existing Live Storefront Pricing (client-side schema) serve the same goal but work differently:
| SSR Live Pricing | Client-Side Live Pricing | |
|---|---|---|
| How it works | Liquid renders prices server-side | JavaScript replaces prices after page load |
| Flash of original price | No | Yes (brief) |
| Requires theme code edit | Yes | No (schema config only) |
| SEO benefit | Yes (prices in initial HTML) | No |
| Supported discount types | Multi Product Discount (Automatic) | All campaign types |
You can use both together. The SSR code handles the initial render, and the client-side schema can handle edge cases or other campaign types.