CTX is the data your sections render from. Every hosted page is assembled from sections, and each section declares the objects it reads — ctx.product, ctx.cart, ctx.localization — in its schema's ctx_needs. The host loads exactly what you declared before your template runs; reading an undeclared object is a hard error at render, so a section's data footprint is always visible in its schema.
Use CTX as your only data source. Every object is already shaped for storefront display — localized, market-priced, and identity-safe — so your template renders what it reads without knowing how the platform resolved it. Objects are lowercase snake_case under ctx.
Theme-facing CTX#
Object |
What it holds |
|---|---|
ctx.shop |
Storefront-safe shop identity, currently name and primary_domain. |
ctx.menus |
Published menu summaries, with full menu trees loaded only when a template asks for a specific menu handle. |
ctx.localization |
Active locale and baseline/no-prefix locale. |
ctx.localization_prompt |
Whether the storefront may show a country/language prompt for the current visitor. |
ctx.restock_notifications |
Notify Me capture rules for the current product and visitor: enabled state, mode, login requirement, and email-input requirement. |
ctx.product |
The current product page product, including media, options, selected variant state, price, availability, and Notify Me eligibility. |
ctx.cart |
The current visitor cart: item counts, currency, subtotal when available, and enriched line items when the template requests them. |
ctx.wishlist |
The visitor's wishlist: enabled, login_required, and item_count always; enriched items (product, variant, availability, purchase state, Notify Me eligibility) when the template requests them. |
ctx.reviews |
Product-page reviews (declare |
ctx.consent |
The visitor's cookie-consent state for the banner: required (this visitor should be asked), given, and the granted categories. Pair it with the consent_give and consent_withdraw actions — the categories are platform-defined, and the visitor chooses. |
ctx.forms |
Form input constraints for hosted actions (comment, contact, newsletter, review): per field, required and max_length (rune count), plus min_length and max_images where the store's review settings supply them. Bind these to input attributes instead of hardcoding numbers — the platform validates the same values on submit. Declare the forms context need to receive it. |
Prices come to you as money values — objects carrying amount and currency_code — ready for the money host filter. There is no separate currency or market object to consult: the resolved currency travels inside every price, and the active locale is in ctx.localization. Products also carry rating ({average, count}) on the product page and on listing cards when the store has reviews enabled — computed from approved reviews only.
Route and action objects#
Some objects appear only on the routes that need them. Product listings expose ctx.products, ctx.collection, and ctx.category. Content routes expose ctx.page or ctx.policy. Blog routes expose ctx.blog_post, ctx.blog, and ctx.blog_category — ctx.blog is the routed listing with items and ready-made pagination, scoped by the category route or the ?tag= query. Vendor, brand, collection-list, and category-list routes expose ctx.vendor, ctx.brand, or the generic ctx.list. Three reads work on any page, no route required: blog_recent gives any section the latest post cards, pages gives the published-page index as {id, title, slug, url} (A to Z, capped at 100), and policies gives every published policy as {id, type, title, slug, url} ordered by type. All carry permalink-correct URLs — footers typically render policies as the legal-links row.
Account and authentication surfaces additionally read ctx.customer, ctx.customer_settings, ctx.form_error, ctx.auth_notice, ctx.auth_form, and ctx.csrf_token. Each is shaped for display and form behavior — a customer object never carries more than the storefront should show.
Storefront kinds#
ctx.storefront.kind is storefront for a normal storefront and b2b for a B2B storefront. B2B renders the same sections with B2B context — see the B2B pages for what changes.
Blog objects#
On the blog post route, blog_post also carries the comments themselves: comments is the first page of approved comments — each {id, author_name, content, created_at} — and comments_total is the full approved count. comments_enabled tells you whether to render the comments block at all, and comments_login_required whether to ask the visitor to sign in instead of showing the guest fields. Pass ?comments_page=2 on the post URL for further pages. Submissions go through the comment_submit form; when the store reviews comments first, the response says so, and the new comment appears once approved.
Blog post cards (blog.items and blog_recent) carry title, slug, url, excerpt, featured_image.url, author_name, published_at, comment_count, and categories[] and tags[] — each ref with name, slug, and url (category refs link to the category page; tag refs to the tag-filtered blog list). The full blog_post adds content (sanitized HTML), seo_title, and seo_description. Cards and posts also carry an author object — {name, bio, avatar_url} — backed by the store's author entity when the post references one, else the plain author_name with empty bio and avatar.
filters (listing routes)#
On listing routes (shop, category, collection) the context carries filters beside products: items[] is the store's enabled filter definitions in merchant order, each with key, label (localized), display_type and values[] — {key, label, count, selected, url}. Counts are LIVE and disjunctive (selecting a value keeps its siblings countable); url toggles that value on the current URL (repeated ?filter.
search (search route)#
On the search route (the configurable search permalink + ?q=) the context carries search: query, placeholder (the merchant's configured prompt), totals per group, and results — products as standard listing cards with pagination (channel-gated, priced, and ?filter.* selections compose with the query), plus content groups (pages, policies, blog_posts, blog_categories, ...) as {title, excerpt, url} cards, limited to the merchant's enabled result types. Disabled search renders the themed 404. ?q= responses are noindexed.