Empat bab sebelumnya nutupin object toko, produk, konten, dan transaksi. Ini bab penutup object: yang struktural (section, block), yang fungsional (form, paginate, filter, search), dan yang khusus file (robots.txt).
Object di bab ini gak mewakili “benda” di toko, tapi mekanisme. section dan block itu soal gimana theme disusun, paginate dan filter soal gimana daftar dipotong dan disaring, form soal gimana input pelanggan ditangani.
section
Isi dan pengaturan section yang lagi dirender. Cuma tersedia di dalam file section dan snippet/block yang dirender dari situ.
id, ID section. Buat section di JSON template, ini ID yang ditulis di file JSON-nya. Buat section statis dari tagsection, ini nama file-nya.settings, pengaturan section, diakses pakaiidsetting:section.settings.heading.blocks, arrayblockmilik section ini.location, konteks section-nya:template,section group, atauglobal.index, urutan section di lokasinya, mulai dari 1.index0, urutan mulai dari 0.
Kegunaan paling umum: bikin ID dan class CSS yang unik per section, karena section yang sama bisa dipakai berkali-kali di satu halaman:
<div id="section-{{ section.id }}" class="hero">
{% style %}
#section-{{ section.id }} {
background: {{ section.settings.background_color }};
}
{% endstyle %}
<h2>{{ section.settings.heading }}</h2>
</div>Kalau kamu nulis .hero { background: ... } tanpa ID, section hero kedua di halaman yang sama bakal ikut warna section pertama.
❌ salah, semua section hero di halaman kena warna yang sama
{% style %}
.hero { background: {{ section.settings.background_color }}; }
{% endstyle %}✅ benar, tiap instance punya style-nya sendiri
{% style %}
#section-{{ section.id }} { background: {{ section.settings.background_color }}; }
{% endstyle %}section.index berguna buat performa: section pertama di halaman (yang kelihatan tanpa scroll) bisa di-load gambarnya secara eager, sisanya lazy. Bahasannya di 64 Performance Navigasi dan Loading. Object ini dibahas lagi di 26 Sections dan Section Schema.
block
Isi dan pengaturan satu section block (block yang didefinisikan di schema section). Diakses waktu loop section.blocks:
id, ID block. Dibuat dinamis sama Shopify dan bisa berubah, jadi jangan pernah nulis nilai literalnya di kode.type, tipe block, string bebas yang didefinisikan di schema. Ini yang dipakai buat nentuin markup mana yang dirender.settings, pengaturan block,block.settings.text.shopify_attributes, atributdata-*yang dipakai theme editor buat ngenalin block dan dengerin event. Wajib ditaruh di elemen pembungkus block. Di luar theme editor, nilainya kosong.
Maksimal 50 block per section. Pola standarnya:
{% for block in section.blocks %}
{% case block.type %}
{% when 'heading' %}
<h2 {{ block.shopify_attributes }}>{{ block.settings.text }}</h2>
{% when 'text' %}
<p {{ block.shopify_attributes }}>{{ block.settings.text }}</p>
{% when 'button' %}
<a href="{{ block.settings.link }}" {{ block.shopify_attributes }}>{{ block.settings.label }}</a>
{% endcase %}
{% endfor %}Kalau shopify_attributes gak dipasang, merchant gak bisa klik block-nya di preview theme editor buat langsung loncat ke pengaturannya. Theme Check punya aturan buat ngingetin ini.
❌ salah, block gak bisa dipilih dari preview editor
<h2>{{ block.settings.text }}</h2>✅ benar
<h2 {{ block.shopify_attributes }}>{{ block.settings.text }}</h2>Catatan: ini object buat section block (block lama yang didefinisikan di dalam section). Theme block yang dibahas di 29 Theme Blocks Mendalam punya cara render berbeda lewat content_for 'blocks', tapi object block-nya mirip.
app
Buat app block dan app embed: cuma punya metafields, yaitu metafield milik app itu. Dipakai app buat nyimpen konfigurasinya. Bahasannya di 28 Blocks.
form
Informasi soal form yang dibikin tag form dari 12 Tags Khusus Theme > form. Cuma tersedia di dalam {% form %} … {% endform %}. Gunanya dua: ngecek hasil submit dan ngisi ulang input kalau ada error.
1. Status
posted_successfully?,truekalau form berhasil dikirim,falsekalau ada error. Buat formcustomer_addressselalutrue.errors, objectform_errors(dibahah di bawah). Kalau gak ada error, nilainya falsy.id, ID form.
Pola dasar:
{% form 'contact' %}
{% if form.posted_successfully? %}
<p>Pesan terkirim, terima kasih!</p>
{% endif %}
{% if form.errors %}
{{ form.errors | default_errors }}
{% endif %}
...
{% endform %}2. Nilai Input
Kalau form gagal, nilai yang diketik pelanggan tersimpan di object form biar bisa diisi ulang, jadi mereka gak ngetik dari nol lagi. Properti mana yang ada tergantung tipe form:
email, ada di form kontak, komentar, dan customer.body, isi pesan form kontak atau isi komentar.author, nama penulis komentar (cumanew_comment).first_name,last_name,phone, buat customer dan alamat.address1,address2,city,province,zip,country,company, cuma formcustomer_address.set_as_default_checkbox, ngerender checkbox HTML buat ngeset alamat ini jadi default (cumacustomer_address).name(nickname penerima) danmessage, buat form gift card recipient.password_needed, selalutrue.
Pola isi ulang:
{% form 'contact' %}
<input type="email" name="contact[email]" value="{{ form.email }}">
<textarea name="contact[body]">{{ form.body }}</textarea>
{% endform %}form_errors
Error dari form. Object ini bisa di-loop langsung (isinya nama field yang error, misalnya email), dan punya dua array pendamping dengan urutan yang sama:
translated_fields, nama field yang udah diterjemahin (misalnya “Email” atau “Alamat email”).messages, pesan error yang udah diterjemahin (misalnya “tidak boleh kosong”).
Cara nampilin manual:
{% if form.errors %}
<ul>
{% for field in form.errors %}
<li>{{ form.errors.translated_fields[field] }} {{ form.errors.messages[field] }}</li>
{% endfor %}
</ul>
{% endif %}Cara malas yang udah cukup bagus, pakai filter default_errors:
{{ form.errors | default_errors }}Filter-filter form dibahas di 19 Filters HTML, URL, Media, Color, dan Font.
paginate
Tersedia di dalam tag paginate dari 11 Tags Perulangan > paginate. Buat bikin navigasi halaman sendiri kalau default_pagination kurang cocok:
current_page, nomor halaman sekarang.pages, jumlah total halaman.items, jumlah total item yang di-paginate.page_size, jumlah item per halaman.current_offset, jumlah item di halaman-halaman sebelum halaman ini. Berguna buat nampilin “Menampilkan 21–40 dari 100”.previous, objectpartbuat halaman sebelumnya.nildi halaman pertama.next, objectpartbuat halaman berikutnya.nildi halaman terakhir.parts, arraypartsemua bagian navigasi (nomor halaman dan…).page_param, nama parameter URL-nya. Biasanyapage, tapi buat settingproduct_listdan sejenisnya dikasih kunci unik.
Object part punya title (nomor halaman atau …), url, dan is_link (false buat halaman sekarang dan buat …).
Pola navigasi manual:
{% paginate collection.products by 12 %}
...
<nav>
{% if paginate.previous %}
<a href="{{ paginate.previous.url }}">← Sebelumnya</a>
{% endif %}
{% for part in paginate.parts %}
{% if part.is_link %}
<a href="{{ part.url }}">{{ part.title }}</a>
{% else %}
<span>{{ part.title }}</span>
{% endif %}
{% endfor %}
{% if paginate.next %}
<a href="{{ paginate.next.url }}">Berikutnya →</a>
{% endif %}
</nav>
<p>Menampilkan {{ paginate.current_offset | plus: 1 }}–{{ paginate.current_offset | plus: paginate.page_size | at_most: paginate.items }} dari {{ paginate.items }}</p>
{% endpaginate %}Object Filtering
Buat storefront filtering, fitur di mana merchant ngatur filter (harga, warna, ukuran, ketersediaan) di app Search & Discovery, dan theme nampilinnya. Object-nya bertingkat: filter punya banyak filter_value.
1. filter
Satu filter, dari collection.filters atau search.filters:
label, nama filter yang dilihat pelanggan, misalnya “Warna”.type, jenisnya:boolean(ya/tidak, misalnya “Tersedia”),list(daftar pilihan, misalnya warna), atauprice_range(rentang harga).param_name, nama parameter URL-nya, misalnyafilter.v.option.color.presentation, cara nampilinnya. Buat filter warna bisaswatchatauimage.operator, operator logika buat filterbooleandanlist(ANDatauOR).nilbuat tipe lain.url_to_remove, URL halaman sekarang tanpa filter ini. Buat tombol “hapus filter”.
Buat tipe list:
values, array semuafilter_value.active_values, yang lagi aktif.inactive_values, yang gak aktif.
Buat tipe boolean:
true_valuedanfalse_value, duafilter_value-nya.
Buat tipe price_range:
min_valuedanmax_value,filter_valuebuat batas bawah dan atas yang lagi aktif.range_max, harga tertinggi di koleksi atau hasil pencarian. Ini batas maksimum slider-nya.
2. filter_value
Satu nilai filter:
label, nama yang dilihat pelanggan, misalnya “Merah”.value, nilai buat parameter URL, dipasangkan samaparam_name.param_name, nama parameter filter induknya.active,truekalau lagi aktif.count, jumlah hasil yang cocok sama nilai ini. Buat nampilin “Merah (12)”.url_to_add, URL sekarang ditambah nilai ini. Parameter paginasi dibuang otomatis (biar balik ke halaman 1).url_to_remove, URL sekarang dikurangi nilai ini.swatch, objectswatch(warna atau gambar) kalau presentasinya swatch.image, objectimagekalau presentasinya gambar.
Pola dasar filter list:
{% for filter in collection.filters %}
{% if filter.type == 'list' %}
<fieldset>
<legend>{{ filter.label }}</legend>
{% for value in filter.values %}
<label>
<input type="checkbox" name="{{ value.param_name }}" value="{{ value.value }}" {% if value.active %}checked{% endif %}>
{{ value.label }} ({{ value.count }})
</label>
{% endfor %}
</fieldset>
{% endif %}
{% endfor %}Kenapa url_to_add dan url_to_remove itu penting? Karena bikin URL filter secara manual itu rumit banget (harus gabungin semua filter aktif dengan benar, encode karakter, buang paginasi). Shopify udah ngitungin, kamu tinggal pakai. Bahasan lengkapnya di 37 Filtering.
3. filter_value_display
Representasi visual nilai filter (versi lama sebelum swatch): type (misalnya colors) dan value (representasinya). Di theme baru, pakai filter_value.swatch dan filter_value.image.
search
Hasil pencarian. Tersedia di template search:
performed,truekalau pencarian beneran dijalankan (ada parameterqdi URL). Kalaufalse, tampilin form kosongnya aja.terms, kata yang dicari.results, hasilnya. Tiap item bisaarticle,page, atauproduct, dan punya properti tambahanobject_typebuat ngebedain. Wajib di-paginate, maksimal 50 per halaman.results_count, jumlah hasil.types, tipe object yang dicari, dari parameter URLtype.filters, arrayfilteryang diatur buat halaman pencarian.sort_by,default_sort_by(relevance),sort_options(arraysort_optiondengannamedanvalue).
Pola dasar:
{% if search.performed %}
<h1>{{ search.results_count }} hasil untuk "{{ search.terms }}"</h1>
{% paginate search.results by 24 %}
{% for item in search.results %}
{% case item.object_type %}
{% when 'product' %}
{% render 'product-card', product: item %}
{% when 'article' %}
{% render 'article-card', article: item %}
{% when 'page' %}
<a href="{{ item.url }}">{{ item.title }}</a>
{% endcase %}
{% else %}
<p>Gak ada hasil.</p>
{% endfor %}
{{ paginate | default_pagination }}
{% endpaginate %}
{% endif %}Ada filter highlight buat nyorot kata yang dicari di dalam hasil. Bahasannya di 38 Search dan Predictive Search.
predictive_search
Buat pencarian prediktif, yaitu saran yang muncul sambil ngetik. Object ini cuma ngasih hasil kalau dirender di section lewat Predictive Search API dan Section Rendering API. Kalau dipanggil di render biasa, kosong. Sama polanya kaya recommendations di 14 Objects Produk dan Koleksi > recommendations:
performed,truekalau lagi dirender lewat API itu.terms, kata yang diketik.types, tipe yang dicari, dari parametertype.resources, objectpredictive_search_resourcesdengan arrayproducts,collections,articles, danpages.
{% if predictive_search.performed %}
{% for product in predictive_search.resources.products %}
<a href="{{ product.url }}">{{ product.title }}</a>
{% endfor %}
{% endif %}Cara pasangnya di 38 Search dan Predictive Search.
sort_option
Satu pilihan urutan dari collection.sort_options atau search.sort_options: name (buat ditampilin, misalnya “Harga, rendah ke tinggi”) dan value (buat parameter URL, misalnya price-ascending).
forloop dan tablerowloop
Udah dibahas tuntas di 11 Tags Perulangan > Object forloop. Ringkasnya: forloop punya first, last, index, index0, rindex, rindex0, length, parentloop. tablerowloop punya semua itu plus col, col0, col_first, col_last, dan row.
Object robots.txt
Sekelompok object yang cuma ada di template robots.txt.liquid, file yang ngasih tau mesin pencari halaman mana yang boleh di-crawl. Strukturnya bertingkat:
robots, punyadefault_groups, arraygroupaturan bawaan Shopify.group, satu kelompok aturan buat satu crawler:user_agent(object),rules(arrayrule), dansitemap(object, ataublankkalau grup ini gak butuh sitemap).user_agent, punyadirective(selaluUser-agent) danvalue(nama crawler, misalnya*atauGooglebot).rule, satu aturan:directive(AllowatauDisallow) danvalue(path-nya, misalnya/policies/). Bisa ditampilin langsung tanpa nyebut propertinya.sitemap, punyadirective(selaluSitemap) danvalue(URL sitemap,https://toko.myshopify.com/sitemap.xml).
Pola dasarnya ngerender bawaan Shopify apa adanya, terus nambahin aturan sendiri:
{% for group in robots.default_groups %}
{{- group.user_agent }}
{%- for rule in group.rules -%}
{{ rule }}
{%- endfor -%}
{%- if group.sitemap != blank -%}
{{ group.sitemap }}
{%- endif -%}
{% endfor %}Jangan ganti aturan bawaannya, cukup tambahin. Aturan bawaan Shopify udah dioptimasi buat SEO dan ngelindungin halaman kaya checkout dan akun dari crawler. Bahasannya di 25 Template Spesial robots.txt, llms.txt, agents dan 48 SEO Metadata, hreflang, robots.txt.
Ringkasan
sectioncuma ada di dalam file section, dansection.idwajib dipakai buat bikin ID dan style yang unik karena section yang sama bisa muncul berkali-kali.section.indexmulai dari 1, berguna buat bedain section di atas layar sama yang di bawah.block.iddinamis dan bisa berubah, jangan ditulis literal.block.shopify_attributeswajib ditaruh di elemen pembungkus biar block bisa diklik di theme editor.- Maksimal 50 block per section, dan
block.typeyang nentuin markup mana yang dirender. formcuma ada di dalam{% form %}, punyaposted_successfully?,errors, dan nilai input buat diisi ulang. Properti yang ada tergantung tipe form.form_errorsbisa di-loop, dengantranslated_fieldsdanmessagesyang udah diterjemahin. Atau cukupform.errors | default_errors.paginatecuma ada di dalam tagpaginate, punyaparts(arraypartdengantitle,url,is_link),previous,next, dancurrent_offsetbuat “menampilkan X–Y dari Z”.filterpunya tiga tipe:boolean,list,price_range, masing-masing dengan properti nilai yang beda (true_value/false_value,values/active_values,min_value/max_value/range_max).filter_value.url_to_adddanurl_to_removeudah ngitungin URL-nya, jangan bikin manual.search.resultscampur produk, artikel, dan halaman, bedain pakaiobject_type, dan wajib di-paginate.predictive_searchcuma terisi kalau dirender lewat Predictive Search API, hasilnya diresources.products/collections/articles/pages.- Object robots.txt bertingkat:
robots.default_groups→group→user_agent,rules,sitemap, dan aturan bawaannya jangan diganti, cukup ditambah.
Selesai sudah bahasan object. Bab selanjutnya kita mulai filter, dimulai dari yang paling dasar dan paling sering dipakai: manipulasi teks, hitung-hitungan, dan pengolahan array.