ShopifyJune 10, 20267 min read

Building Custom Shopify Sections with Liquid

A deep dive into Liquid templating and how to build flexible, schema-driven sections that give clients full control without touching code.

JA

Jacob Almogela

Full Stack Developer

Building Custom Shopify Sections with Liquid

One of the most valuable things you can deliver to a Shopify client is a section they can edit themselves without ever touching code. Shopify's Liquid templating language makes this possible through schema-driven sections. You define what settings exist and the Theme Customizer handles the UI automatically.

What Is a Shopify Section?

A section is a reusable Liquid template that lives in the /sections folder. It combines HTML markup with a schema block that tells Shopify which settings to expose in the Theme Customizer. Settings can be text, images, colors, URLs, select dropdowns, and more. All of this without writing a single line of custom admin UI.

liquid
<div class="testimonials" style="background: {{ section.settings.bg_color }}">
  <h2>{{ section.settings.heading }}</h2>

  {% for block in section.blocks %}
    <blockquote {{ block.shopify_attributes }}>
      <p>{{ block.settings.quote }}</p>
      <cite>{{ block.settings.author }}</cite>
    </blockquote>
  {% endfor %}
</div>

The {% schema %} Block

The schema block is JSON embedded at the bottom of your .liquid file. It has two main areas: settings for section-level controls, and blocks for repeatable child elements like testimonial cards or feature rows. The Theme Customizer reads this JSON and generates the entire UI automatically.

json
{% schema %}
{
  "name": "Testimonials",
  "settings": [
    {
      "type": "text",
      "id": "heading",
      "label": "Section Heading",
      "default": "What Our Clients Say"
    },
    {
      "type": "color",
      "id": "bg_color",
      "label": "Background Color",
      "default": "#f5f5f0"
    }
  ],
  "blocks": [
    {
      "type": "testimonial",
      "name": "Testimonial",
      "settings": [
        { "type": "textarea", "id": "quote",  "label": "Quote"        },
        { "type": "text",     "id": "author", "label": "Author Name"  },
        { "type": "image_picker", "id": "avatar", "label": "Avatar"   }
      ]
    }
  ],
  "presets": [{ "name": "Testimonials" }]
}
{% endschema %}
TIP

Always include a presets array with at least one entry. Without it, merchants can't add your section from the Add Section panel in the Theme Customizer.

Section Settings vs Block Settings

Section settings apply once to the whole section like the heading, background color, or number of columns. Block settings repeat per item. Each testimonial, feature card, or FAQ entry gets its own set of controls. Blocks can be reordered and duplicated by the merchant, which makes them perfect for any list-like content.

  • section.settings.heading — accesses a section-level setting
  • block.settings.quote — accesses a setting on the current block in a for loop
  • {{ block.shopify_attributes }} — required attribute for drag-to-reorder in the editor
  • section.blocks.size — total count of blocks, useful for conditional logic

Adding JavaScript Interactivity

For sliders, tabs, or accordions, you attach a small JavaScript file to the section using the schema's javascript key, or just inline a script tag. Shopify automatically deduplicates section JS when the same section appears multiple times on a page.

liquid
{% javascript %}
  class TestimonialsSlider extends HTMLElement {
    connectedCallback() {
      this.currentIndex = 0;
      this.slides = this.querySelectorAll('blockquote');
      this.querySelector('[data-next]')
        .addEventListener('click', () => this.advance());
    }
    advance() {
      this.slides[this.currentIndex].hidden = true;
      this.currentIndex = (this.currentIndex + 1) % this.slides.length;
      this.slides[this.currentIndex].hidden = false;
    }
  }
  customElements.define('testimonials-slider', TestimonialsSlider);
{% endjavascript %}

Key Takeaways

  • Sections live in /sections and combine Liquid markup with a {% schema %} JSON block
  • Settings expose section-level controls; blocks expose repeatable per-item controls
  • Always add {{ block.shopify_attributes }} inside your block loop for editor drag-and-drop
  • Use Web Components (customElements.define) inside {% javascript %} for clean, scoped JS
  • Presets make sections discoverable — don't skip them

A well built Liquid section is one of the highest leverage things you can deliver on a Shopify project. The client gets full control through a friendly UI and you never get a support ticket asking how to change a heading. That is the goal.

#Shopify#Liquid#eCommerce#JavaScript
© 2026 Jacob AlmogelaBuilt with Next.js + Framer Motion