Data
Data serializers
Turning Shopify objects into JSON React can use.
snippets/json--*.liquid turn Shopify objects into JSON React can use. Each one
outputs a bare value, or null when its subject is blank, so they compose.
json--section | The standard payload: settings, blocks, plus opt-in resources |
json--product | Product, with variants / media / selling_plans toggles |
json--variant, json--product-variants | Variants |
json--selling-plan, json--selling-plan-groups, json--selling-plan-allocations | Subscriptions |
json--collection, json--article, json--cart, json--line-item | Resources |
json--filters, json--paginate | Collection filtering and paging |
json--image, json--media | Real CDN URLs, srcset, focal point |
json--customer, json--link-list, json--shop, json--routes | The rest |
Opting into resources
1{% render 'react-section', component: 'main-product', section: section,2 with_product: product %}The with_ prefix is deliberate. {% render %} gets a clean scope, but global
objects still reach it — so a plain product parameter would silently populate
on product templates and nowhere else. Prefixing means a resource is included
only when you asked for it, and payload size stays something you control.
| Parameter | |
|---|---|
with_product, with_collection, with_article | Resources |
with_cart, with_customer, with_menu | The rest |
product_variants, product_media, product_selling_plans | Default true |
collection_limit | Products to include. Omit for none |
image_width | Width for base image src values |
Watch the size
The payload is inline in the HTML on every page load.
| 3-variant product | ~12 KB |
| Same, with subscriptions | ~19 KB |
| Each extra variant | ~1.5 KB |
| Each subscription allocation | ~650 bytes |
A 50-variant product on a 4-plan group is over 100 KB of HTML. For grids, pass
product_variants: false, product_media: false and fetch the rest from
{product.url}.js when you actually need it.
Money
Integers are in the shop's minor unit; *_formatted is the display string.
Do maths on the integer, render the string. Never re-format cents in JavaScript — currencies with non-decimal subunits break, and a store selling in JPY or KWD will be wrong in a way nobody notices until a customer complains.
1const total = lines.reduce((sum, line) => sum + line.final_line_price, 0)2<span>{cart.total_price_formatted}</span>formatMoney from @/framework is available where you genuinely have to build
a string client-side — it uses Intl.NumberFormat with the shop's currency.
Subscriptions
Shopify splits this in two, and so do the snippets:
selling_plan_groupson the product — the catalogue: names, picker options, discounts as rules.selling_plan_allocationson each variant — the resolved prices.
Join on selling plan id and render the allocation's price. Don't apply
price_adjustments yourself:
1const price = variant.selling_plan_allocations2 .find((a) => a.selling_plan_id === plan.id)3 .price_formatted // "$21.25", discount already appliedEmpty arrays on stores without subscriptions, so it costs nothing until used.