Bagian 1 udah selesai, alat-alat kita lengkap. Sekarang masuk Bagian 2: bahasa Liquid. Di 01 Apa itu Theme Shopify > Cara Kerjanya kita udah lihat sekilas
{{ product.title }}, sekarang kita pelajari dari akar.
Liquid itu bahasa template bikinan Shopify, sifatnya open source dan dipakai banyak project lain juga (Jekyll, misalnya). Yang kita pelajari di buku ini adalah variasi Liquid buat theme Shopify, yang punya tag, filter, dan object tambahan khusus buat toko.
Shopify juga punya variasi Liquid lain buat template notifikasi email, Shopify Flow, order printer, dan packing slip, tapi itu gak dibahas di sini.
Apa itu Bahasa Template?
Bahasa template bikin kamu bisa nulis satu cetakan yang isinya konten statis, terus nyisipin informasi dinamis tergantung di mana cetakan itu dirender.
Contoh: kamu bikin satu template produk yang berisi semua atribut standar produk (gambar, judul, harga). Template itu bakal ngerender atribut-atribut tadi dengan isi yang sesuai tergantung produk mana yang lagi dibuka. Satu template, ribuan produk.
Tiga Bahan Utama
Semua kode Liquid itu kombinasi dari tiga hal:
- Objects, data yang mau ditampilin. Ditulis di dalam
{{ }}. - Tags, logika yang ngatur apa yang harus dilakuin. Ditulis di dalam
{% %}. - Filters, pengubah output. Ditulis pakai
|setelah object.
Contoh yang gabungin ketiganya:
<title>
{{ page_title }}
</title>
{% if page_description -%}
<meta name="description" content="{{ page_description | truncate: 150 }}">
{%- endif %}Hasilnya:
<title>
Health potion
</title>
<meta name="description" content="Are you low on health? Well we've got the potion just for you! Just need a top up? Almost dead? In between? No need to worry because we have a ...">Bedah satu-satu: {{ page_title }} itu object yang ditampilin. {% if page_description %} itu tag yang ngecek apakah deskripsinya ada. | truncate: 150 itu filter yang motong teksnya jadi 150 karakter.
Cara paling gampang ngebedain: {{ }} itu buat nampilin sesuatu, {% %} itu buat ngelakuin sesuatu. Kurung kurawal ganda bakal nyetak ke halaman, kurung persen gak nyetak apa-apa, cuma instruksi.
Objects
Object itu variabel yang bisa kamu pakai buat bangun theme. Jenisnya antara lain:
- Sumber daya toko, kaya koleksi atau produk beserta propertinya.
- Konten standar yang jadi tulang punggung theme, kaya
content_for_header. - Elemen fungsional buat interaktivitas, kaya
paginatedansearch.
Object bisa mewakili satu nilai atau punya banyak properti. Buat nampilin object, bungkus pakai {{ }}. Buat nampilin propertinya, pakai notasi titik:
{{ product.title }}Kalau datanya:
{
"product": {
"title": "Health potion"
}
}Hasilnya:
Health potion1. Tiga Cara Object Bisa Diakses
Ini penting banget dan sering bikin bingung pemula: gak semua object bisa dipakai di semua tempat.
- Global, bisa dipakai di file Liquid manapun. Contohnya
shop,settings,request. Kecuali dicheckout.liquiddan file asset.liquid. - Di template tertentu, cuma ada di template itu beserta section dan block-nya. Contohnya object
productcuma ada di template produk. Kalau kamu pakaiproductdi halaman depan, isinya kosong. - Lewat object induk, dikembalikan sebagai properti object lain. Contohnya object
articlebisa diakses lewatarticlesataublog.
Tiap object punya dokumentasi yang nyebut cara aksesnya. Kita bahas semuanya di 13 Objects Global sampai 17 Objects Lainnya.
❌ salah, product gak ada di halaman koleksi, hasilnya kosong tanpa error
{% comment %} di templates/collection.json {% endcomment %}
<h1>{{ product.title }}</h1>✅ benar, di halaman koleksi ambil produknya lewat object collection
{% for product in collection.products %}
<h2>{{ product.title }}</h2>
{% endfor %}2. Bikin Variabel Sendiri
Pakai tag assign atau capture. Secara sintaks, Liquid memperlakukan variabel sama persis kaya object:
{% assign my_variable = 'My custom string.' %}
{{ my_variable }}Hasilnya:
My custom string.Detailnya di 10 Tags Variabel dan Percabangan.
Tags
Tag itu instruksi, bukan konten. Dibungkus {% %}, dan gak nyetak apa-apa ke halaman.
Contoh paling dasar, tag if:
{% if product.available %}
Price: $99.99
{% else %}
Sorry, this product is sold out.
{% endif %}Kalau product.available itu true, hasilnya:
Price: $99.99Beberapa tag nerima parameter, ada yang wajib ada yang opsional. Contohnya for punya parameter opsional limit buat berhenti di indeks tertentu:
{% assign numbers = '1,2,3,4,5' | split: ',' %}
{% for item in numbers limit:2 -%}
{{ item }}
{% endfor %}Hasilnya:
1
2Kalau kamu punya banyak tag berturut-turut, gak perlu nulis {% %} berkali-kali. Ada tag liquid yang bikin kamu bisa nulis banyak tag dalam satu pembungkus. Bahasannya di 10 Tags Variabel dan Percabangan.
Filters
Filter ngubah output dari variabel dan object. Cara pakainya: tulis | setelah object, terus nama filter-nya:
{{ product.title | upcase }}Kalau judulnya “Health potion”, hasilnya:
HEALTH POTIONBanyak filter nerima parameter setelah tanda titik dua:
{{ product.title | remove: 'Health' }}Hasilnya:
potionDan filter bisa dirantai. Urutannya dari kiri ke kanan, hasil filter pertama masuk ke filter kedua, dan seterusnya:
{{ product.title | upcase | remove: 'HEALTH' }}Hasilnya:
POTIONPerhatiin: remove-nya nyari 'HEALTH' huruf besar, karena upcase udah jalan duluan. Kalau urutannya dibalik, remove: 'Health' harus huruf biasa. Urutan filter itu penting.
❌ salah, upcase jalan dulu, jadi remove: 'Health' gak nemu apa-apa
{{ product.title | upcase | remove: 'Health' }}✅ benar, sesuaikan sama urutannya
{{ product.title | remove: 'Health' | upcase }}Semua filter dibahas di 18 Filters String, Math, dan Array sampai 20 Filters Money, Metafield, Cart, Customer, dan Localization.
Handle
Ini konsep khas Shopify yang bakal kamu temuin di mana-mana.
Object yang mewakili sumber daya toko (produk, koleksi, artikel, blog) punya handle buat mengidentifikasi satu item secara unik. Handle dipakai buat bikin URL sumber daya itu, dan buat ngambil properti-nya. Object lain kaya linklists, links, dan settings juga punya handle.
Gampangnya: handle itu nama “ramah URL” dari sebuah benda. Produk “Health Potion” punya handle health-potion, dan URL-nya /products/health-potion.
1. Aturan Pembuatan Handle
Handle dibuat otomatis dari judulnya, dengan aturan:
- Selalu huruf kecil.
- Spasi dan karakter khusus diganti tanda hubung
-. - Beberapa spasi atau karakter khusus berturut-turut jadi satu tanda hubung.
- Spasi atau karakter khusus di awal dibuang.
Handle harus unik. Kalau ada judul yang sama, handle-nya ditambahin angka: dua produk bernama Potion bakal punya handle potion dan potion-1.
Dan ini jebakan yang sering bikin bingung: setelah sumber daya dibuat, ganti judulnya gak ngubah handle-nya. Jadi produk yang dulu dinamain “Ramuan Lama” terus diganti jadi “Ramuan Baru” tetap punya handle ramuan-lama. Handle bisa diubah manual di Shopify admin di bagian Handle atau Edit website SEO, tapi kalau kamu ngerujuk sumber daya pakai handle di kode, rujukannya harus ikut diupdate.
Catatan buat object lain: link di dalam linklists handle-nya dari judulnya dan gak bisa diubah langsung. Setting dari settings_schema.json, section, atau block handle-nya dari properti id-nya.
Ada filter handle buat ngubah string apapun jadi handle:
{{ product.title | handle }}Kalau judulnya “Health potion”, hasilnya:
health-potion2. Ngerujuk Pakai Handle
Semua object yang punya handle punya properti handle, misalnya product.handle. Dan kamu bisa ngambil satu object dari object induknya pakai handle dengan dua cara:
- Notasi kurung siku
[ ], nerima handle dalam tanda kutip, variabel Liquid, atau rujukan object. - Notasi titik
., nerima handle tanpa kutip.
'About us' page URL: {{ pages['about-us'].url }}
Enable product suggestions: {{ settings.predictive_search_enabled }}Hasilnya:
'About us' page URL: /pages/about-us
Enable product suggestions: trueKapan pakai yang mana? Kurung siku wajib kalau handle-nya ada tanda hubung (karena pages.about-us bakal dibaca sebagai pages.about dikurangi us) atau kalau handle-nya dari variabel. Notasi titik cukup buat handle sederhana tanpa tanda hubung.
❌ salah, tanda hubung bikin Liquid bingung
{{ pages.about-us.url }}✅ benar, pakai kurung siku
{{ pages['about-us'].url }}✅ benar juga, handle dari variabel
{% assign page_handle = 'about-us' %}
{{ pages[page_handle].url }}Operator Logika dan Perbandingan
Dipakai di tag kondisional (if, unless, case, else):
==, sama dengan.!=, tidak sama dengan.>, lebih besar.<, lebih kecil.>=, lebih besar atau sama.<=, lebih kecil atau sama.or, kondisi A atau B.and, kondisi A dan B.contains, ngecek keberadaan string di dalam string atau array.
1. contains
Bisa dipakai buat ngecek string di dalam array, atau string di dalam string. Tapi gak bisa buat ngecek object di dalam array object:
{% if product.tags contains 'healing' %}
This potion contains restorative properties.
{% endif %}❌ salah, contains gak bisa nyari object
{% if collection.products contains product %}✅ benar, bandingin lewat properti yang berupa string
{% assign handles = collection.products | map: 'handle' %}
{% if handles contains product.handle %}2. Urutan Evaluasi
Ini yang paling sering bikin bug halus: kalau ada lebih dari satu operator dalam satu tag, dievaluasi dari kanan ke kiri, dan urutan ini gak bisa diubah. Dan tanda kurung () bukan karakter yang valid di dalam tag Liquid. Kalau kamu pakai buat ngelompokin, tag-nya gak bakal dirender sama sekali.
{% unless true and false and false or true %}
This evaluates to false, since Liquid checks tags like this:
true and (false and (false or true))
true and (false and true)
true and false
false
{% endunless %}Jadi true and false and false or true dibaca dari kanan: false or true = true, terus false and true = false, terus true and false = false.
❌ salah, tanda kurung bikin tag-nya gak dirender
{% if (a or b) and c %}✅ benar, pecah jadi variabel dulu
{% assign a_or_b = false %}
{% if a or b %}{% assign a_or_b = true %}{% endif %}
{% if a_or_b and c %}Tipe Data
Output Liquid bisa salah satu dari enam tipe:
string, deretan karakter dalam kutip tunggal atau ganda. Buat ngecek string kosong, pakai objectblank.number, angka, baik desimal maupun bulat.boolean,trueataufalse.nil, nilai yang tidak terdefinisi. Tag atau output yang ngembaliinnilgak nyetak apa-apa, dan diperlakukan sebagaifalse. Catatan: string berisi karakter “nil” bukannil.array, daftar variabel dengan tipe apapun. Diakses pakaiforatautablerow, atau item tertentu pakai[ ]dengan indeks mulai dari 0. Kamu gak bisa bikin array dari nol cuma pakai Liquid, tapi bisa pakai filtersplitbuat mecah string jadi array.empty, dikembalikan kalau kamu ngakses object yang terdefinisi tapi gak punya nilai. Contohnya halaman atau produk yang udah dihapus, atau setting tanpa nilai. Bandingin samaemptybuat ngecek object-nya ada sebelum ngakses atributnya:
{% unless pages.about-us == empty %}
<h1>{{ page.title }}</h1>
<div>
{{ page.content }}
</div>
{% endunless %}Cara bikin array satu-satunya:
{% assign colors = 'red,green,blue' | split: ',' %}
{{ colors[0] }}Hasilnya red.
Truthy dan Falsy
Semua tipe data harus bisa dievaluasi jadi true atau false. Yang jadi true disebut truthy, yang jadi false disebut falsy.
Aturannya di Liquid sangat sederhana dan sangat berbeda dari JavaScript: cuma nil dan false yang falsy. Semua yang lain truthy. Termasuk:
- String kosong
''→ truthy. - Angka
0→ truthy. - Array kosong → truthy.
- Object kosong (
EmptyDrop) → truthy.
Kalau kamu datang dari JavaScript di mana 0 dan '' itu falsy, ini bakal bikin kaget. Akibatnya, kamu harus hati-hati ngecek nilai: nilai yang bentuknya gak sesuai harapan bisa tetap truthy.
Solusinya: string kosong dicek pakai blank, object kosong dicek pakai empty:
{% if settings.featured_potions_title != blank -%}
{{ settings.featured_potions_title }}
{%- else -%}
No value for this setting has been selected.
{%- endif %}
{% unless pages.recipes == empty -%}
{{ pages.recipes.content }}
{%- else -%}
No page with this handle exists.
{%- endunless %}Kalau featured_potions_title-nya null dan halaman recipes gak ada, hasilnya:
No value for this setting has been selected.
No page with this handle exists.❌ salah, string kosong itu truthy, jadi blok ini tetap jalan walau setting-nya kosong
{% if section.settings.heading %}
<h2>{{ section.settings.heading }}</h2>
{% endif %}✅ benar, cek pakai blank
{% if section.settings.heading != blank %}
<h2>{{ section.settings.heading }}</h2>
{% endif %}Whitespace Control
Tiap baris Liquid, walaupun gak nyetak teks, tetap ngasilin satu baris di output. Jadi file yang penuh tag if dan assign bakal ngasilin HTML yang penuh baris kosong.
Buat ngebuang whitespace itu, tambahin tanda hubung di dalam tag: {%- dan -%}, atau {{- dan -}}. Tanda hubung di sisi kiri buang whitespace sebelum tag, di sisi kanan buang whitespace setelah tag. Boleh cuma satu sisi:
{%- if collection.products.size > 0 -%}
The '{{ collection.title }}' collection contains the following types of products:
{% for type in collection.all_types -%}
{% unless type == blank -%}
- {{ type }}
{%- endunless -%}
{%- endfor %}
{%- endif -%}Hasilnya rapi tanpa baris kosong berlebih:
The 'Sale potions' collection contains the following types of products:
- Health
- Health & Beauty
- Invisibility
- WaterIni bukan cuma soal kerapian. Di beberapa tempat, whitespace itu ngaruh ke tampilan, misalnya di antara elemen inline-block, atau di dalam <pre>. Dan HTML yang lebih kecil berarti halaman yang lebih ringan.
Ringkasan
- Liquid itu bahasa template: satu cetakan, data dinamis disisipin waktu dirender.
- Tiga bahan: objects
{{ }}buat nampilin, tags{% %}buat logika, filters|buat ngubah output. - Gak semua object ada di semua tempat: ada yang global, ada yang cuma di template tertentu, ada yang lewat object induk.
- Filter dirantai dari kiri ke kanan, urutannya ngaruh ke hasil.
- Handle itu nama ramah-URL yang unik: huruf kecil, spasi jadi
-, dan gak berubah walaupun judulnya diganti. - Rujuk pakai handle lewat
[ ]kalau ada tanda hubung atau dari variabel, notasi titik cuma buat handle sederhana. containscuma buat string di string atau string di array, bukan object di array.- Operator dievaluasi dari kanan ke kiri dan tanda kurung dilarang. Pecah jadi variabel kalau butuh pengelompokan.
- Enam tipe data: string, number, boolean, nil, array, empty. Array cuma bisa dibikin lewat
split. - Cuma
nildanfalseyang falsy. String kosong,0, dan array kosong itu truthy. Cek string pakaiblank, cek object pakaiempty. - Tiap baris Liquid ngasilin baris output, pakai
{%-dan-%}buat buang whitespace.
Bab selanjutnya kita bedah tag-tag pertama: assign, capture, echo, increment, decrement, tag liquid, dan percabangan if, unless, case, else.