When building a highly customized and visually engaging Shopify storefront, understanding the power of section schema and schema settings is crucial. Shopify’s schema provides a flexible, developer-friendly way to define sections and settings that allow merchants to personalize their store without any coding. By configuring schema in your theme code, you can create customizable sections with options for text, colors, images, and more, giving merchants the control to update content as their brand evolves. In this blog, we’ll explore the fundamentals of Shopify’s schema and schema settings, breaking down how they work and sharing tips to make the most of this feature in your store’s theme.
Prefer video?
Enjoy, otherwise read on!
What is a section schema?
When you create a new liquid file within the ‘sections’ directory, it will pre-populate with some code like so:
{% schema %}
{
"name": "Section name",
"settings": []
}
{% endschema %}
Shopify schema is a structured data format that defines the customizable settings and layout options for a section or block within a theme. Written in JSON format and placed between {% schema %}...{% endschema %}
tags, the schema allows developers to create a user-friendly interface in the Shopify admin where merchants can adjust various settings, text, images, colors, and other attributes without needing to edit code directly.
Put simply, everything between these tags is what allows users to make customizations in the theme editor / customizer like so:
Schema Content
This image shows a simple breakdown of the different attributes available to the section schema and what they do:
While these are all useful, I will focus mostly on the ‘settings’ in this article as it provides the most useful elements for allowing theme customization for the end user.
How to add schema settings
To allow the users in the theme customizer to enter data, we simply need to add values to the section schema. Here is a list of some of the settings we can use:
- checkbox
- number
- radio
- range
- select
- text
- textarea
Take a simple example by adding this to the schema:
{% schema %}
{
"name": "New Product Page",
"settings": [
{
"type": "text",
"id": "product-title",
"label": "Product Title"
}
}
{% endschema %}
This code declares a name for our section and adds a setting for a text input like so:
This allows the user to save a value of their choosing. However, just because a value has been added it doesn’t mean it will show up in the UI. We will see how to display these values next.
Display section settings
With values saved, we can display them using liquid syntax like so:
<h1 class="product-title">{{ section.settings.product-title }}</h1>
All you need to do is add the setting’s “id” to ‘section.settings.’ to display it in the UI.
Putting it all together
Now that we have a basic understanding of the schema, settings and how to display these values let’s create a new section. Create a file within the ‘sections’ directory and name it ‘new-product-section.liquid’. You can add the following styles at the top:
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
margin: 0;
padding: 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.product-grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
@media (min-width: 768px) {
.product-grid {
grid-template-columns: 1fr 1fr;
}
}
.product-image {
position: relative;
aspect-ratio: 1;
overflow: hidden;
border-radius: 8px;
}
.product-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.thumbnail-container {
display: flex;
gap: 10px;
overflow-x: auto;
padding: 10px 0;
}
.thumbnail {
width: 80px;
height: 80px;
border-radius: 4px;
border: 2px solid #e2e8f0;
overflow: hidden;
cursor: pointer;
}
.thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
}
.product-info {
display: flex;
flex-direction: column;
gap: 20px;
}
.product-title {
font-size: 24px;
font-weight: bold;
margin: 0;
}
.product-rating {
display: flex;
align-items: center;
gap: 5px;
}
.star {
color: #fbbf24;
}
.product-price {
font-size: 24px;
font-weight: bold;
}
.product-options select {
width: 100%;
padding: 8px;
margin-top: 5px;
border: 1px solid #e2e8f0;
border-radius: 4px;
}
.quantity-selector {
display: flex;
align-items: center;
border: 1px solid #e2e8f0;
border-radius: 4px;
overflow: hidden;
}
.quantity-selector button {
background: none;
border: none;
padding: 10px;
cursor: pointer;
}
.quantity-selector span {
padding: 0 20px;
}
.add-to-cart {
background-color: #2563eb;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.add-to-cart:hover {
background-color: #1d4ed8;
}
.product-details {
margin-top: 40px;
}
.details-section {
border: 1px solid #e2e8f0;
border-radius: 4px;
margin-bottom: 10px;
}
.details-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background-color: #f8fafc;
cursor: pointer;
}
.details-content {
padding: 15px;
display: none;
}
.details-content.active {
display: block;
}
</style>
Now we can add the following liquid code below. You’ll notice that we are referencing settings values for several different types of section settings. We also are using them in a couple of places for conditional statements in liquid and you’ll also see a peak of how to utilize section blocks!
<div class="container">
<div class="product-grid">
<div class="product-images">
<div class="product-image">
{{ section.settings.main-image | image_url: width: 400 | image_tag: alt: "Product main image" }}
</div>
</div>
<div class="product-info">
<div>
<h1 class="product-title">{{ section.settings.product-title }}</h1>
<div class="product-rating">
{% assign star_rating = section.settings.star-review %}
{% for i in (1..5) %}
{% if i <= star_rating %}
<span class="star">★</span>
{% else %}
<span class="star">☆</span>
{% endif %}
{% endfor %}
<span>(150 reviews)</span>
</div>
</div>
<p>{{ section.settings.product-description }}</p>
<div class="product-price">${{ section.settings.product-price }}</div>
<div class="product-options">
<label for="color">Color Selected:</label>
<select id="color">
<option>{{ section.settings.product-color }}</option>
</select>
</div>
<div style="display: flex; gap: 20px;">
<div class="quantity-selector">
<button id="decreaseQuantity">-</button>
<span id="quantity">1</span>
<button id="increaseQuantity">+</button>
</div>
<button {% unless section.settings.background == blank %}style="background: {{ section.settings.background }}"{% endunless %} class="add-to-cart">Add to Cart</button>
</div>
</div>
</div>
<div class="product-details">
<div class="details-section">
<div class="details-header">
<span>Description</span>
<span class="toggle">▼</span>
</div>
<div class="details-content">
<p>This ergonomic desk chair is designed with your comfort in mind...</p>
{% assign liquiProducts = section.settings.collection.products %}
{% for prod in liquiProducts %}
<a href="{{ prod.url }}"><p>{{ prod.title }}</p></a>
{% endfor %}
</div>
</div>
<div class="details-section">
<div class="details-header">
{% if section.settins.metafield == blank %}
<span>{{ section.settings.metafield }}</span>
{% else %}
<span>Features</span>
{% endif %}
<span class="toggle">▼</span>
</div>
<div class="details-content">
<p>Adjustable height, 360-degree swivel, lumbar support...</p>
</div>
</div>
<div class="details-section">
<div class="details-header">
<span>Specifications</span>
<span class="toggle">▼</span>
</div>
<div class="details-content">
{% for block in section.blocks %}
{%- case block.type -%}
{%- when "heading" -%}
<h1>{{ block.settings.heading }}</h1>
{% endcase %}
{% endfor %}
</div>
</div>
</div>
</div>
Now finally, let’s add the most important part… THE SCHEMA! After adding these values we can navigate to the theme editor / customizer and add some values!
{% schema %}
{
"name": "New Product Page",
"settings": [
{
"type": "image_picker",
"id": "main-image",
"label": "Main Image"
},
{
"type": "text",
"id": "product-title",
"label": "Product Title"
},
{
"type": "range",
"id": "star-review",
"min": 1,
"max": 5,
"step": 1,
"label": "# of stars",
"default": 4
},
{
"type": "textarea",
"id": "product-description",
"label": "Product Description"
},
{
"type": "number",
"id": "product-price",
"label": "Product Price"
},
{
"type": "select",
"id": "product-color",
"label": "Product Color",
"options": [
{
"value": "Black",
"label": "Black"
},
{
"value": "White",
"label": "White"
},
{
"value": "Grey",
"label": "Grey"
}
],
"default": "Black"
},
{
"type": "color_background",
"id": "background",
"label": "Background",
"default": "linear-gradient(#ffffff, #000000)"
},
{
"type": "collection",
"id": "collection",
"label": "Collection"
},
{
"type": "text",
"id": "metafield",
"label": "Use a Metafield Here",
"default": "Features"
}
],
"blocks": [
{
"type": "heading",
"name": "Custom Block",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Hello, world!"
}
]
}
],
"presets": [
{
"name": "New Product Page"
}
]
}
{% endschema %}
Using metafields in theme settings
One thing I wanted to call out was the ability to use metafields in the schema settings. If we look at the schema setting for ‘product-title’ in the customizer you’ll see an icon above and right of it:
If you click this icon, you will have the ability to connect it to a dynamic metafield source!
Now on any given product page, the metafield value that is saved will be saved and display in this schema setting!
Conclusion
Shopify’s section schema and schema settings are essential tools for building adaptable, merchant-friendly themes. By using schema thoughtfully, developers can empower store owners to make easy, impactful changes that keep their storefront fresh and aligned with their brand’s identity. With these customizable settings in place, Shopify themes not only become more versatile but also create a smoother workflow for store management. Whether you’re a developer aiming to create a flexible theme or a merchant looking to refine your store’s look, mastering schema settings opens up a world of possibilities to bring your vision to life.