Di 14 Objects Produk dan Koleksi kita bahas yang dijual. Sekarang yang nemenin jualannya: blog, halaman, menu, dan data kustom lewat metafield dan metaobject.
Bab ini dibagi tiga kelompok:
- Konten editorial:
article,blog,comment,page,user. - Navigasi:
linklistdanlink. - Data kustom:
metafield,metafields,metaobject, dan object-object nilai kayacolor,font,rating,money,measurement.
Kelompok ketiga ini yang paling penting buat theme modern, karena metafield itu cara merchant nambahin data apapun ke produk, koleksi, atau halaman tanpa nunggu Shopify nambahin fitur.
article
Satu artikel blog. Tersedia di template article, lewat blog.articles, atau articles['blog-handle/article-handle'].
id,title,handle,url.content, isi artikel (HTML).excerpt, kutipan singkat yang diisi merchant.excerpt_or_content, kutipan kalau ada, kalau nggak ya isi lengkapnya. Ini yang biasanya dipakai di daftar artikel biar gak perluif.image, gambar unggulan, objectimage.author, nama lengkap penulis (string).user, objectuserpenulisnya, denganfirst_name,last_name,name,email,bio,homepage,image, danaccount_owner(truekalau penulisnya pemilik toko).tags, array tag artikel.created_at,published_at,updated_at, timestamp.template_suffix, alternate template-nya.metafields.comments, arraycommentyang udah dipublikasikan. Bisa di-paginate.comments_count, jumlah komentar yang dipublikasikan.comments_enabled?,truekalau komentar diaktifkan.moderated?,truekalau blog induknya moderasi komentar (komentar harus disetujui dulu).comment_post_url, URL tujuan POST buat komentar baru. Tapi kamu gak perlu ini kalau pakai{% form 'new_comment', article %}yang dibahas di 12 Tags Khusus Theme > form.
Pola daftar artikel:
{% for article in blog.articles %}
<article>
{% if article.image %}
{{ article.image | image_url: width: 600 | image_tag }}
{% endif %}
<h2><a href="{{ article.url }}">{{ article.title }}</a></h2>
<p>{{ article.published_at | date: '%d %B %Y' }} oleh {{ article.author }}</p>
<p>{{ article.excerpt_or_content | strip_html | truncatewords: 30 }}</p>
</article>
{% endfor %}Perhatiin strip_html | truncatewords: 30: karena content itu HTML, kalau dipotong mentah bisa ninggalin tag yang gak ketutup. strip_html dulu baru dipotong. Filter-filternya di 18 Filters String, Math, dan Array.
blog
Satu blog. Tersedia di template blog, atau lewat blogs['handle'].
id,title,handle,url.articles, array artikel. Bisa di-paginate, dan wajib di-paginate kalau lebih dari 50.articles_count, jumlah artikel, gak termasuk yang disembunyiin.all_tags, semua tag dari semua artikel di blog.tags, sama kayaall_tags(daftar semua tag). Bedanya samacurrent_tagsglobal:current_tagsitu yang lagi aktif sebagai filter.next_article, artikel berikutnya (yang lebih lama).previous_article, artikel sebelumnya (yang lebih baru).comments_enabled?danmoderated?.template_suffixdanmetafields.
Perhatiin arah next_article dan previous_article yang kebalik dari intuisi: “next” itu yang lebih lama, karena blog diurutkan dari yang terbaru. Jadi kalau kamu bikin tombol “Artikel berikutnya”, pikirin dulu maksudnya “berikutnya dalam urutan tampil” atau “yang lebih baru”.
Dua properti ini cuma bernilai di dalam template article (karena butuh tau kamu lagi di artikel mana):
{% if blog.previous_article %}
<a href="{{ blog.previous_article.url }}">← Lebih baru</a>
{% endif %}
{% if blog.next_article %}
<a href="{{ blog.next_article.url }}">Lebih lama →</a>
{% endif %}comment
Satu komentar di artikel:
id.author, nama penulis komentar.email, emailnya. Jangan ditampilin ke publik.content, isi komentar.created_atdanupdated_at.status, selalupublished(karena yang gak dipublikasikan gak ikut dikembalikan).url, URL artikelnya ditambah#comment-id.
page
Satu halaman statis (About, Contact, FAQ). Tersedia di template page, atau lewat pages['handle']:
id,title,handle,url.content, isi halaman (HTML).author.published_at.template_suffixdanmetafields.
Ingat dari 09 Dasar Liquid > Tipe Data: halaman yang gak ada ngembaliin empty, dan empty itu truthy. Jadi:
❌ salah, blok ini tetap jalan walaupun halamannya gak ada
{% if pages['faq'] %}
{{ pages['faq'].content }}
{% endif %}✅ benar
{% unless pages['faq'] == empty %}
{{ pages['faq'].content }}
{% endunless %}linklist dan link
Ini object buat navigasi. Merchant bikin menu di Shopify admin (Online Store > Navigation), dan theme nampilinnya lewat dua object ini.
1. linklist
Satu menu:
title, judul menu.handle, handle menu, misalnyamain-menuataufooter.links, arraylinkdi menu ini.levels, jumlah tingkat bersarang di menu (1 = datar, 2 = ada dropdown, 3 = ada mega menu).
Diakses lewat linklists['handle'], atau lebih baik lewat setting bertipe link_list biar merchant bisa milih menu mana yang dipakai. Bahasannya di 30 Settings dan Input Settings.
2. link
Satu link di menu:
title, teks link.url, URL-nya.handle, handle dari judulnya.type, jenis tujuannya:article_link,blog_link,catalog_link,collection_link,collections_link,customer_account_page_link,frontpage_link,http_link(link eksternal, atau koleksi per tipe/vendor),metaobject_link,page_link,policy_link,product_link,search_link.object, object yang ditunjuk link ini, bisaarticle,blog,collection,metaobject,page,policy, atauproduct. Ini yang bikin kamu bisa nampilin gambar koleksi di mega menu tanpa query tambahan.links, array link anak (submenu).levels, jumlah tingkat di bawah link ini.data_sharing_opt_out_icon, ikon “Your Privacy Choices” (sebuah<img>) khusus buat link opt-out penjualan data yang otomatis ditambahin Shopify kalau merchant nyalain fitur itu. Hukum privasi negara bagian AS (CCPA/CPRA) mewajibkan ikon ini tampil di sebelah link-nya.nilbuat link lain.
Empat properti buat nandain menu yang lagi aktif:
current,truekalau path URL sekarang sama persis dengan URL link. Parameter URL diabaikan, dan URL produk di dalam koleksi (/collections/x/products/y) dianggap sama dengan/products/y.active,truekalau path URL sekarang sama atau mengandung URL link. Jadi waktu buka/blogs/potion-notions/new-potions, link ke/blogs/potion-notionsituactive. Ini buat nyorot kategori induk di menu.child_current,truekalau ada link anak yangcurrent.child_active,truekalau ada link anak yangactive.
Contoh ngecek jumlah anak:
{% for link in linklists.main-menu.links -%}
{% if link.links.size > 0 -%}
- {{ link.title }} ({{ link.links.size }} children)<br>
{%- else -%}
- {{ link.title }}<br>
{%- endif %}
{%- endfor %}Hasilnya:
- Home<br>
- Catalog (2 children)<br>
- Contact<br>Pola menu dua tingkat dengan penanda aktif:
<ul>
{% for link in linklists.main-menu.links %}
<li class="{% if link.active %}is-active{% endif %}">
<a href="{{ link.url }}" {% if link.current %}aria-current="page"{% endif %}>
{{ link.title }}{% if link.data_sharing_opt_out_icon %}{{ link.data_sharing_opt_out_icon }}{% endif %}
</a>
{% if link.links.size > 0 %}
<ul>
{% for child in link.links %}
<li><a href="{{ child.url }}">{{ child.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>Cara bikin navigasi lengkap termasuk mega menu ada di 36 Navigasi dan Menu.
Metafield
Ini bagian terpenting bab ini. Metafield itu data tambahan yang ditempel ke object Shopify. Produk punya kolom bawaan (judul, harga, deskripsi), tapi kalau merchant butuh “bahan”, “cara cuci”, “negara asal”, atau “produk terkait”, itu semua metafield.
Metafield gak bisa dibikin dari Liquid. Cuma bisa lewat Shopify admin (Settings > Custom data) atau lewat app. Liquid cuma baca.
1. Cara Akses
Jalurnya dua lapis: namespace (pengelompokan biar gak bentrok) dan key (nama metafield-nya):
{{ resource.metafields.namespace.key }}Contoh, metafield directions di namespace information milik produk:
Type: {{ product.metafields.information.directions.type }}
Value: {{ product.metafields.information.directions.value }}Hasilnya:
Type: single_line_text_field
Value: Take with a meal.Object yang punya metafields: shop, product, variant, collection, article, blog, page, customer, order, company, company_location, location, market, brand, app, dan remote_product.
Ada jebakan nama: kalau key metafield-nya size, first, atau last, wajib pakai kurung siku. Soalnya tiga nama itu juga filter bawaan Liquid. Dengan notasi titik, Liquid ngembaliin metafield-nya kalau ada, tapi kalau gak ada dia malah nerapin filter-nya ke namespace, jadi size ngembaliin jumlah metafield bukan nilai kosong.
❌ berisiko, kalau metafield-nya gak ada, size jadi filter dan ngembaliin angka
{{ product.metafields.custom.size }}✅ benar, kurung siku selalu nyari berdasarkan key
{{ product.metafields.custom['size'] }}2. Object metafield
Tiap metafield punya tiga properti:
type, tipenya (dibahas di bawah).value, nilainya, bentuknya tergantung tipe.list?,truekalau ini tipe list (banyak nilai).
Tipe-tipenya:
- Teks:
single_line_text_field,multi_line_text_field,rich_text_field(mendukung heading, list, link, bold, italic). - Referensi:
product_reference(nilainya objectproduct),collection_reference(collection),variant_reference(variant),page_reference(page),file_reference(generic_fileataumediabuat gambar dan video),url_reference. - Angka:
number_integer,number_decimal. - Tanggal:
date,date_time, nilainya string yang diformat pakai filterdate. - Lainnya:
json(object JSON),boolean,color(objectcolor),weight/volume/dimension(objectmeasurement),rating(objectrating),money(objectmoneydalam mata uang lokal pelanggan).
Yang penting: buat tipe referensi, value-nya itu object utuh. Jadi product.metafields.custom.related.value itu langsung object product yang bisa kamu ambil title, url, featured_image-nya. Gak perlu query lagi.
Selain baca value mentah, ada filter metafield yang nampilin nilai dalam format HTML yang pas (misalnya rich text jadi HTML, rating jadi bintang). Dibahas di 20 Filters Money, Metafield, Cart, Customer, dan Localization.
3. Metafield Tipe json
value-nya object JSON yang propertinya bisa diakses pakai nama atau indeks, dan bisa di-loop:
Temperature: {{ product.metafields.information.burn_temperature.value.temperature }}
Unit: {{ product.metafields.information.burn_temperature.value['unit'] }}
{% for property in product.metafields.information.burn_temperature.value -%}
{{ property.first | capitalize }}: {{ property.last }}
{%- endfor %}Hasilnya:
Temperature: 700
Unit: degrees
Temperature: 700
Unit: degrees
Scale: FahrenheitWaktu di-loop, tiap property itu pasangan di mana first = nama kunci dan last = nilainya.
4. Metafield Tipe list
value-nya array yang bisa di-loop:
{% for item in product.metafields.information.combine_with.value -%}
{{ item.product.title }}
{%- endfor %}Buat list teks biasa, itemnya bisa diakses langsung pakai indeks:
First item in list: {{ product.metafields.information.pickup_locations.value[0] }}
Last item in list: {{ product.metafields.information.pickup_locations.value.last }}Cara ngitung panjangnya beda tergantung tipe:
- Tipe referensi (list produk, list koleksi): pakai properti
count. - Tipe non-referensi (list teks, list angka): pakai filter
size.
Number of similar products: {{ product.metafields.information.similar_products.value.count }}
Number of pickup locations: {{ product.metafields.information.pickup_locations.value.size }}5. Metafield Deprecated
Tipe lama integer, json_string, dan string gak punya properti type, value, list?. Mereka langsung ngembaliin nilainya dan gak kompatibel sama filter metafield. Kalau nemu metafield yang .value-nya kosong padahal ada isinya, kemungkinan tipenya yang lama.
6. metafields dan metafield_namespace
resource.metafields itu object metafields yang ngelompokin per namespace. resource.metafields.custom itu object metafield_namespace. Dua-duanya cuma wadah, gak punya properti sendiri, cuma jalan buat sampai ke metafield-nya.
Metaobject
Kalau metafield itu kolom tambahan di object yang udah ada, metaobject itu tabel baru yang sepenuhnya dibikin merchant. Contoh: “Testimoni” dengan kolom nama, foto, dan kutipan. “Toko fisik” dengan kolom alamat, jam buka, dan peta. Dibikin di Content > Metaobjects.
Strukturnya: metaobject_definition (definisinya, kaya skema tabel) punya banyak metaobject (entri-entrinya, kaya baris tabel).
1. Akses Satu Metaobject
Lewat object global metaobjects, dengan tipe terus handle:
{{ metaobjects.type.handle }}
{{ metaobjects['type']['handle'] }}Nilai field-nya diakses pakai key field-nya, dan tiap field itu object metafield (jadi ada .value):
{{ metaobjects.testimonials.homepage.title }}
{{ metaobjects['highlights']['washable'].image.value }}Batasnya 20 handle unik per halaman dan gak bisa di-paginate. Buat lebih banyak, pakai values di bawah.
Kalau metaobject-nya punya capability publishable, yang statusnya draft ngembaliin nil.
2. Loop Semua Entri
Lewat metaobjects.type.values, yang merupakan properti metaobject_definition:
{% for testimonial in metaobjects.testimonials.values %}
{{ testimonial.author.value }}
{% endfor %}Maksimal 50 entri per loop, bisa di-paginate sampai 250 per halaman. Ada juga values_count buat jumlah totalnya. Entri berstatus draft dilewatin.
3. Object metaobject
Satu entri punya field-field yang didefinisikan merchant, plus satu properti bawaan system yang dikelompokin biar gak bentrok sama nama field buatan merchant:
system.handle, handle unik entri.system.id.system.type, tipe definisinya.system.url, URL relatif entri, kalau metaobject-nya punya halaman sendiri.
Jadi kalau merchant bikin field bernama id atau url, gak ketuker sama bawaan Shopify.
4. Di Template Metaobject
Metaobject bisa punya halaman sendiri lewat template templates/metaobject/*.json. Di dalam template itu, ada object metaobject yang mewakili entri yang lagi dirender:
{{ metaobject.title.value }}Bahasannya di 24 Template per Halaman.
Object Nilai
Sekelompok object kecil yang jadi nilai dari setting atau metafield.
1. color
Warna dari setting color atau metafield color. Kalau ditampilin langsung, keluar kode hex:
{{ settings.colors_accent_2 }}Hasilnya #334fb4. Propertinya:
red,green,blue, komponen 0–255.alpha, transparansi 0.0–1.0.hue(0–360),saturation(0–100),lightness(0–100).chroma(0.0–0.5), buat ruang warna OKLCH.rgb, stringr g bdipisah spasi, buatrgb()CSS modern.rgba, stringr g b / a.oklchdanoklcha, versi OKLCH-nya.color_space,srgbatauoklch.
Properti-properti ini yang bikin kamu bisa bikin warna dengan transparansi dari setting:
{% style %}
.overlay {
background: rgb({{ settings.colors_accent_1.rgb }} / 0.5);
}
{% endstyle %}Ada juga filter warna buat nyampur, nerangin, dan ngegelapin, dibahas di 19 Filters HTML, URL, Media, Color, dan Font. Dan ingat batasan live preview dari 06 Theme Editor dan Code Editor > Live Preview.
2. color_scheme dan color_scheme_group
Dari setting bertipe color_scheme_group. Tiap color_scheme punya id dan settings (object berisi warna-warnanya sesuai definisi di schema). Pola standarnya bikin class CSS per skema:
{% for scheme in settings.color_schemes %}
.color-{{ scheme.id }} {
--color-background: {{ scheme.settings.background }};
--color-text: {{ scheme.settings.text }};
}
{% endfor %}Hasilnya:
.color-background-1 {
--color-background: #FFFFFF;
--color-text: #121212;
}
.color-background-2 {
--color-background: #F3F3F3;
--color-text: #121212;
}
.color-inverse {
--color-background: #121212;
--color-text: #FFFFFF;
}Bahasannya di 30 Settings dan Input Settings dan 56 Design dan Color System.
3. font
Font dari setting font_picker:
family, nama keluarga font.fallback_families, font cadangan.style,normalatauitalic.weight, ketebalan (400, 700, dan sebagainya).baseline_ratio, rasio baseline sebagai desimal.system?,truekalau font sistem (gak perlu di-load).variants, arrayfontvarian lain di keluarga yang sama (bold, italic, dan sebagainya).
Cara load dan pakainya lewat filter font_face, font_url, dan font_modify, dibahas di 19 Filters HTML, URL, Media, Color, dan Font dan 31 Dynamic Sources dan Fonts.
4. rating
Dari metafield rating: rating (nilainya), scale_min, scale_max. Jadi rating 4.5 dari skala 0–5 punya rating = 4.5, scale_min = 0, scale_max = 5.
5. money
Dari metafield money: punya currency (object currency), dan nilainya ditampilin dalam mata uang lokal pelanggan.
6. measurement
Dari metafield weight, volume, atau dimension: type (jenisnya), unit (satuan, misalnya kg), value (angkanya).
Object Kecil Lainnya
1. part
Bagian dari navigasi paginasi, dikembalikan paginate.parts: title (nomor halaman), url, dan is_link (false buat halaman sekarang dan …). Dibahas di 17 Objects Lainnya.
2. parent_relationship
Buat line item bersarang (bundle) di keranjang: parent ngasih line item induknya. Dibahas di 16 Objects Cart, Checkout, Order, dan Customer.
Ringkasan
article.excerpt_or_contentbuat daftar artikel, danstrip_htmldulu sebelumtruncatewords.blog.next_articleitu yang lebih lama,previous_articleyang lebih baru, dan dua-duanya cuma bernilai di templatearticle.comment.statusselalupublished, dan jangan tampilincomment.email.- Halaman yang gak ada ngembaliin
emptyyang truthy, cek pakai== empty. linklistitu menu,linkitu itemnya.link.objectngasih object tujuannya,link.typengasih jenisnya,link.linksanak-anaknya.current= URL sama persis,active= URL sama atau mengandung, pluschild_currentdanchild_activebuat induknya.link.data_sharing_opt_out_iconwajib dirender di sebelah link “Your Privacy Choices” buat hukum privasi AS.- Metafield diakses
resource.metafields.namespace.key, punyatype,value, danlist?. Keysize,first,lastwajib pakai kurung siku. - Metafield referensi ngembaliin object utuh di
value, gak perlu query lagi. - Panjang list:
countbuat tipe referensi,sizebuat tipe lain. - Tipe lama
integer,json_string,stringlangsung ngembaliin nilai tanpa.valuedan gak kompatibel sama filter metafield. - Metaobject diakses
metaobjects.type.handle(maksimal 20 per halaman) atau di-loop lewatmetaobjects.type.values(maksimal 50, bisa paginate). Info bawaan ada disystembiar gak bentrok sama field merchant. colorditampilin langsung jadi hex, tapi punyargb,rgba,oklchbuat CSS modern dan komponenred/green/blue/alpha.color_schemepunyaiddansettings, pola standarnya di-loop jadi class CSS per skema.fontpunyafamily,weight,style,system?, danvariants, di-load lewat filter font.
Bab selanjutnya kita ke urusan transaksi: cart dan line_item buat keranjang, customer beserta alamat dan ordernya, order dengan fulfillment dan transaksinya, plus object diskon dan B2B.