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

  1. When you toggle Dynamic Pricing ON for an eligible campaign, Hype writes the campaign's discount rules to shop.metafields.hype.discount_rates
  2. When toggled OFF, the metafield is cleared
  3. Only one automatic campaign's rates are stored at a time
  4. Your theme's price snippet reads this metafield and matches the current product against the discount rules
  5. 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:

  1. Reads the metafield and matches the current product against discount rules
  2. Derives a currency exchange rate for multi-market amount discounts
  3. Overrides price and compare_at_price so 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:

  1. Market-specific amount exists — use it directly (already in the correct currency)
  2. 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 1000000 to 920000
  • 920000 / 1000000 = 0.92
  • A $5 USD discount becomes 5 * 0.92 = 4.60 EUR

Note: The derived rate includes Shopify's currency conversion markup (typically ~2%), which is correct behavior — product.price in 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:

  1. allProducts is true, OR
  2. The product's ID is in productIds, OR
  3. 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.price is 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.id and collection.id are numeric in Liquid. The code uses | append: '' to coerce them to strings for comparison with the JSON string values in the metafield.
  • product.collections is 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.