Langsung ke konten utama
Halaman HTML Mode Scalev dapat memakai window.Scalev dari JavaScript browser. Runtime ini memberi konteks halaman yang aman, konteks store terpilih, helper checkout, forwarding analytics, helper prefill form, dan diagnostics tanpa mengekspos token API privat ke browser. Halaman ini ditulis untuk developer dan AI agent yang membuat file HTML Mode. Gunakan method ini daripada memanggil URL Scalev privat secara langsung.

Ketersediaan

Runtime tersedia di halaman HTML Mode yang sudah dirender. Di preview editor lokal, beberapa method dapat mengembalikan data preview.
const scalev = window.Scalev;

if (!scalev) {
  // Jaga halaman tetap bisa dipakai saat data runtime dimuat.
}
Sebagian besar method asynchronous dan mengembalikan Promise. Scalev.data.get() dan Scalev.diagnostics.get() bersifat synchronous. Payload dan response method runtime memakai key object camelCase. Runtime menangani casing backend secara internal, jadi JavaScript halaman tidak perlu mengirim key snake_case. Runtime method juga mengembalikan hasil yang terlihat oleh JavaScript secara langsung. Container backend seperti data dan is_paginated dihapus sebelum array dikembalikan. String enum dan blob milik provider tidak diubah. Contohnya success_page, direct_to_whatsapp, analytics parameters, metadata, dan customData tetap memakai nilai aslinya.

Konteks store

Saat Store Context dipilih, Scalev.data.get().store berisi ringkasan store terpilih, produk, dan bundle price option yang dipilih. Perlakukan data ini sebagai katalog checkout khusus halaman. Saat HTML Checkout Page dipilih, Scalev.data.get().afterCheckout berisi tipe sukses setelah checkout yang dipilih dan konfigurasi tujuan publiknya. Saat Store Context tidak dipilih, perlakukan store sebagai data yang tidak tersedia. Buat landing page biasa dan gunakan hanya method aman seperti Scalev.data.get(), Scalev.analytics.track(), dan Scalev.prefill.get().

Aturan keamanan

  • Jangan taruh API key, JWT business user, storefront API key, customer token, cookie, atau credential di JavaScript halaman.
  • Gunakan method window.Scalev yang terdokumentasi, bukan URL Scalev privat atau API privat.
  • Buat order hanya setelah pengunjung sengaja submit form.
  • Utamakan Scalev.checkout.createOrder() saat submit; method ini memvalidasi payload sebelum order disimpan.
  • Gunakan hanya produk, bundle, harga, inventory, payment method, opsi pengiriman, dan identitas customer yang ada di runtime data.

Scalev.data.get()

Mengembalikan data publik halaman yang diinjeksi ke halaman yang dirender.
const data = Scalev.data.get();
Contoh response:
{
  "page": {
    "id": 1,
    "uniqueId": "pageUid",
    "username": "brand"
  },
  "store": {
    "id": 1,
    "uniqueId": "storeUid",
    "name": "Main Store",
    "paymentMethodOptions": [
      {
        "value": "bt:BCA:paymentAccountUid",
        "display": "Bank Central Asia",
        "logoUrl": "https://cdn.scalev.com/icons/BT_BCA.png"
      },
      {
        "value": "cod",
        "display": "COD",
        "logoUrl": "https://cdn.scalev.com/icons/cod.png"
      }
    ],
    "products": [
      {
        "id": 1,
        "name": "Product",
        "variants": [
          {
            "id": 10,
            "uniqueId": "variantUid",
            "name": "Default",
            "price": 99000,
            "availableQty": 12
          }
        ]
      }
    ],
    "bundlePriceOptions": [
      {
        "id": 20,
        "uniqueId": "bundleOptionUid",
        "name": "Bundle",
        "price": 179000
      }
    ]
  },
  "afterCheckout": {
    "type": "other_page",
    "otherPagePath": "/thank-you"
  }
}
Gunakan store.paymentMethodOptions untuk render pilihan payment. Render display, tampilkan logoUrl, dan submit value yang dipilih sebagai paymentMethod. Value payment option sudah diratakan:
  • va:BRI berarti virtual account BRI.
  • bt:BCA:paymentAccountUid berarti bank transfer manual untuk akun BCA tersebut.
  • Value seperti cod, qris, invoice, alfamart, atau gopay tetap memakai nilai aslinya.

Method lokasi

Gunakan method ini untuk form alamat dan pengiriman.
const provinces = await Scalev.location.provinces();
const cities = await Scalev.location.cities(provinces[0].id);
const subdistricts = await Scalev.location.subdistricts(cities[0].id);
const postalCodes = await Scalev.location.postalCodes(subdistricts[0].id);
provinces, cities, dan subdistricts menerima query object opsional:
const provinces = await Scalev.location.provinces({ search: "Jawa" });
Response province dan city memakai { id, name }. Response subdistrict memakai id dan name untuk subdistrict, ditambah cityName, provinceName, dan display untuk label alamat. Contoh response:
[
  {
    "id": 31,
    "name": "DKI Jakarta"
  }
]
[
  {
    "id": 3171,
    "name": "Kota Jakarta Pusat"
  }
]
[
  {
    "id": 9090,
    "name": "Gambir",
    "cityName": "Kota Jakarta Pusat",
    "provinceName": "DKI Jakarta",
    "display": "Gambir, Kota Jakarta Pusat, DKI Jakarta"
  }
]
[
  {
    "postalCode": "10110"
  }
]

Scalev.checkout.validateDiscount(payload)

Memvalidasi kode diskon untuk payload checkout.
const result = await Scalev.checkout.validateDiscount({
  discountCode: "PROMO10",
  grossRevenue: 179000,
  netProductPrice: 179000,
  shippingCost: 0,
  paymentMethod: store.paymentMethodOptions?.[0]?.value || "cod"
});
Contoh response:
{
  "discountCode": {
    "code": "PROMO10",
    "appliedTo": "product_price",
    "amountType": "fixed",
    "amount": 10000,
    "isEnabled": true
  },
  "eligibilityDetails": {
    "isEnabled": true,
    "isExpiryCheck": true,
    "isUsageLimitCheck": true,
    "isMinimumRevenueCheck": true,
    "isLimitedToPagesCheck": true,
    "isLimitedToPaymentMethodsCheck": true,
    "isPageDiscountActive": true,
    "isAmountNotZero": true
  },
  "isEligible": true,
  "discountCodeDiscount": 10000
}

Scalev.checkout.shippingOptions(payload)

Mengembalikan opsi pengiriman untuk item, tujuan, dan payment method yang dipilih. Gunakan ini sebagai satu-satunya method lookup pengiriman.
const shippingOptions = await Scalev.checkout.shippingOptions({
  paymentMethod: selectedPaymentOption.value,
  destination: {
    subdistrictId: selectedSubdistrictId,
    postalCode: selectedPostalCode
  },
  items: [
    {
      type: "product",
      variantUniqueId: firstVariant.uniqueId,
      quantity: 1
    }
  ]
});
Kirim option yang dipilih sebagai satu field shipping di estimateSummary dan createOrder. Runtime akan menyiapkan request checkout dari option tersebut. Opsi dapat berisi logoUrl saat courier code tersedia. Contoh response:
[
  {
    "courierServiceId": 48,
    "courierCode": "anteraja",
    "serviceCode": "ND",
    "name": "Next Day",
    "cost": 15300,
    "etd": "1",
    "isCod": false,
    "warehouseUniqueId": "warehouseUid",
    "courierAggregatorCode": null,
    "logoUrl": "https://cdn.scalev.com/assets/images/kurir/anteraja.png"
  }
]
Payload method yang direkomendasikan:
{
  "items": [
    { "type": "product", "variantUniqueId": "variantUid", "quantity": 1 },
    {
      "type": "bundle",
      "bundlePriceOptionUniqueId": "bundleOptionUid",
      "quantity": 1
    }
  ],
  "destination": { "subdistrictId": 12345, "postalCode": "10110" },
  "paymentMethod": "cod"
}

Scalev.checkout.estimateSummary(payload)

Mengembalikan ringkasan checkout untuk halaman yang menampilkan breakdown biaya sebelum submit. Method ini opsional. Kirim item, destination, payment, dan shipping yang sama seperti payload yang akan dikirim ke Scalev.checkout.createOrder(payload). Hasil method ini tidak menggantikan validasi pembuatan order. Scalev tetap memvalidasi dan menerapkan shipping final, discount, biaya tambahan, dan total saat order dibuat.
const shipping = shippingOptions[0];

const payload = {
  destination: { subdistrictId: 12345, postalCode: "10110" },
  items: [
    { type: "product", variantUniqueId: firstVariant.uniqueId, quantity: 1 },
    {
      type: "bundle",
      bundlePriceOptionUniqueId: firstBundlePriceOption.uniqueId,
      quantity: 1
    }
  ],
  paymentMethod: selectedPaymentOption.value,
  shipping
};

const summary = await Scalev.checkout.estimateSummary(payload);
Payload method yang direkomendasikan:
{
  "items": [
    { "type": "product", "variantUniqueId": "variantUid", "quantity": 1 },
    {
      "type": "bundle",
      "bundlePriceOptionUniqueId": "bundleOptionUid",
      "quantity": 1
    }
  ],
  "destination": { "subdistrictId": 12345, "postalCode": "10110" },
  "paymentMethod": "cod",
  "shipping": {
    "courierServiceId": 48,
    "courierCode": "anteraja",
    "serviceCode": "ND",
    "name": "Next Day",
    "cost": 15300,
    "etd": "1",
    "isCod": false,
    "warehouseUniqueId": "warehouseUid",
    "courierAggregatorCode": null,
    "logoUrl": "https://cdn.scalev.com/assets/images/kurir/anteraja.png"
  }
}
Contoh response:
{
  "productPrice": 268000,
  "shippingCost": 15300,
  "otherIncome": 0,
  "otherIncomeName": "Biaya Lainnya",
  "grossRevenue": 273300
}
Gunakan estimateSummary hanya saat UI checkout menampilkan total sebelum submit. Jangan hitung atau submit otherIncome atau otherIncomeName; Scalev menghitung biaya tambahan yang dikonfigurasi di store pada estimateSummary dan menerapkannya lagi saat createOrder.

Scalev.checkout.createOrder(payload)

Membuat public order sungguhan dan memvalidasi payload. Panggil method ini hanya setelah pengunjung sengaja submit form.
async function submitOrder(event) {
  event.preventDefault();

  const data = Scalev.data.get();
  const store = data.store;
  const firstVariant = store.products[0].variants[0];
  const selectedPaymentOption = store.paymentMethodOptions[0];
  const selectedSubdistrictId = 12345;
  const selectedPostalCode = "10110";
  const items = [
    { type: "product", variantUniqueId: firstVariant.uniqueId, quantity: 1 }
  ];
  const destination = {
    subdistrictId: selectedSubdistrictId,
    postalCode: selectedPostalCode
  };
  const shippingOptions = await Scalev.checkout.shippingOptions({
    paymentMethod: selectedPaymentOption.value,
    destination,
    items
  });
  const shipping = shippingOptions[0];

  const payload = {
    customer: {
      name: event.currentTarget.elements.customerName.value,
      phone: event.currentTarget.elements.customerPhone.value,
      email: event.currentTarget.elements.customerEmail.value
    },
    destination: {
      address: event.currentTarget.elements.address.value,
      ...destination
    },
    items,
    paymentMethod: selectedPaymentOption.value,
    shipping
  };

  const order = await Scalev.checkout.createOrder(payload);
  return order;
}
Field payload yang didukung:
  • Object customer: customer.name, customer.phone, customer.email
  • Object destination: destination.address, destination.subdistrictId, destination.postalCode
  • Field payment: paymentMethod
  • List item: items[] dengan { type: "product", variantUniqueId, quantity } atau { type: "bundle", bundlePriceOptionUniqueId, quantity }
  • Field discount: discountCode
Jangan submit field product discount atau shipping discount di level atas. Harga produk dan penyesuaian item-level berada di items[] saat dibutuhkan. Gunakan validateDiscount untuk melihat estimasi discount code yang eligible, lalu kirim kode terpilih sebagai discountCode ke createOrder. Untuk pilihan pengiriman, panggil Scalev.checkout.shippingOptions(payload), biarkan pengunjung memilih satu option, lalu kirim seluruh option itu sebagai shipping ke summary dan order. Payload method yang direkomendasikan:
{
  "customer": {
    "name": "Customer Name",
    "phone": "08123456789",
    "email": "customer@example.com"
  },
  "destination": {
    "address": "Customer address",
    "subdistrictId": 12345,
    "postalCode": "10110"
  },
  "items": [
    { "type": "product", "variantUniqueId": "variantUid", "quantity": 1 }
  ],
  "paymentMethod": "cod",
  "shipping": {
    "courierServiceId": 48,
    "courierCode": "anteraja",
    "serviceCode": "ND",
    "name": "Next Day",
    "cost": 15300,
    "etd": "1",
    "isCod": false,
    "warehouseUniqueId": "warehouseUid",
    "courierAggregatorCode": null,
    "logoUrl": "https://cdn.scalev.com/assets/images/kurir/anteraja.png"
  },
  "discountCode": "PROMO10",
  "eventSourceUrl": "https://brand.myscalev.com/page",
  "utmSource": "ads"
}
Untuk payment selection, render store.paymentMethodOptions[].display, render gambar payment dari store.paymentMethodOptions[].logoUrl, dan submit hanya value option terpilih sebagai paymentMethod. Contoh response:
{
  "orderId": "260601HPQSPBX",
  "status": "pending",
  "paymentStatus": "unpaid",
  "secretSlug": "orderSecretSlug",
  "publicOrderUrl": "https://brand.myscalev.com/order/orderSecretSlug",
  "paymentUrl": null,
  "productPrice": "90000.00",
  "productDiscount": "0.00",
  "shippingCost": "15300.00",
  "shippingDiscount": "0.00",
  "discountCodeDiscount": "10000.00",
  "otherIncome": "0.00",
  "otherIncomeName": "Biaya Lainnya",
  "grossRevenue": "95300.00",
  "paymentMethod": "bank_transfer",
  "paymentAccount": {
    "uniqueId": "paymentAccountUid",
    "financialEntityName": "Bank Central Asia",
    "accountNumber": "1234567890"
  },
  "courierService": {
    "id": 48,
    "name": "Next Day",
    "courier": {
      "name": "AnterAja",
      "code": "anteraja"
    }
  },
  "variants": {},
  "bundlePriceOptions": {
    "Bundle": {
      "bundlePriceOptionUniqueId": "bundleOptionUid",
      "quantity": 1
    }
  },
  "handlerPhone": null,
  "chatMessage": null
}

Error handling

Runtime method menolak Promise dengan JavaScript Error. Gunakan error.message untuk copy UI. Gunakan error.status, error.data, dan Scalev.diagnostics.get() hanya untuk debugging.
try {
  const order = await Scalev.checkout.createOrder(payload);
  return order;
} catch (error) {
  showFormError(error.message || "Order creation failed.");
}

Scalev.analytics.track(provider, payload)

Meneruskan event analytics yang dikonfigurasi melalui Scalev.
await Scalev.analytics.track("facebook", {
  firstName: "Customer",
  phone: "08123456789",
  variants: [{ uniqueId: "variantUid", quantity: 1, price: 179000 }],
  events: [
    {
      eventName: "Lead",
      parameters: { value: 179000, currency: "IDR" }
    }
  ]
});
Nama provider yang didukung:
  • facebook
  • tiktok
  • kwai
Contoh response:
null
Jika provider tidak dikirim, runtime melewati call tanpa menghubungi Scalev:
{
  "skipped": true,
  "reason": "missing_analytics_provider"
}
Jika request analytics gagal, checkout flow harus tetap berjalan dan runtime mengembalikan:
{
  "skipped": true,
  "reason": "analytics_request_failed"
}

Scalev.prefill.get()

Membaca data prefill form yang aman untuk browser ini.
const prefill = await Scalev.prefill.get();
const customerName = prefill.customer?.name || "";
const customerPhone = prefill.customer?.phone || "";
const destinationAddress = prefill.destination?.address || "";
Contoh response:
{
  "customer": {
    "name": "Customer Name",
    "phone": "08123456789",
    "email": "customer@example.com"
  },
  "destination": {
    "address": "Jl. Contoh No. 1",
    "subdistrictId": 9104,
    "postalCode": "12250"
  }
}

Scalev.prefill.save(form, metadata)

Menyimpan data prefill form yang aman di cookie terenkripsi scv_fd. Ini ditangani lokal oleh fe-public dan tidak memanggil Storefront atau page runtime API endpoint.
await Scalev.prefill.save(
  {
    customer: {
      name: "Customer Name",
      phone: "08123456789",
      email: "customer@example.com"
    },
    destination: {
      address: "Jl. Contoh No. 1",
      subdistrictId: 9104,
      postalCode: "12250"
    }
  },
  {
    source: "checkout_form"
  }
);
Contoh response:
{
  "saved": true
}

Scalev.diagnostics.get()

Mengembalikan runtime diagnostics terbaru untuk debugging.
const diagnostics = Scalev.diagnostics.get();
Contoh response:
[
  {
    "level": "error",
    "code": "runtime_request_failed",
    "message": "Scalev runtime request failed.",
    "details": {
      "path": "/pages/pageUid/orders",
      "status": 422,
      "response": {
        "message": "customer.phone: can't be blank"
      }
    },
    "timestamp": "2026-06-01T08:00:00.000Z"
  }
]