Di 23 Templates kita lihat template JSON cuma daftar section. Sekarang kita bikin section-nya: komponen yang paling sering kamu tulis sebagai developer theme.

Section itu file Liquid yang bikin modul konten yang bisa dipakai ulang dan dikustomisasi merchant. Contoh: section Image with text yang nampilin gambar dan teks berdampingan, dengan opsi buat merchant milih gambarnya, ngisi teksnya, dan ngatur urutannya.

Section bisa ditambahin ke halaman secara dinamis lewat template JSON atau section group, jadi merchant bebas nyusun layout halaman. Section yang ada di template JSON atau section group juga bisa nampung app block, biar merchant nambahin konten app tanpa ngedit kode. Batasnya: 25 section per template atau section group, 50 block per section.

Bawaannya section tersedia buat semua template dan section group. Kamu bisa batasi lewat schema.

Lokasi

Di folder sections/:

└── theme
  ...
  ├── templates
  ├── sections
  ...

Tiga Isi Section

Satu file section punya tiga jenis isi:

1. Konten Utama

HTML dan Liquid apapun. Section punya akses ke semua object global, tag, dan filter kaya file Liquid lain, plus dua object khusus:

  1. section, properti dan nilai setting section ini. Dari 17 Objects Lainnya > section.
  2. block, properti dan nilai setting satu block. Dari 17 Objects Lainnya > block.

Aturan scope-nya mirip snippet: variabel yang dibikin di luar section gak bisa diakses di dalamnya (selain object global), dan object section, block, serta variabel yang dibikin di dalam section gak bisa diakses di luar. Satu-satunya pengecualian: snippet yang dirender dari dalam section bisa akses section dan block.

2. Aset

Section bisa ngebundel JavaScript dan CSS-nya sendiri pakai tag {% javascript %} dan {% stylesheet %} dari 12 Tags Khusus Theme > javascript dan stylesheet. Bahasan cara load-nya di 54 Best Practices Umum.

3. Schema (Wajib)

Tag {% schema %} yang nentuin atribut dan setting section. Ini satu-satunya yang wajib. Dibahas panjang di bawah.

Tiga Cara Render Section

  1. Dirujuk di template JSON atau section group. Ini cara utama, merchant bisa ngatur.
  2. Dirender statis pakai tag section dari 12 Tags Khusus Theme > section.
  3. Lewat Section Rendering API, buat update dinamis tanpa reload. Bahasannya di 51 Ajax API dan Section Rendering API.

Render Statis

Hindari sebisa mungkin. Section statis gak bisa dihapus atau diurutin merchant. Tapi kalau emang perlu, misalnya di template Liquid lama:

{% section 'featured-product' %}

Ada satu aturan yang sering bikin bingung: section statis bisa dirender di banyak file, tapi cuma ada satu instance-nya. Ubah setting-nya di satu tempat, semua tempat lain ikut berubah. Beda sama section di template JSON yang tiap instance punya setting sendiri.

❌ berisiko, dua halaman pakai section statis yang sama, setting-nya jadi sharing

{% comment %} di dua template Liquid berbeda {% endcomment %}
{% section 'promo-banner' %}

✅ lebih baik, rujuk di template JSON masing-masing, tiap instance punya setting sendiri

{
  "sections": {
    "promo": { "type": "promo-banner", "settings": { "text": "Diskon 20%" } }
  },
  "order": ["promo"]
}

Integrasi dengan Theme Editor

Waktu merchant ngutak-atik section dan block di theme editor, HTML-nya ditambah, dihapus, atau dirender ulang langsung di DOM tanpa reload halaman. Akibatnya, JavaScript yang jalan waktu halaman dimuat gak jalan lagi. Slider yang diinisialisasi waktu load bakal rusak begitu merchant nambah slide baru.

Dua hal yang wajib dijaga:

  1. Kode JavaScript harus bisa diinisialisasi ulang waktu section atau block ditambah atau berubah, pakai event dari theme editor.
  2. Waktu section atau block dipilih, dia harus jadi dan tetap kelihatan. Section slideshow harus scroll ke tampilan waktu dipilih, geser ke slide yang dipilih, dan berhenti di situ selama masih dipilih. Kalau nggak, merchant ngedit slide 3 tapi yang kelihatan slide 1.

Buat ngenalin aksi theme editor (pilih section, pilih block, urutin ulang), pakai event JavaScript yang ditembak theme editor. Dan buat mencegah kode tertentu jalan di editor, pakai request.design_mode dan Shopify.designMode dari 06 Theme Editor dan Code Editor > Integrasi Theme dengan Theme Editor. Bahasan lengkap event-nya di 54 Best Practices Umum.

Satu lagi yang udah disebut di 23 Templates > 3. Section Data: section harus punya presets biar bisa ditambahin lewat theme editor. Tanpa preset, section harus ditulis manual di JSON dan gak bisa dihapus merchant.

Tag schema

{% schema %} itu tag Liquid, tapi gak ngeluarin apa-apa dan gak ngerender Liquid di dalamnya. Isinya wajib JSON valid. Aturannya:

  1. Cuma boleh satu {% schema %} per section.
  2. Boleh ditaruh di mana aja di file, tapi gak boleh di dalam tag Liquid lain.
  3. Lebih dari satu, atau ditaruh di dalam tag lain, error sintaks.

Ini contoh schema lengkap buat section Slideshow yang bakal kita bedah atribut per atribut:

{% schema %}
{
  "name": "Slideshow",
  "tag": "section",
  "class": "slideshow",
  "limit": 1,
  "settings": [
    {
      "type": "text",
      "id": "title",
      "label": "Slideshow"
    }
  ],
  "max_blocks": 5,
  "blocks": [
     {
       "name": "Slide",
       "type": "slide",
       "settings": [
         {
           "type": "image_picker",
           "id": "image",
           "label": "Image"
         }
       ]
     }
  ],
  "presets": [
    {
      "name": "Slideshow",
      "settings": {
        "title": "Slideshow"
      },
      "blocks": [
        {
          "type": "slide"
        },
        {
          "type": "slide"
        }
      ]
    }
  ],
  "locales": {
    "en": {
      "title": "Slideshow"
    },
    "fr": {
      "title": "Diaporama"
    }
  },
  "enabled_on": {
    "templates": ["*"],
    "groups": ["footer"]
  }
}
{% endschema %}

❌ salah, schema di dalam tag if

{% if true %}
  {% schema %}{ "name": "Slideshow" }{% endschema %}
{% endif %}

✅ benar, schema berdiri sendiri

<div>...</div>
{% schema %}{ "name": "Slideshow" }{% endschema %}

1. name

Judul section yang tampil di theme editor. Maksimal 25 karakter sesuai 21 Gambaran Arsitektur Theme > 5. Penamaan:

{
  "name": "Slideshow"
}

2. tag

Bawaannya Shopify ngebungkus section pakai <div> dengan ID unik:

<div id="shopify-section-[id]" class="shopify-section">
  // Output of the section content
</div>

Kalau mau elemen lain, pakai tag. Yang diterima: article, aside, div, footer, header, section:

{
  "name": "Slideshow",
  "tag": "section"
}

Hasilnya:

<section id="shopify-section-[id]" class="shopify-section">
  // Output of the section content
</section>

Ini penting buat HTML semantik: header pakai header, footer pakai footer, sidebar pakai aside. Bahasannya di 55 Accessibility.

3. class

Nambahin class ke pembungkusnya, di samping shopify-section yang selalu ada:

{
  "name": "Slideshow",
  "tag": "section",
  "class": "slideshow"
}

Hasilnya:

<section id="shopify-section-[id]" class="shopify-section slideshow">
  // Output of the section content
</section>

4. limit

Bawaannya section bisa ditambahin berapa kali pun ke satu template atau section group. limit batasin jadi 1 atau 2:

{
  "name": "Slideshow",
  "limit": 1
}

Cocok buat section yang gak masuk akal kalau ada dua, kaya header atau pengumuman.

5. settings

Setting khusus section buat merchant. Semua tipe setting dibahas di 30 Settings dan Input Settings:

{
  "name": "Slideshow",
  "settings": [
    {
      "type": "text",
      "id": "header",
      "label": "Header"
    }
  ]
}

Semua id setting harus unik di dalam section. Duplikat = error. Nilainya diakses lewat section.settings.header.

Ingat catatan section statis: semua render statis section yang sama berbagi nilai setting.

6. blocks

Block itu modul konten di dalam section yang bisa ditambah, dihapus, dan diurutin merchant. Tiap block punya:

  1. type (wajib), pengenal bebas, diakses lewat block.type.
  2. name (wajib), judul block di theme editor.
  3. limit (opsional), maksimal berapa block tipe ini.
  4. settings (opsional), setting input atau sidebar buat block.
{
  "name": "Slideshow",
  "settings": [
    {
      "type": "text",
      "id": "title",
      "label": "Slideshow"
    }
  ],
  "blocks": [
     {
       "name": "Slide",
       "type": "slide",
       "settings": [
         {
           "type": "image_picker",
           "id": "image",
           "label": "Image"
         }
       ]
     }
   ]
}

Semua name dan type block harus unik di dalam section, dan semua id setting harus unik di dalam block. Duplikat = error.

Block yang didefinisikan di sini namanya section block, yang cuma hidup di section ini. Ada juga theme block yang bisa dipakai di banyak section, dibahas di 28 Blocks dan 29 Theme Blocks Mendalam.

7. Render Block

Loop section.blocks, cocokin block.type, dan wajib pasang block.shopify_attributes di elemen pembungkus tiap block:

{% for block in section.blocks %}
  {% case block.type %}
    {% when 'slide' %}
      <div class="slide" {{ block.shopify_attributes }}>
        {{ block.settings.image | image_url: width: 2048 | image_tag }}
      </div>
    ...
  {% endcase %}
{% endfor %}

shopify_attributes itu yang dipakai theme editor buat ngenalin block di JavaScript API-nya. Kalau block-mu cuma satu elemen, pastiin elemen itu yang dapat atributnya.

Dan jangan pernah ngandelin nilai literal block.id, karena ID-nya dibikin dinamis dan bisa berubah:

❌ salah, ID bisa berubah dan block-nya hilang

{% for block in section.blocks %}
{%- if block.id == 'J6d9jV' -%}
<h1>{{ block.settings.heading }}</h1>
{% endif %}
{% endfor %}

✅ benar, cocokin pakai type

{% for block in section.blocks %}
{%- if block.type == 'heading' -%}
<h1 {{ block.shopify_attributes }}>{{ block.settings.heading }}</h1>
{% endif %}
{% endfor %}

8. Block yang Direkomendasikan

Kalau section-mu nerima theme block (lewat tipe @theme), kamu bisa nyorot block tertentu di pemilih block biar gampang ditemuin. Sertakan @theme bareng block yang direkomendasikan:

"blocks": [
  { "type": "@theme" },
  { "type": "button" },
  { "type": "text" },
  { "type": "_marquee" }
]

text, button, dan _marquee langsung muncul di pemilih, theme block lain tetap bisa diakses lewat Show all. Bahasannya di 29 Theme Blocks Mendalam.

9. Judul Block Dinamis

Theme editor bisa nampilin nilai setting sebagai judul block di sidebar, biar merchant gampang ngenalin dan ngurutin. Dia ngecek id setting di block dengan urutan prioritas:

  1. heading
  2. title
  3. text

Kalau gak ada yang cocok, name block yang dipakai. Jadi block ini tampil di sidebar dengan judul “Welcome to our store”:

"blocks": [
  {
    "name": "Announcement",
    "type": "announcement",
    "settings": [
      {
        "type": "text",
        "id": "heading",
        "default": "Welcome to our store",
        "label": "Heading"
      }
    ]
  }
]

Ini alasan bagus buat konsisten namain setting teks utama heading atau title.

10. max_blocks

Batas bawaan 50 block per section. max_blocks nurunin batasnya:

{
  "name": "Slideshow",
  "max_blocks": 5
}

Static block gak dihitung di batas ini.

11. presets

Preset itu konfigurasi section yang udah jadi yang bisa dipilih merchant waktu nambahin section ke template JSON. Contoh: section “Testimonials” punya preset satu testimoni, carousel, dan grid. Merchant tinggal pilih, gak perlu ngatur dari nol.

Jangan ketuker sama theme preset di settings_data.json yang dibahas di 32 Config settings_schema.json, settings_data.json, markets.json, itu beda.

Di pemilih Add section:

  1. Preset diurutkan abjad berdasarkan name.
  2. Bisa dikelompokkan ke kategori yang bisa dilipat pakai category.
  3. Preset tanpa kategori selalu tampil duluan.
  4. Theme editor otomatis bikin preview preset-nya, yang bisa dikustom lewat visual preview mode.

Atributnya:

  1. name (wajib), nama di pemilih dan sidebar, dan disimpan di template JSON waktu section ditambahin.
  2. category (opsional), pengelompokan.
  3. settings (opsional), nilai awal setting.
  4. blocks (opsional), block awal, tiap-tiapnya punya type dan settings, opsional name.
"presets": [
  {
    "name": "Slideshow",
    "category": "Banners",
    "settings": {
      "title": "Slideshow"
    },
    "blocks": [
      {
        "type": "slide"
      },
      {
        "type": "slide"
      }
    ]
  }
]

Section dengan preset jangan dirender statis. Buat section statis, pakai default.

12. default

Buat section yang dirender statis, default nentuin konfigurasi awalnya. Atributnya sama kaya preset (settings dan blocks):

"default": {
  "settings": {
    "title": "Slideshow"
  },
  "blocks": [
    {
      "type": "slide"
    },
    {
      "type": "slide"
    }
  ]
}

Tapi ada nuansa: default cuma buat section yang bakal dipakai ulang atau dipasang di banyak theme atau toko. Section statis yang udah terpasang di theme dari awal sebaiknya pakai atribut default di tiap setting-nya sendiri (misalnya "default": "Slideshow" di dalam definisi setting title), bukan default level section.

13. locales

Section bisa bawa terjemahannya sendiri, terpisah dari folder locales/ theme. Berguna buat section yang mau dipasang di banyak theme atau toko:

"locales": {
  "en": {
    "title": "Slideshow"
  },
  "fr": {
    "title": "Diaporama"
  }
}

Terjemahan ini muncul di tab Sections di language editor. Kalau merchant ngedit, perubahannya disimpan ke file locale, schema section-nya gak berubah.

Diakses lewat filter t dengan format sections.[nama-section].[kunci]:

{{ 'sections.slideshow.title' | t }}

Ini yang disinggung di 20 Filters Money, Metafield, Cart, Customer, dan Localization > 5. Locale di Section. Ingat: terjemahan lain di schema (label setting, nama block) itu buat teks merchant di theme editor dan gak pakai t, dibahas di 33 Locales dan Translasi.

14. enabled_on

Batasi section ke jenis template dan section group tertentu. Wajib minimal salah satu:

  1. templates, daftar jenis halaman (nilai-nilai request.page_type dari 13 Objects Global > request), atau ["*"] buat semua.
  2. groups, daftar tipe section group: header, footer, aside, atau tipe kustom dengan format custom.<NAMA>, atau ["*"] buat semua.
"enabled_on": {
  "templates": ["*"],
  "groups": ["footer"]
}

Section ini bisa dipakai di semua template dan di section group footer aja (gak di header).

15. disabled_on

Kebalikannya: section tersedia di mana aja kecuali yang disebut:

"disabled_on": {
  "templates": ["password"],
  "groups": ["footer"]
}

Section ini bisa dipakai di semua template kecuali password, dan semua section group kecuali footer.

Cuma boleh pakai salah satu, enabled_on atau disabled_on, gak dua-duanya. Keduanya menggantikan atribut templates lama.

❌ salah, dua-duanya dipakai

"enabled_on": { "templates": ["index"] },
"disabled_on": { "groups": ["footer"] }

✅ benar, pilih satu

"enabled_on": { "templates": ["index"], "groups": [] }

Section vs Block: Kapan yang Mana

Dari sudut pandang desain theme, section dan block itu komponen modular yang ngasih merchant kesempatan kustomisasi. Aturan mainnya buat theme Online Store 2.0:

  1. Konten default tiap template harus ada di satu section utama (main-product, main-collection), dan section lain bisa ditambah, dihapus, diurutin.
  2. Pakai section buat nambah, ngehapus, atau ngurutin konten di level template atau section group, dan buat setting yang ngatur seluruh layout dan isi section.
  3. Pakai block buat konten yang diulang di dalam section (slide, kolom, item testimoni).

Bahasan lengkapnya di 54 Best Practices Umum.

Contoh Section Utuh

Ngerangkai semuanya, ini section “Image with text” sederhana:

{{ 'section-image-with-text.css' | asset_url | stylesheet_tag }}
 
<div class="image-with-text image-with-text--{{ section.settings.layout }}" id="section-{{ section.id }}">
  {% if section.settings.image != blank %}
    {{ section.settings.image | image_url: width: 1500 | image_tag: sizes: '(min-width: 750px) 50vw, 100vw' }}
  {% else %}
    {{ 'image' | placeholder_svg_tag }}
  {% endif %}
 
  <div class="image-with-text__content">
    {% for block in section.blocks %}
      {% case block.type %}
        {% when 'heading' %}
          <h2 {{ block.shopify_attributes }}>{{ block.settings.heading }}</h2>
        {% when 'text' %}
          <div {{ block.shopify_attributes }}>{{ block.settings.text }}</div>
        {% when 'button' %}
          <a href="{{ block.settings.link }}" class="button" {{ block.shopify_attributes }}>{{ block.settings.label }}</a>
      {% endcase %}
    {% endfor %}
  </div>
</div>
 
{% schema %}
{
  "name": "t:sections.image_with_text.name",
  "tag": "section",
  "class": "section",
  "settings": [
    {
      "type": "image_picker",
      "id": "image",
      "label": "t:sections.image_with_text.settings.image.label"
    },
    {
      "type": "select",
      "id": "layout",
      "options": [
        { "value": "image_first", "label": "t:sections.image_with_text.settings.layout.options__1.label" },
        { "value": "text_first", "label": "t:sections.image_with_text.settings.layout.options__2.label" }
      ],
      "default": "image_first",
      "label": "t:sections.image_with_text.settings.layout.label"
    }
  ],
  "blocks": [
    {
      "type": "heading",
      "name": "t:sections.image_with_text.blocks.heading.name",
      "limit": 1,
      "settings": [
        { "type": "inline_richtext", "id": "heading", "default": "Image with text", "label": "t:sections.image_with_text.blocks.heading.settings.heading.label" }
      ]
    },
    {
      "type": "text",
      "name": "t:sections.image_with_text.blocks.text.name",
      "limit": 1,
      "settings": [
        { "type": "richtext", "id": "text", "default": "<p>Pair text with an image.</p>", "label": "t:sections.image_with_text.blocks.text.settings.text.label" }
      ]
    },
    {
      "type": "button",
      "name": "t:sections.image_with_text.blocks.button.name",
      "limit": 1,
      "settings": [
        { "type": "text", "id": "label", "default": "Button label", "label": "t:sections.image_with_text.blocks.button.settings.label.label" },
        { "type": "url", "id": "link", "label": "t:sections.image_with_text.blocks.button.settings.link.label" }
      ]
    }
  ],
  "presets": [
    {
      "name": "t:sections.image_with_text.presets.name",
      "blocks": [
        { "type": "heading" },
        { "type": "text" },
        { "type": "button" }
      ]
    }
  ]
}
{% endschema %}

Perhatiin "t:sections.image_with_text.name": itu kunci terjemahan schema yang ngambil dari file locale schema, biar label di theme editor ikut bahasa merchant. Dibahas di 33 Locales dan Translasi.

Ringkasan

  1. Section = konten utama (HTML/Liquid) + aset opsional (javascript/stylesheet) + schema wajib.
  2. Object section dan block cuma ada di dalam section dan snippet yang dirender dari situ.
  3. Tiga cara render: template JSON/section group (utama), tag section (statis, hindari), Section Rendering API.
  4. Section statis cuma punya satu instance, setting-nya sharing di semua tempat dia dirender.
  5. Theme editor ngubah DOM tanpa reload, jadi JavaScript harus bisa diinisialisasi ulang, dan section/block yang dipilih harus tetap kelihatan.
  6. {% schema %} cuma boleh satu, gak boleh di dalam tag lain, isinya JSON valid.
  7. name maksimal 25 karakter, tag buat elemen semantik, class nambahin class, limit batasin 1 atau 2.
  8. id setting unik per section, name dan type block unik per section, id setting block unik per block.
  9. block.shopify_attributes wajib di pembungkus block, dan jangan ngandelin block.id literal.
  10. Judul block dinamis diambil dari setting heading, title, atau text sesuai prioritas.
  11. presets buat section di template JSON, default buat section statis yang dipakai ulang. Section dengan preset jangan dirender statis.
  12. locales di schema buat terjemahan yang dibawa section, diakses sections.[nama].[kunci] | t.
  13. enabled_on atau disabled_on, pilih satu, dengan templates dan groups.

Bab selanjutnya kita ke wadah section di layout: section group buat header, footer, dan area lain yang bisa diatur merchant, plus cara migrasi dari section statis lama.