Skip to content

Section Schema and Settings

In the anatomy of a theme, sections were described as self-contained Liquid files that control both the HTML output and the settings that appear in the Theme Editor. The part that handles the settings is a block called {% schema %}, and it sits at the bottom of every section file.

If you’ve opened any section in Dawn and found yourself confronted with hundreds of lines of JSON at the bottom and no idea what it’s doing, this is the page that explains it.


Every section file ends with a {% schema %} block. When the Theme Editor loads, Shopify reads that schema and generates the settings panel on the right side of the screen automatically. The panel you see when you click on a section, the one with fields for button text, image height, background colour, is built entirely from what’s in the schema.

The Liquid above the schema handles what the customer sees. The schema handles what the merchant can configure. The two connect through setting IDs, which you reference in your Liquid using section.settings.your_id.

One thing that catches people out: the schema block itself doesn’t output anything to the page. It’s instructions, not content.


Here’s a section with a single text setting for a heading:

<h2>{{ section.settings.heading }}</h2>
{% schema %}
{
"name": "Featured Text",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Welcome to our store"
}
]
}
{% endschema %}

The name at the top is the section’s display name in the Theme Editor sidebar. The label is what appears next to the input field. The id is what you reference in your Liquid and it needs to match exactly, so keep them lowercase with underscores and don’t change them once a theme is live (changing an ID orphans any value a merchant has already saved against it).

The default sets the initial value before the merchant has changed anything. Without it the field starts empty.


There are more setting types than you’ll need day to day. These are the ones that come up constantly:

text A single-line text input. Good for headings, labels, and button text.

textarea Multi-line text. Good for short paragraphs or descriptions where the merchant needs a bit more room.

image_picker Lets the merchant select an image from their store’s file library. Returns an image object you can use with the image_url filter.

select A dropdown with predefined options you define. Good for layout choices, alignment options, or anything where the merchant should pick from a fixed list rather than type freely.

{% schema %}
{
"name": "Image Banner",
"settings": [
{
"type": "select",
"id": "text_alignment",
"label": "Text alignment",
"options": [
{ "value": "left", "label": "Left" },
{ "value": "center", "label": "Centre" },
{ "value": "right", "label": "Right" }
],
"default": "center"
}
]
}
{% endschema %}

checkbox A true/false toggle. Good for showing or hiding an element, or switching between two behaviours.

range A slider between a minimum and maximum value you set. Good for font sizes, padding values, or controlling how many items appear in a grid.

color A colour picker. Returns a hex value you can use directly in CSS.


Some sections need to support a variable number of repeating items: a list of testimonials, a row of logos, a set of feature cards. Blocks handle this.

A block defines a repeatable unit with its own settings. The merchant can add, remove, and reorder blocks in the Theme Editor up to the limit you set with max_blocks. In your Liquid, you loop over them with {% for block in section.blocks %}.

{% for block in section.blocks %}
<div class="testimonial" {{ block.shopify_attributes }}>
<p>{{ block.settings.quote }}</p>
<p>{{ block.settings.author }}</p>
</div>
{% endfor %}
{% schema %}
{
"name": "Testimonials",
"max_blocks": 6,
"blocks": [
{
"type": "testimonial",
"name": "Testimonial",
"settings": [
{
"type": "textarea",
"id": "quote",
"label": "Quote"
},
{
"type": "text",
"id": "author",
"label": "Author name"
}
]
}
]
}
{% endschema %}

The general rule on when to make something a setting versus hardcoding it: if a merchant might reasonably want to change it, make it a setting. If it’s structural to how the section works, hardcode it. A heading is a setting. The fact that the section uses a two-column grid probably isn’t.

Schema is JSON inside a Liquid tag, which means malformed JSON will stop the section from loading in the Theme Editor. shopify theme check will catch schema errors before you push, which is another good reason to run it as a habit before every push.

For testing schema changes, the workflow is the same as any other local edit: make the change, open the preview URL in your browser, click into the Theme Editor on that URL, and you’ll see the updated settings panel immediately without pushing anything.