Setelah ngebahas semua folder theme dari 21 Gambaran Arsitektur Theme sampai 33 Locales dan Translasi, ada satu file yang sengaja kita tunda: checkout.liquid. Dia udah deprecated, tapi masih sering ditemuin di theme toko Plus yang lama, dan kamu perlu tau apa itu biar bisa ngenalin, gak niru, dan tau harus migrasi ke mana.

checkout.liquid itu layout di folder layout yang ngerender halaman checkout, dan cuma tersedia buat merchant Shopify Plus. Toko non-Plus cuma bisa ngustomisasi checkout lewat theme editor (logo, warna, font) dan gak pernah nyentuh file ini.

Status Deprecation

Ini yang paling penting dari bab ini:

  1. checkout.liquid udah gak didukung buat langkah Information, Shipping, dan Payment.
  2. checkout.liquid dan additional scripts udah dimatikan buat halaman Thank you dan Order status sejak 28 Agustus 2025.
  3. Script tag di halaman Thank you dan Order status dimatikan buat toko Plus sejak 28 Agustus 2025, dan buat toko non-Plus sejak 26 Agustus 2026.

Toko yang masih pakai checkout.liquid buat Thank you dan Order status wajib upgrade ke Shopify Extensions in Checkout (Checkout Extensibility). Penggantinya bukan file theme, tapi app extension: UI extension, Shopify Functions, dan branding API yang dibangun lewat app, bukan lewat theme. Dokumentasinya ada di Build checkout extensions.

Jadi buat kamu sebagai theme developer: jangan pernah bikin checkout.liquid baru. Sisanya bab ini buat ngerti kode lama.

Kenapa dihapus? Karena checkout.liquid ngasih akses penuh ke DOM checkout, dan tiap kali Shopify ngupgrade checkout, kustomisasi merchant rusak. Toko Plus yang makainya harus pakai versi checkout Maintenance yang dibekukan, gak dapat fitur baru, dan harus upgrade manual. Checkout Extensibility ngasih titik kustomisasi yang stabil dan versi-aman, dengan Shopify tetap megang kendali penuh atas alur bayar.

Lokasi

└── theme
  ├── layout
  |  ├── theme.liquid
  |  └── checkout.liquid
  ├── templates
  ...

Bersebelahan sama theme.liquid dari 22 Layouts, tapi gak bisa dipilih lewat tag layout di template. Shopify otomatis makainya buat halaman checkout kalau aksesnya diaktifin.

Akses dan Dua Versi Checkout

Buat ngaktifin atau matiin akses checkout.liquid, merchant Plus harus ngontak support Shopify. Sebelum minta, mereka harus paham dua versi checkout:

  1. Standard, checkout bawaan. Dipakai kalau akses checkout.liquid gak aktif, dan otomatis diperbarui tiap Shopify rilis fitur.
  2. Maintenance, dipakai kalau akses checkout.liquid aktif. Versi stabil dari Standard yang dibekukan di waktu tertentu, gak diperbarui otomatis. Buat dapat fitur baru: matiin akses checkout.liquid (balik ke Standard), atau nunggu Maintenance di-upgrade dan ngikutin proses upgrade manual.

Nambahin file-nya (kalau akses udah aktif) lewat code editor admin: Online Store > Themes > … > Edit code, terus di folder Layout klik Add a new layout, pilih checkout, klik Create layout.

Struktur Bawaan

<!DOCTYPE html>
<html lang="{{ locale }}" dir="{{ direction }}" className="{{ checkout_html_classes }}">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, height=device-height, minimum-scale=1.0, user-scalable=0" />
    <meta name="referrer" content="origin" />
    <title>{{ page_title }}</title>
    {{ content_for_header }}
    {{ checkout_stylesheets }}
    {{ checkout_scripts }}
  </head>
  <body>
    {{ skip_to_content_link }}
    <header className="banner" data-header role="banner">
      <div className="wrap">
        {{ content_for_logo }}
      </div>
    </header>
    {{ order_summary_toggle }}
    <div className="content" data-content>
      <div className="wrap">
        <div className="main">
          <header className="main__header" role="banner">
            {{ content_for_logo }}
            {{ breadcrumb }}
            {{ alternative_payment_methods }}
          </header>
          <main className="main__content" role="main">
            {{ content_for_layout }}
          </main>
          <footer className="main__footer" role="contentinfo">
            {{ content_for_footer }}
          </footer>
        </div>
        <aside className="sidebar" role="complementary">
          <div className="sidebar__header">
            {{ content_for_logo }}
          </div>
          <div className="sidebar__content">
            {{ content_for_order_summary }}
          </div>
        </aside>
      </div>
    </div>
    {{ tracking_code }}
  </body>
</html>

Polanya mirip theme.liquid: kerangka HTML dengan object-object Shopify yang ngisi bagian tertentu. Bedanya, hampir semua isinya dirender Shopify, kamu cuma ngatur kerangkanya.

Langkah Checkout

Checkout itu satu halaman dengan satu URL yang isinya berganti sesuai langkah:

  1. Inventory issues, tampil kalau ada item yang stoknya habis atau kurang dari yang diminta. Pembeli lihat tombol konfirmasi buat nyesuain jumlah.
  2. Contact information, pembeli ngisi email (bisa login kalau akun pelanggan aktif). Kalau ada item yang butuh pengiriman, tampil form alamat pengiriman, kalau gak, form alamat tagihan.
  3. Shipping method, pilih opsi pengiriman. Dilewati kalau gak ada item yang butuh pengiriman (produk digital, jasa).
  4. Payment method, pilih metode bayar dan isi datanya. Sebagian provider ngarahin ke situs lain. Bisa isi alamat tagihan berbeda.
  5. Review order, opsional tergantung pengaturan checkout, pembeli konfirmasi total, alamat, dan pembayaran lalu klik Complete order. Bisa wajib buat toko yang beroperasi di Uni Eropa.
  6. Processing/forwarding, halaman sementara waktu pesanan diproses atau waktu diarahin ke provider pembayaran luar.
  7. Order status, langkah terakhir setelah pesanan selesai.

Di setiap langkah, Order summary (produk, harga, pajak, ongkir) tampil di kolom kanan, dan collapse di layar mobile.

Object Checkout

Object khusus yang cuma ada di layout ini:

  1. content_for_header (wajib), script Shopify buat hCaptcha, app, dan lainnya. Harus di antara <head> dan </head>.
  2. content_for_layout (wajib), form dan konten tiap langkah checkout. Harus di antara <body> dan </body>.
  3. locale, locale yang dipilih.
  4. direction, arah CSS konten, ltr atau rtl.
  5. page_title, judul halaman, biasanya dibungkus <title>.
  6. skip_to_content_link, link tersembunyi buat aksesibilitas, lompat ke konten utama.
  7. checkout_html_classes, string class buat tag <html> biar dapat CSS bawaan Shopify.
  8. checkout_stylesheets, stylesheet checkout Shopify. Jangan dihapus walaupun punya stylesheet sendiri, karena ngeganti styling bawaan itu kerjaan besar.
  9. checkout_scripts, file JavaScript Shopify.
  10. content_for_logo, logo toko sesuai pengaturan checkout.
  11. breadcrumb, daftar langkah checkout, gak tampil di langkah review terakhir.
  12. order_summary_toggle, markup buat nampilin/nyembunyiin ringkasan pesanan di mobile.
  13. content_for_order_summary, ringkasan pesanan: line item, diskon, pajak, total.
  14. alternative_payment_methods, daftar metode bayar express (PayPal, dan seterusnya).
  15. content_for_footer, daftar kebijakan toko, atau notis hak cipta kalau kosong.
  16. tracking_code, JavaScript buat Google Analytics dan Facebook Pixel.
  17. checkout, object checkout dari 16 Objects Cart, Checkout, Order, dan Customer.

Kalau object wajib gak ada, file-nya gak bisa disimpan lewat code editor atau CLI.

Kustomisasi Konten

Ini batasan mendasar checkout.liquid: kamu gak bisa ngedit konten yang dihasilkan object checkout sebelum dirender. Pengecualiannya cuma pengaturan translasi, theme editor, dan beberapa opsi di admin. Jadi kalau mau ngubah isi form, satu-satunya cara: JavaScript setelah render. Ini akar masalah yang bikin checkout.liquid rapuh.

1. Identifikasi Langkah via JavaScript

Karena satu URL buat semua langkah, Shopify nyediain object JavaScript buat tau posisi pembeli:

  1. Shopify.Checkout.step: contact_information, shipping_method, payment_method, processing (antara payment dan thank you), review (opsional).
  2. Shopify.Checkout.page: show (template langkah biasa), stock_problems, processing, forward (halaman gateway pihak ketiga), thank_you.
  3. Shopify.Checkout.OrderStatus, buat nambahin konten di halaman Order status, dan buat bedain Thank you dari Order status.

Nuansanya: kunjungan pertama ke halaman Order status dianggap Thank you page, di situ step dan page terdefinisi. Kalau pembeli reload atau balik lagi, checkout-nya udah jadi order, halaman jadi Order status, step dan page undefined, dan OrderStatus yang terdefinisi.

2. Page Events

Dua event utama:

  1. page:load, waktu konten tiap langkah dimuat. Event bawaan buat nambahin konten.
  2. page:change, waktu pembeli masih di langkah yang sama tapi sebagian konten berubah, misalnya setelah submit kode diskon.

Kalau cuma pakai page:load, konten yang kamu tambahin bisa ketimpa waktu page:change. Jadi selalu dengerin dua-duanya:

$(document).on("page:load page:change", function() {
  // Add content
});

3. jQuery Checkout

Checkout bawa jQuery-nya sendiri di Checkout.$ (versinya belum tentu terbaru):

(function($) {
  $(document).on("page:load page:change", function() {
    // Add your customizations
  });
})(Checkout.$);

4. Checkout Attributes

Mirip cart attributes: input dengan name="checkout[attributes][nama-atribut]" di dalam form utama checkout:

<input type="text" name="checkout[attributes][custom attribute]" />

Dua jebakan:

  1. Kalau ngumpulin atribut di langkah Payment method, isi dulu dengan nilai placeholder sebelum lanjut, karena nilai kosong bisa bikin error “checkout has changed”.
  2. Nangkep checkout attribute ngehapus cart attribute yang udah ada. Buat ngejaganya, loop checkout.attributes dan masukin lagi sebagai input tersembunyi (dari dalam fungsi JavaScript yang naruh input di form utama):
{% for attribute in checkout.attributes %}
  <input type=hidden name="checkout[attributes][{{ attribute.first }}]" value="{{ attribute.last  }}" />
{% endfor %}

Best Practice Kustomisasi (Kode Lama)

Kalau kamu ngerawat toko Plus yang masih punya checkout.liquid (sampai migrasinya selesai), ini praktik yang dipakai:

1. Backup Dulu

Sebelum ngubah apa-apa, backup versi sekarang (download atau duplikat theme). Dan ingat: tiap Shopify rilis upgrade checkout, layout yang udah diubah harus di-upgrade manual.

2. Minimalkan Ketergantungan DOM

Pertimbangan terbesar: seberapa bergantung kode kamu ke struktur DOM. Tiap upgrade checkout, output object Liquid bisa berubah, dan kustomisasi yang nempel ke struktur itu rusak. Cara paling aman: nambahin konten di luar output object Liquid, dan kalau harus milih elemen, rujuk atribut data dan name yang jarang berubah, bukan class.

❌ rapuh

$(".section .section__content .field__input-wrapper input").val("...");

✅ lebih tahan upgrade

$("input[name='checkout[email]']").val("...");

3. Satu Snippet per Kustomisasi, Ada Komentar

Simpan semua kode satu kustomisasi di satu snippet, dan kasih komentar siapa dan kapan yang ngubah:

{% comment %} Added by Name from Company on September 21 2018 {% endcomment %}

4. Killswitch

Kustomisasi checkout lebih rawan konflik yang bisa nghambat penjualan. Jadi bungkus semuanya dengan killswitch: theme setting yang bisa dimatiin buat ngebalikin checkout ke normal sambil kamu debug.

{
  "type": "checkbox",
  "id": "checkout_customization",
  "label": "Enables a checkout customization"
},
{% comment %}Added by Name at Company on September 21, 2018{% endcomment %}
{% if settings.checkout_customization %}
  {% render 'checkout-customization' %}
{% endif %}

Di snippet-nya: pakai jQuery checkout, dengerin page:load page:change, dan batasi ke langkah yang tepat:

(function($) {
  $(document).on("page:load page:change", function() {
    if (Shopify.Checkout.step === "contact_information") {
      // Add content
    }
  });
})(Checkout.$);

5. Form Submit dan Validasi

Banyak kustomisasi butuh validasi sebelum pembeli lanjut. Karena tombol submit utama punya perilaku khusus, cara termudah: dengerin click di tombolnya (bukan submit di form), dan alihkan Enter ke click juga:

(function($) {
  $(document).on("page:load page:change", function() {
    if (Shopify.Checkout.step === "contact_information") {
      $("DEFINE_YOUR_SUBMIT_BUTTON_SELECTOR").on("click", function(e) {
        e.preventDefault();
        if (data is valid) {
          $("DEFINE_YOUR_MAIN_FORM_SELECTOR").submit();
        } else {
          // Show an error
        }
      });
      $("DEFINE_YOUR_MAIN_FORM_SELECTOR").on("keyup", function(e) {
        if (e.keycode === 13) {
          e.preventDefault();
          $("DEFINE_YOUR_SUBMIT_BUTTON_SELECTOR").trigger("click");
        }
      });
    }
  });
})(Checkout.$);

Selector-nya placeholder, kamu yang nentuin, dengan prinsip minim ketergantungan DOM.

6. Kustomisasi yang Sering Diminta

  1. Blokir karakter tertentu di field alamat: validasi di event blur field dan di form submit, bandingin sama regex, tampilin error dan cegah default kalau gak valid.
  2. Batasi panjang field alamat: $("SELECTOR").attr("maxlength", nilai), plus pesan waktu batasnya kecapai karena maxlength cuma nyegah input tanpa ngasih tau.
  3. Checkbox Terms of Service wajib: bikin checkbox, cek di form submit, dan simpan nilainya sebagai checkout attribute.

Semua ini sekarang punya padanan yang jauh lebih bersih di Checkout Extensibility (validation function, checkout UI extension dengan checkbox dan attribute).

CSS di checkout.liquid

Kalau nambahin CSS di checkout.liquid, praktiknya:

  1. Ingat ada empat sampai enam halaman checkout tergantung pengaturan, semua harus di-style.
  2. Pakai BEM dan selector paling sederhana. Checkout pakai BEM buat ngurangin nesting. ❌ terlalu dalam
.order-summary .order-summary__section .product_list .product_info .product__info__name {
  color: red;
}

✅ BEM langsung

.product__info__name {
  color: green;
}
  1. Hindari !important, stylesheet kamu dimuat setelah stylesheet dasar, jadi gak perlu.
  2. Desain tombol buat semua state: disabled, normal, hover.
  3. Breakpoint bawaan: Small 0px ke atas (tanpa media query), Medium 750px, Large 1000px, Large Desktop 1300px.
  4. Webfont sendiri bisa dimuat lewat @font-face di tag style checkout.liquid.
  5. Aset eksternal wajib https:// karena checkout pakai SSL, dan sebaiknya dari CDN Shopify.
  6. Feature detection lewat class di <html>: js/no-js, browser dan OS (mac chrome), dan class Modernizr buat dukungan CSS (RGBA, multiple background, box-shadow, pseudo-element, inline SVG).
  7. State field: default (tanpa class), fokus field--focus, error field--error. Kebijakan dan halaman processing tampil di modal layar penuh. Pakai warning buat ngasih tau total berubah (misalnya stok disesuaikan), dan pesan error yang jelas.

Ringkasan

  1. checkout.liquid itu layout checkout khusus Plus yang udah deprecated: gak didukung buat Information/Shipping/Payment, dimatikan buat Thank you dan Order status sejak 28 Agustus 2025, script tag non-Plus sejak 26 Agustus 2026.
  2. Penggantinya Checkout Extensibility (UI extension, Functions, branding API lewat app), bukan file theme. Jangan bikin checkout.liquid baru.
  3. Dihapus karena rapuh: kustomisasi cuma bisa lewat JavaScript setelah render dan rusak tiap upgrade, dan toko harus dibekukan di versi Maintenance.
  4. Object wajib: content_for_header di head dan content_for_layout di body, sisanya opsional tapi checkout_stylesheets sebaiknya jangan dihapus.
  5. Tujuh langkah checkout di satu URL, diidentifikasi via Shopify.Checkout.step, .page, dan .OrderStatus, dengan nuansa Thank you vs Order status.
  6. Selalu dengerin page:load dan page:change, pakai Checkout.$.
  7. Checkout attribute lewat name="checkout[attributes][x]", tapi ngehapus cart attribute kecuali kamu masukin lagi lewat loop checkout.attributes.
  8. Praktik kode lama: backup, minim ketergantungan DOM (pakai atribut data/name), satu snippet per kustomisasi dengan komentar, killswitch theme setting, validasi lewat click tombol submit.
  9. CSS: BEM, tanpa !important, breakpoint 750/1000/1300, aset https://, class state field--focus/field--error.

Bab selanjutnya kita lompat dari yang paling tua ke yang paling baru: dua tag Liquid yang masih developer preview, {% block %} dan {% partial %}, yang ngubah cara nulis markup theme block dan snippet.