Skip to content

Read the data in Liquid

Every key DiscountOS writes uses one app-owned namespace:

app--284350873601--discount_os

The number is the DiscountOS app’s ID. Put the namespace in one variable, or better in a theme setting, and use it everywhere:

{%- assign ns = 'app--284350873601--discount_os' -%}
PlaceWhat it holds
product.metafields[ns]Discounts that apply to this product. With Publish to collection products on, this includes discounts on the product’s collections.
collection.metafields[ns]Discounts that target this collection.
shop.metafields[ns]Every published discount, plus the sync state. Discounts that cover the whole store, the order or shipping live only here.

Each product and collection with at least one discount has these keys:

KeyTypeWhat it is
discountslist of discount entriesEvery published discount for this product or collection.
max_reward_percentdecimalThe best percentage off among discounts every shopper gets. 0 when there is none.
max_reward_centsintegerThe best fixed amount off among discounts every shopper gets, in the shop currency’s smallest unit (1500 is $15.00). 0 when there is none.
max_reward_discountone discount entryThe discount behind max_reward_percent. When no percentage discount qualifies, the discount behind max_reward_cents. Missing when neither has a winner.

When a product or collection has no discounts, all four keys are removed.

The shop also has two keys about the sync itself:

KeyTypeWhat it is
sync_pausedtrue / falsetrue while Live sync is off. The data is not being updated.
synced_atdate and timeWhen the data was last written.

Each item in discounts is a discount entry: a Shopify metaobject with one field per fact. Read every field with .value:

{%- assign offers = product.metafields[ns].discounts.value -%}
{%- for d in offers -%}
<p>{{ d.discount_title.value }} ({{ d.discount_type.value }}, {{ d.method.value }})</p>
{%- endfor -%}

Things to know:

  • The list is not sorted best first. Use max_reward_discount for the best offer.
  • Money is in the smallest unit of the shop currency. 1500 means $15.00. Shopify’s money filter divides by 100, which is right for two-decimal currencies. For a currency with no decimals (such as JPY) or three decimals (such as KWD), rescale first.
  • Decimals print with a point. reward_values and maximum_reward_value print as 10.0. Use | round for whole numbers.
  • Lists of products or collections cannot be read by position. In Liquid, d.reward_product_references.value[0] and .first return nothing. Loop over the list, or turn it into names with | map: 'title'.
  • A json field that is empty is still truthy. Check for the key you need, not the field.
  • Identify an entry by its handle. d.system.handle is discount- followed by the Shopify discount ID. It stays the same after a fresh write; the entry’s own ID does not.
{%- if shop.metafields[ns].sync_paused.value -%}
<p>Offer updates are paused. Prices at checkout are always current.</p>
{%- else -%}
<p>Offers as of {{ shop.metafields[ns].synced_at.value | date: '%b %-d, %H:%M' }}</p>
{%- endif -%}