Langsung ke konten utama
Saat kamu membuat form checkout manual di HTML Mode, Scalev.checkout.createOrder(payload) membuat order. Halaman kamu menangani redirect setelah order dibuat. HTML Checkout Page mengekspos konfigurasi aksi setelah checkout di Scalev.data.get().afterCheckout. Gunakan konfigurasi itu untuk memilih salah satu dari enam type ini setelah createOrder berhasil.
const afterCheckout = Scalev.data.get().afterCheckout || {
  type: "success_page"
};
afterCheckout berisi state konfigurasi dari editor Scalev.

Aturan redirect

Gunakan aturan ini untuk menentukan ke mana pembeli diarahkan setelah createOrder berhasil:
  • Untuk halaman checkout HTML Mode baru, render label payment dari Scalev.data.get().store.paymentMethodOptions[].display dan submit value option terpilih sebagai paymentMethod.
  • E-payment method selalu menuju halaman instruksi pembayaran. Ini mencakup va, value VA yang diratakan seperti va:BRI, qris, card, invoice, alfamart, ovo, dana, shopeepay, linkaja, dan gopay.
  • Value bank transfer manual seperti bt:BCA:paymentAccountUid diperlakukan sebagai bank_transfer.
  • Jika status order adalah draft, path instruksi pembayaran fallback ke Self Hosted Orderan / Invoice (order_page).
  • Jika halaman dirender di iframe, kirim target URL ke parent window daripada menavigasi iframe secara langsung.
Gunakan data order yang dikembalikan createOrder dan URL publik di response itu. createOrder mengembalikan object order secara langsung:
{
  "secretSlug": "orderSecret",
  "publicOrderUrl": "https://example.com/o/orderSecret",
  "paymentUrl": "https://example.com/o/orderSecret/success",
  "handlerPhone": "6281200000000",
  "chatMessage": "..."
}
const order = await Scalev.checkout.createOrder(payload);

Implementasi referensi

Gunakan helper ini setelah createOrder berhasil.
const PAYMENT_INSTRUCTION_METHODS = new Set([
  "va",
  "qris",
  "card",
  "invoice",
  "alfamart",
  "ovo",
  "dana",
  "shopeepay",
  "linkaja",
  "gopay"
]);

const SCALEV_QUERY_FORWARD_HOSTS = new Set([
  "scalev.com",
  "scalev.id",
  "app.scalev.id",
  "app.scalev.com"
]);

function paymentMethodForRedirect(paymentMethod) {
  if (typeof paymentMethod !== "string") return paymentMethod;

  if (paymentMethod.toLowerCase().startsWith("va:")) return "va";
  if (paymentMethod.toLowerCase().startsWith("bt:")) return "bank_transfer";

  return paymentMethod;
}

function publicOrderUrl(order) {
  if (order.publicOrderUrl) return order.publicOrderUrl;
  return new URL(`/o/${order.secretSlug}`, window.location.origin).toString();
}

function paymentInstructionUrl(order) {
  if (order.status === "draft") return publicOrderUrl(order);
  if (order.paymentUrl) return order.paymentUrl;

  const url = new URL(publicOrderUrl(order));
  url.pathname = `${url.pathname.replace(/\/$/, "")}/success`;
  return url.toString();
}

function whatsappUrl(phone, order, fallbackMessage = "") {
  const cleanPhone = String(phone || "").replace(/[^\d]/g, "");
  const message = order.chatMessage || encodeURIComponent(fallbackMessage);
  return `https://api.whatsapp.com/send/?phone=${cleanPhone}&text=${message}`;
}

function withCurrentQuery(url) {
  const nextUrl = new URL(url, window.location.href);
  const currentParams = new URLSearchParams(window.location.search);

  currentParams.forEach((value, key) => {
    nextUrl.searchParams.set(key, value);
  });

  return nextUrl.toString();
}

function maybeForwardCurrentQuery(url) {
  const nextUrl = new URL(url, window.location.href);
  const shouldForward =
    nextUrl.host === window.location.host ||
    SCALEV_QUERY_FORWARD_HOSTS.has(nextUrl.host);

  return shouldForward
    ? withCurrentQuery(nextUrl.toString())
    : nextUrl.toString();
}

function navigateAfterOrder(url) {
  if (window.self !== window.top) {
    window.parent.postMessage(url, "*");
    return;
  }

  window.location.assign(url);
}

function redirectAfterOrder({
  type,
  order,
  paymentMethod,
  customWhatsappPhone,
  otherPagePath,
  customUrl
}) {
  const redirectPaymentMethod = paymentMethodForRedirect(
    paymentMethod || order.paymentMethod
  );
  const finalType = PAYMENT_INSTRUCTION_METHODS.has(redirectPaymentMethod)
    ? "success_page"
    : type;

  if (finalType === "success_page") {
    return navigateAfterOrder(paymentInstructionUrl(order));
  }

  if (finalType === "direct_to_whatsapp") {
    const phone = order.handlerPhone;
    return navigateAfterOrder(
      phone ? whatsappUrl(phone, order) : publicOrderUrl(order)
    );
  }

  if (finalType === "direct_to_custom_whatsapp") {
    return navigateAfterOrder(whatsappUrl(customWhatsappPhone, order));
  }

  if (finalType === "other_page") {
    return navigateAfterOrder(withCurrentQuery(otherPagePath));
  }

  if (finalType === "order_page") {
    return navigateAfterOrder(publicOrderUrl(order));
  }

  if (finalType === "custom_url") {
    return navigateAfterOrder(maybeForwardCurrentQuery(customUrl));
  }

  return navigateAfterOrder(paymentInstructionUrl(order));
}
Contoh pemakaian:
const data = Scalev.data.get();
const store = data.store;
const afterCheckout = data.afterCheckout || { type: "success_page" };
const selectedPaymentOption = store.paymentMethodOptions[0];
const selectedVariant = store.products[0].variants[0];
const destination = {
  address: form.address.value,
  subdistrictId: Number(form.subdistrictId.value),
  postalCode: form.postalCode.value
};
const items = [
  { type: "product", variantUniqueId: selectedVariant.uniqueId, quantity: 1 }
];
const shippingOptions = await Scalev.checkout.shippingOptions({
  items,
  destination,
  paymentMethod: selectedPaymentOption.value
});
const shipping = shippingOptions[0];

const payload = {
  customer: {
    name: form.customerName.value,
    phone: form.customerPhone.value
  },
  destination,
  items,
  paymentMethod: selectedPaymentOption.value,
  shipping
};

const order = await Scalev.checkout.createOrder(payload);

redirectAfterOrder({
  type: afterCheckout.type,
  order,
  paymentMethod: payload.paymentMethod,
  customWhatsappPhone: afterCheckout.customWhatsappPhone,
  otherPagePath: afterCheckout.otherPagePath,
  customUrl: afterCheckout.customUrl
});
Jika checkout memakai biaya tambahan dari store, Scalev menghitungnya di estimateSummary dan menerapkan serta memvalidasinya lagi di createOrder. Gunakan Scalev.checkout.estimateSummary() hanya saat halaman perlu menampilkan estimasi biaya dan total sebelum submit; kirim payload yang akan kamu kirim ke createOrder. Logic redirect setelah order dibuat tidak berubah.

Enam type

Label editorValuePerilaku HTML Mode
Halaman Instruksi Pembayaransuccess_pageRedirect ke halaman instruksi pembayaran Scalev. Prioritaskan order.paymentUrl; fallback ke /o/{secretSlug}/success. Untuk order.status bernilai draft, gunakan Self Hosted Orderan / Invoice (order_page).
Langsung ke WhatsAppdirect_to_whatsappBuka WhatsApp memakai order.handlerPhone dan order.chatMessage. Scalev memilih handler dari assignment store atau halaman. Saat handlerPhone kosong, arahkan ke Self Hosted Orderan / Invoice (order_page).
Langsung ke Nomor WhatsApp tertentudirect_to_custom_whatsappBuka WhatsApp memakai nomor yang kamu konfigurasi dan order.chatMessage. Gunakan ini saat setiap order harus masuk ke nomor sales atau admin tetap.
Landing Page Lainnyaother_pageRedirect ke path landing page lain di host yang sama dan pertahankan query string saat ini. Gunakan afterCheckout.otherPagePath dari konfigurasi runtime jika page sudah dipilih.
Self Hosted Orderan / Invoiceorder_pageRedirect ke halaman publik order atau invoice. Prioritaskan order.publicOrderUrl; fallback ke /o/{secretSlug} di origin saat ini.
Custom URLcustom_urlRedirect ke URL yang kamu berikan. Untuk host saat ini atau host app Scalev yang dikenal, kamu bisa meneruskan query string saat ini untuk menjaga attribution. Untuk host eksternal, teruskan hanya parameter yang sengaja dibagi.

Memilih type

Gunakan success_page saat pembeli perlu melihat instruksi pembayaran atau status pembayaran Scalev paling lengkap. Gunakan direct_to_whatsapp saat langkah berikutnya ditangani sales yang diassign oleh store. State konfigurasi terpilih hanya mengekspos afterCheckout.handlerAssignment; Scalev menentukan handler sebenarnya saat order dibuat, jadi redirect memakai order.handlerPhone dari response order. Gunakan direct_to_custom_whatsapp saat langkah berikutnya selalu masuk ke nomor tetap. Baca nomornya dari afterCheckout.customWhatsappPhone. Gunakan other_page saat tujuan berikutnya adalah landing page Scalev lain di host yang sama, misalnya thank-you page atau upsell page. Baca path dari afterCheckout.otherPagePath. Gunakan order_page saat pembeli perlu melihat invoice atau detail order publik yang dibuat. Gunakan custom_url untuk tujuan di luar flow halaman saat ini, seperti handoff ke CRM, thank-you page eksternal, atau pengalaman custom yang kamu hosting sendiri. Baca URL dari afterCheckout.customUrl.

Catatan analytics dan attribution

Pertahankan query parameter untuk other_page. Untuk custom_url, teruskan query parameter hanya saat target host adalah host saat ini atau salah satu host app Scalev yang dikenal. Setelah Scalev.checkout.createOrder(payload) berhasil, HTML Checkout Page otomatis men-trigger event analytics submit form yang dikonfigurasi untuk pixel analytics di halaman. Redirect tetap manual, jadi jalankan redirect setelah createOrder selesai dan tambahkan custom analytics hanya untuk event yang memang terpisah. Jika halaman memiliki tombol atau link yang redirect ke URL lain, pertahankan query parameter yang umum penting untuk analytics, seperti UTM, click, dan affiliate parameter.