Skip to content

How rendering works

Every storefront page goes through the same steps. Knowing them tells you which file to change.

1. The request picks a store, a theme and a template

Section titled “1. The request picks a store, a theme and a template”

The domain picks the store. The store’s live theme draws the page, unless a staff member is previewing another theme or editing in the visual editor.

The URL picks the page type and its template:

URL Page type Template
/ index templates/index.json
/products/<handle> product templates/product.json
/collections/<handle> collection templates/collection.json
/collections list-collections templates/list-collections.json
/pages/<handle> page templates/page.json
/blogs/<blog>, /blogs/<blog>/<article> blog, article templates/blog.json, templates/article.json
/search search templates/search.json
/cart cart templates/cart.json
/custom/<name> custom_page custom_pages/<name>.liquid
/password password templates/password.json
anything else 404 templates/404.json

A product, collection or page can use an alternate template: templates/product.gift.json is used by products whose template is set to “gift” in admin. Products also take ?view=gift, which is how quick-view popups load a lighter template.

Pages in a language other than the store’s primary one have a prefix: /ar/products/…. The prefix is handled for you: routes, url properties and the url setting all include it.

A JSON template is data the visual editor writes: which sections the page has, their settings and blocks, and their order.

templates/product.json
{
"sections": {
"main": { "type": "main-product", "blocks": { "title": { "type": "product-title" } }, "block_order": ["title"] },
"related": { "type": "related-products", "settings": { "limit": 4 } }
},
"order": ["main", "related"]
}

Each entry renders sections/<type>.liquid with a section object holding its settings and blocks, wrapped in an element:

<section id="shopify-section-template--main" class="shopify-section">…</section>

A Liquid template (templates/page.faq.liquid) is rendered as is, without sections the merchant can arrange.

A section loops over section.blocks, or outputs its theme blocks with {% content_for 'blocks' %}. Blocks can hold blocks, up to 8 levels deep.

The template’s output becomes content_for_layout inside layout/theme.liquid (or the layout the template names). The layout draws the <head>, renders the header and footer section groups with {% sections 'header-group' %}, and must output:

  • {{ content_for_header }} in <head>: meta tags, hreflang links, analytics and the editor bridge.
  • {{ content_for_layout }} in <body>.

Pages of the live theme are cached and refreshed when the merchant changes something that appears on them. Previews and the visual editor are never cached.

A Liquid error doesn’t break the page. In previews and the editor the error is shown where it happened (Liquid error (sections/hero.liquid): …); on the live store it becomes an HTML comment. The code editor won’t save a syntax error to the live theme.

A page also has limits: 2 seconds to render, 10,000 iterations per loop and 200 sections.

Was this page helpful?