Object udah tuntas. Sekarang giliran filter, dimulai dari yang paling sering dipakai: ngolah teks, ngitung angka, dan ngutak-atik array.
Ingat aturan dari 09 Dasar Liquid > Filters: filter ditulis setelah |, nerima parameter setelah :, dan dirantai dari kiri ke kanan. Bab ini bahas filter yang umum di semua Liquid (bukan khusus Shopify), tapi tetap yang bakal kamu tulis tiap hari.
Cara baca sintaks di bab ini: string | append: string artinya filter append nerima string di kiri dan satu parameter string. array | where: string, string artinya nerima array dan dua parameter.
Filter String
1. Ubah Huruf Besar-Kecil
upcase, semua jadi huruf besar.'hello' | upcase→HELLO.downcase, semua jadi huruf kecil.'HELLO' | downcase→hello.capitalize, huruf pertama kata pertama jadi besar, sisanya jadi kecil.'this sentence should start with a capitalized word.' | capitalize→This sentence should start with a capitalized word.camelize, jadi CamelCase.'variable-name' | camelize→VariableName.
Perhatiin capitalize ngecilin sisanya. Jadi 'iPhone Case' | capitalize jadi Iphone case, bukan IPhone Case.
downcase sering dipakai buat perbandingan yang gak peduli kapital:
{% assign type = product.type | downcase %}
{% if type == 'kaos' %}...{% endif %}2. Tambah dan Hapus
append, nambahin string di belakang.request.origin | append: product.url→ URL absolut.prepend, nambahin di depan.product.url | prepend: request.origin, hasilnya sama.remove, hapus semua kemunculan substring."I can't do it!" | remove: "'t"→I can do it!.remove_first, hapus kemunculan pertama aja.remove_last, hapus kemunculan terakhir aja.replace, ganti semua kemunculan.replace: 'a', 'b'.replace_first, ganti yang pertama.'komodo-dragon-scale' | replace_first: '-', ' '→komodo dragon-scale.replace_last, ganti yang terakhir.
Buat nggabungin string, append lebih cepat daripada capture, dan ada cara yang lebih cepat lagi pakai echo di dalam tag liquid. Bahasannya di 58 Performance Liquid.
3. Bersihin Spasi dan HTML
strip, buang spasi, tab, dan baris baru di kedua ujung.lstrip, cuma di kiri.rstrip, cuma di kanan.strip_newlines, buang semua baris baru di dalam string.strip_html, buang semua tag HTML.'<h3>Judul</h3><p>Isi</p>' | strip_html→JudulIsi.newline_to_br, ganti baris baru\njadi<br />. Buat nampilin teks daritextareayang ngehormatin enter.
strip_html wajib dipakai sebelum motong teks yang isinya HTML, kalau nggak tag-nya bisa kepotong di tengah dan ngerusak layout halaman.
4. Potong Teks
truncate: jumlah, potong sampai jumlah karakter, ditambah...di belakang. Elipsisnya ikut dihitung dalam jumlah karakter.'How to tell if you're out of invisibility potion' | truncate: 15→How to tell ....truncatewords: jumlah, potong sampai jumlah kata, ditambah.... Elipsisnya gak dihitung sebagai kata.
Dua-duanya nerima parameter kedua buat elipsis kustom. Kasih string kosong kalau gak mau elipsis:
{{ article.title | truncate: 15, '--' }}
{{ article.title | truncate: 15, '' }}Hasilnya:
How to tell i--
How to tell ifDan ini yang paling penting: tag HTML dihitung sebagai kata oleh truncatewords. Jadi <p> bisa kepotong dan </p>-nya hilang.
❌ salah, tag penutup bisa hilang, layout halaman berantakan
{{ article.content | truncatewords: 15 }}✅ benar
{{ article.content | strip_html | truncatewords: 15 }}5. Pecah dan Gabung
split: pemisah, pecah string jadi array. Ini satu-satunya cara bikin array di Liquid.'health-potion' | split: '-'→["health", "potion"].join, gabung array jadi string dipisah spasi.join: ', 'buat pemisah kustom.slice: mulaiatauslice: mulai, panjang, ambil potongan string (atau array) dari indeks 0. Indeks negatif ngitung dari belakang:
{{ collection.title | slice: 0 }}
{{ collection.title | slice: 0, 5 }}
{{ collection.title | slice: -3, 3 }}Kalau judulnya “Products”, hasilnya:
P
Produ
cts6. Handle
handleize, ubah string jadi handle sesuai aturan di 09 Dasar Liquid > Handle. Punya alias handle:
{{ product.title | handleize }}
{{ product.title | handle }}Dua-duanya ngasilin health-potion. Berguna buat bikin ID atau class CSS dari judul.
7. Pluralize
pluralize: tunggal, jamak, pilih bentuk tunggal atau jamak berdasarkan angka:
Cart item count: {{ cart.item_count }} {{ cart.item_count | pluralize: 'item', 'items' }}Hasilnya Cart item count: 2 items. Peringatan: ini pakai aturan bahasa Inggris. Buat bahasa Indonesia yang gak punya bentuk jamak, atau bahasa lain yang aturannya beda, pakai sistem terjemahan dengan count yang dibahas di 33 Locales dan Translasi.
Filter Escape dan Encoding
Ini kelompok filter keamanan. Kalau kamu nampilin teks yang diketik orang lain (nama pelanggan, isi komentar, judul produk yang diisi merchant), teks itu bisa berisi <script> atau karakter yang ngerusak HTML.
1. escape
Ubah karakter khusus HTML (<, >, ', &) jadi entitasnya:
{{ '<p>Text to be escaped.</p>' | escape }}Hasilnya:
<p>Text to be escaped.</p>Jadi kalau ada yang ngisi nama <script>alert(1)</script>, yang tampil ya teks itu apa adanya, bukan dieksekusi.
2. escape_once
Sama kaya escape, tapi gak nyentuh karakter yang udah di-escape. Kalau string udah berisi <, escape bakal ngubah &-nya jadi &lt; (double escape), sementara escape_once biarin aja. Pakai ini kalau gak yakin string-nya udah di-escape atau belum.
❌ berisiko, teks dari pengguna ditampilin mentah
<p>{{ comment.content }}</p>✅ aman
<p>{{ comment.content | escape }}</p>Ingat juga dari 06 Theme Editor dan Code Editor > Live Preview: escape itu satu-satunya filter yang gak ngerusak live preview setting teks.
3. Filter URL
url_encode, ubah karakter yang gak aman di URL jadi persen-encoded. Spasi jadi+, bukan%20.'[email protected]' | url_encode→test%40test.com.url_escape, escape karakter yang gak aman di URL.'<p>Health & Love potions</p>' | url_escape→%3Cp%3EHealth%20&%20Love%20potions%3C/p%3E. Perhatiin&-nya gak di-escape.url_param_escape, sama kayaurl_escapeplus&. Hasilnya%3Cp%3EHealth%20%26%20Love%20potions%3C/p%3E. Pakai ini buat nilai parameter query, karena&di situ bakal dianggap pemisah parameter.url_decode, kebalikanurl_encode.
4. Base64
base64_encodedanbase64_decode.'one two three' | base64_encode→b25lIHR3byB0aHJlZQ==.base64_url_safe_encodedanbase64_url_safe_decode, versi yang aman buat URL, pakai-dan_sebagai ganti+dan/.
5. Hash
Buat bikin hash (sidik jari) dari string, biasanya buat verifikasi atau bikin ID unik:
md5,sha1,sha256,blake3, hash biasa.hmac_sha1: kuncidanhmac_sha256: kunci, hash dengan kunci rahasia (HMAC):
{%- assign secret_potion = 'Polyjuice' | hmac_sha256: 'Polina' -%}
My secret potion: {{ secret_potion }}Hasilnya 8e0d5d65cff1242a4af66c8f4a32854fd5fb80edcc8aabe9b302b29c7c71dc20. Jarang dipakai di theme biasa, tapi berguna buat integrasi pihak ketiga yang butuh tanda tangan.
Filter Math
Semua nerima angka di kiri:
plus: n, tambah.4 | plus: 2→6.minus: n, kurang.times: n, kali.divided_by: n, bagi. Hasilnya ngikutin tipe pembaginya: dibagi bilangan bulat hasilnya bulat (dibulatkan ke bawah), dibagi desimal hasilnya desimal.modulo: n, sisa bagi.12 | modulo: 5→2. Berguna buat “tiap item ketiga”.abs, nilai mutlak.-3 | abs→3.ceil, bulatkan ke atas.1.2 | ceil→2.floor, bulatkan ke bawah.1.8 | floor→1.round, bulatkan ke terdekat.2.7 | round→3. Dengan parameter:3.14159 | round: 2→3.14.at_least: n, batasi minimal.4 | at_least: 5→5,4 | at_least: 3→4.at_most: n, batasi maksimal.6 | at_most: 5→5.
Jebakan divided_by yang sering bikin bingung:
{{ 20 | divided_by: 7 }}
{{ 20 | divided_by: 7.0 }}Hasilnya:
2
2.857142857142857❌ salah, persentase diskon jadi 0 karena pembagian bulat
{{ 25 | divided_by: 100 | times: product.price }}✅ benar, pakai desimal biar hasilnya desimal
{{ 25 | divided_by: 100.0 | times: product.price }}Buat ngitung persentase diskon dari harga coret:
{% assign discount = product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price | round %}
Hemat {{ discount }}%at_least dan at_most berguna buat ngunci nilai dalam rentang, misalnya jumlah kolom grid antara 1 sampai 4: settings.columns | at_least: 1 | at_most: 4.
Filter Array
Ini kelompok yang bikin Liquid bisa ngolah data tanpa perulangan manual.
1. Ambil Item
first, item pertama. Bisa juga pakai notasi titik:collection.products.first.last, item terakhir.collection.products.last.size, jumlah item (atau jumlah karakter kalau string). Bisa notasi titik:collection.products.size.
Notasi titik berguna di dalam tag di mana filter gak bisa dipakai:
{% if collection.products.size >= 10 %}
There are 10 or more products in this collection.
{% else %}
There are less than 10 products in this collection.
{% endif %}2. Saring
where: properti, nilai, ambil item yang properti-nya sama dengan nilai:
{% assign polina_products = collection.products | where: 'vendor', "Polina's Potent Potions" %}Dengan satu parameter aja, where ngambil item yang properti boolean-nya true:
{% assign available_products = collection.products | where: 'available' %}reject: properti, nilai, kebalikannya, buang item yang cocok.find: properti, nilai, ambil item pertama yang cocok (bukan array, langsung object-nya):
{% assign product = collection.products | find: 'vendor', "Polina's Potent Potions" %}
{{ product.title }}find_index: properti, nilai, ambil indeks item pertama yang cocok.has: properti, nilai, ngembaliintrue/falseapakah ada item yang cocok.compact, buang semua itemnil. Berguna setelahmapke properti yang bisa kosong.uniq, buang duplikat.'invisibility, health, love, health, invisibility' | split: ', ' | uniq | join: ', '→invisibility, health, love.
Ingat batasan dari 09 Dasar Liquid > Operator Logika dan Perbandingan: contains gak bisa nyari object di array. has dan where itu obatnya.
❌ salah, contains gak bisa nyari object
{% if collection.products contains product %}✅ benar
{% if collection.products | has: 'id', product.id %}Tunggu, itu juga salah: filter gak bisa dipakai langsung di dalam if. Yang benar, simpan dulu:
✅ benar beneran
{% assign in_collection = collection.products | has: 'id', product.id %}
{% if in_collection %}3. Ubah dan Gabung
map: properti, bikin array baru berisi satu properti dari tiap item:
{%- assign product_titles = collection.products | map: 'title' -%}
{{ product_titles | join: ', ' }}Hasilnya Draught of Immortality, Glacier ice, Health potion, Invisibility potion.
2. concat: array, gabung dua array. Gak buang duplikat, sambung sama uniq kalau perlu:
{%- assign types_and_vendors = collection.all_types | concat: collection.all_vendors -%}reverse, balik urutan.sum, jumlahin semua item. Dengan parameter, jumlahin properti tiap item:
Total quantity of all items in cart:
{{ cart.items | sum: 'quantity' }}
Subtotal price for all items in cart:
{{ cart.items | sum: 'final_line_price' | money }}Hasilnya 2 dan $422.49.
4. Urutkan
sort, urutkan peka kapital (huruf besar duluan) atau numerik.["Burning", "dried", "Salty"] | sort→Burning, Salty, dried.sort_natural, urutkan gak peka kapital. HasilnyaBurning, dried, Salty. Jangan dipakai buat angka, karena tiap item diubah jadi string dulu, jadi10bakal di depan9.- Dua-duanya nerima parameter properti buat ngurutin array object:
collection.products | sort: 'price'.
Jangan ketuker sama sort_by yang beda total: itu filter URL yang nambahin parameter ?sort_by= ke collection.url:
{{ collection.url | sort_by: 'best-selling' }}Hasilnya /collections/sale-potions?sort_by=best-selling. Nilainya: manual, best-selling, title-ascending, title-descending, price-ascending, price-descending, created-ascending, created-descending.
❌ salah, sort_by bukan buat ngurutin array
{% assign sorted = collection.products | sort_by: 'price' %}✅ benar
{% assign sorted = collection.products | sort: 'price' %}default
Ngasih nilai cadangan kalau variabelnya nil, false, atau empty:
{{ product.selected_variant.url | default: product.url }}Kalau selected_variant-nya nil, yang keluar product.url.
Perhatiin: string kosong '' itu bukan nil, bukan false, bukan empty, jadi default gak nangkepnya. Ingat aturan truthy/falsy di 09 Dasar Liquid > Truthy dan Falsy.
Ada parameter allow_false: true buat kasus di mana false itu nilai yang sah dan gak boleh diganti:
{%- assign display_price = false -%}
{{ display_price | default: true, allow_false: true }}Hasilnya false, bukan true.
Dan ingat dari 06 Theme Editor dan Code Editor > Live Preview: default di dalam {% style %} bikin live preview warna rusak, terapin di luar.
date
Ubah timestamp jadi format tanggal lain. Nerima format strftime ala Ruby:
{{ article.created_at | date: '%B %d, %Y' }}Hasilnya April 14, 2022. Kode format yang paling sering: %d (tanggal 01–31), %m (bulan 01–12), %B (nama bulan penuh), %b (nama bulan singkat), %Y (tahun 4 digit), %y (2 digit), %A (nama hari), %H:%M (jam:menit). Referensi lengkapnya di strftime reference.
Kata kunci 'now' dan 'today' ngasih waktu sekarang:
{{ 'now' | date: '%B %d, %Y' }}Tapi hati-hati: waktunya itu waktu Liquid terakhir dirender, dan karena ada cache, gak selalu update tiap kunjungan. Jangan dipakai buat countdown atau apapun yang butuh waktu presisi, itu urusan JavaScript.
Format Sadar Bahasa
Daripada nulis %B %d, %Y yang hasilnya selalu bahasa Inggris, pakai parameter format: dengan nama format yang otomatis nyesuaiin bahasa toko:
{{ article.created_at | date: format: 'abbreviated_date' }}Format bawaannya: abbreviated_date, basic, date, date_at_time, default, on_date (plus short dan long yang deprecated).
Kamu juga bisa bikin format sendiri di file locale di bawah kunci date_formats:
"date_formats": {
"month_day_year": "%B %d, %Y"
}Terus dipakai:
{{ article.created_at | date: format: 'month_day_year' }}Dengan cara ini, tiap bahasa bisa punya format tanggalnya sendiri (Indonesia %d %B %Y, Amerika %B %d, %Y). Bahasannya di 33 Locales dan Translasi.
❌ kurang bagus, format dan nama bulan selalu Inggris
{{ article.published_at | date: '%B %d, %Y' }}✅ lebih bagus, ngikutin bahasa toko
{{ article.published_at | date: format: 'date' }}json
Ubah string atau object jadi JSON. Berguna buat ngirim data ke JavaScript:
<script>
const product = {{ product | json }};
</script>Gak perlu dibungkus kutip, karena filter json udah nyertain kutipnya dan udah nge-escape kutip di dalamnya.
Satu catatan keamanan: di toko yang dibuat setelah 5 Desember 2017, product | json gak ngeluarin inventory_quantity dan inventory_policy varian, biar bot gak bisa ngintip stok toko. Kalau butuh, akses lewat varian satu-satu.
❌ salah, double kutip
const title = "{{ product.title | json }}";✅ benar
const title = {{ product.title | json }};Ringkasan
capitalizengecilin sisa hurufnya, bukan cuma ngegedein yang pertama.remove/replacekena semua,remove_first/replace_firstcuma yang pertama,_lastcuma yang terakhir.strip_htmlwajib sebelumtruncatewords, karena tag HTML dihitung kata dan bisa kepotong.truncatengitung karakter (elipsis ikut dihitung),truncatewordsngitung kata. Parameter kedua buat elipsis kustom.splititu satu-satunya cara bikin array,joinkebalikannya.escapebuat semua teks dari pengguna,escape_oncekalau gak yakin udah di-escape.url_encodeubah spasi jadi+,url_param_escapejuga nge-escape&buat nilai parameter query.divided_byngikutin tipe pembaginya, bagi dengan100hasilnya bulat, bagi dengan100.0hasilnya desimal.at_leastdanat_mostbuat ngunci nilai dalam rentang.where,reject,find,find_index,hasnyaring array berdasarkan properti, danwheredengan satu parameter nyari booleantrue.- Filter gak bisa dipakai langsung di dalam
if, simpan dulu pakaiassign. mapngambil satu properti,sumbisa ngejumlahin properti,concatgak buang duplikat (pakaiuniq).sortpeka kapital,sort_naturalnggak (dan jangan buat angka).sort_byitu filter URL, bukan pengurut array.defaultcuma nangkepnil,false,empty, bukan string kosong.allow_false: truekalaufalseitu nilai sah.datepakai strftime, tapi lebih baikdate: format: 'nama'yang sadar bahasa dan bisa dikustom di locale.'now'gak selalu update karena cache.jsonudah nyertain kutip dan nge-escape, dan nyembunyiin stok varian dariproduct | json.
Bab selanjutnya kita masuk ke filter khas Shopify: bikin tag HTML, URL aset dan CDN, gambar dan video responsif, manipulasi warna, dan load font.