Quick Start
Tambahkan satu baris script tag ke halaman HTML Anda. Widget akan otomatis muncul sebagai floating button di kanan bawah halaman.
<script
src="https://cdn.ztakonai.com/widget.js"
data-widget-id="wgt_abc123"
data-api-key="tk_live_xxxx">
</script>htmlScript Tag Attributes
| Attribute | Required | Description |
|---|---|---|
data-widget-id* | string | Widget ID dari TakonAI dashboard (format: wgt_...) |
data-api-key* | string | Public API key dari TakonAI dashboard (format: tk_live_...) |
data-base-url | string | Override URL widget — hanya untuk development/staging. Default: https://cdn.ztakonai.com |
Embed Guide
Widget bekerja dengan menginjeksi sebuah <iframe> ke halaman Anda. Komunikasi antara halaman host dan widget dilakukan via postMessage.
Cara Kerja
- Script tag loader dieksekusi saat halaman load.
- Loader membuat floating bubble button (fixed, bottom-right, z-index 9990).
- Saat user klik bubble, iframe
/embeddiinjeksi dan chat panel dibuka. - Iframe berkomunikasi dengan halaman host via
postMessage. window.Takonaitersedia untuk kontrol programmatic setelah script dimuat.
Inisialisasi dengan User Context
Panggil window.Takonai.init() setelah halaman selesai dimuat untuk menghubungkan widget dengan sesi user Anda.
window.Takonai.init({
externalId: 'user_123', // ID unik user dari sistem Anda
currentStep: 1, // Step aktif saat ini (opsional)
context: { // Data konteks tambahan (opsional)
planType: 'pro',
cartTotal: 150000,
},
});jsMengelola Banyak Step (Multi-Step)
Untuk halaman yang memiliki urutan step — seperti form checkout atau pendaftaran wizard — Anda dapat memisahkan konfigurasi form menjadi beberapa step di dashboard TakonAI.
Di sisi frontend, Anda perlu memberitahu widget setiap kali user berpindah step menggunakan setStep(). Dengan cara ini, AI hanya memproses Tool/Form Filling yang sesuai dengan form di step yang sedang aktif.
Cara kerja multi-step
- Buat konfigurasi widget di dashboard dengan beberapa step, masing-masing memiliki form yang berbeda.
- Saat halaman pertama dimuat, panggil
init({ currentStep: 1 }). - Setiap kali user pindah ke step berikutnya, panggil
setStep(n)agar AI tahu step mana yang aktif. - AI hanya akan mengisi form di step yang sedang aktif — tidak ada kebocoran data antar step.
// Step 1 — saat halaman pertama load
window.Takonai.init({
externalId: 'usr_123',
currentStep: 1,
});
// Step 2 — saat user klik tombol "Lanjut"
function goToStep2() {
showStep(2); // tampilkan form step 2 di halaman Anda
window.Takonai.setStep(2, {
// opsional: kirim data dari step sebelumnya sebagai konteks
buyerName: document.querySelector('[name="full_name"]').value,
});
}
// Step 3 — opsional, lanjut ke step berikutnya
function goToStep3() {
showStep(3);
window.Takonai.setStep(3);
}jsGunakan callback onFill untuk mengisi form yang tepat berdasarkan step yang dikirim AI:
window.Takonai.onFill = ({ step, formName, data }) => {
// Pilih form yang sesuai dengan step aktif
const formMap = {
1: document.getElementById('form-buyer'),
2: document.getElementById('form-shipping'),
3: document.getElementById('form-payment'),
};
const formEl = formMap[step];
if (!formEl) return;
Object.entries(data).forEach(([field, value]) => {
const el = formEl.querySelector('[name="' + field + '"]');
if (el) el.value = value;
});
};jswindow.Takonai
Global object yang di-expose oleh widget loader script. Tersedia setelah script tag dimuat.
init(opts)
MethodInisialisasi widget dengan konteks user. Harus dipanggil sebelum widget bisa berinteraksi dengan data sesi Anda. Widget akan mengirim TAKONAI_INIT ke iframe dan menerima konfirmasi TAKONAI_INIT_ACK.
window.Takonai.init(opts: TakonaiInitOptions): void
interface TakonaiInitOptions {
externalId: string; // Required — ID user dari sistem Anda
currentStep?: number; // Optional — step aktif (default: 1)
context?: Record<string, unknown>; // Optional — data konteks dinamis
welcomeMessage?: string; // Optional — override pesan sapaan dari dashboard
}tsParameters
| Name | Type | Description |
|---|---|---|
externalId* | string | ID unik user dari sistem Anda. Digunakan untuk identifikasi sesi. |
currentStep | number | Step aktif saat init. Default: 1. |
context | object | Data konteks bebas yang diteruskan ke AI (kategori produk, nilai form, dll). |
welcomeMessage | string | Override pesan sapaan yang dikonfigurasi di dashboard. Berguna untuk personalisasi per-user atau per-halaman. |
Example
window.Takonai.init({
externalId: 'usr_4891',
currentStep: 2,
context: {
category: 'electronics',
priceRange: '500k-1jt',
},
welcomeMessage: 'Halo, Budi! Ada yang bisa kami bantu hari ini?',
});jssetStep(step, context?)
MethodUpdate step aktif widget, misalnya saat user berpindah halaman atau mengisi form multi-step. Mengirim pesan TAKONAI_STEP_CHANGED ke iframe.
window.Takonai.setStep(step: number, context?: Record<string, unknown>): voidtsParameters
| Name | Type | Description |
|---|---|---|
step* | number | Nomor step baru (1-indexed, sesuai konfigurasi widget di dashboard). |
context | object | Konteks baru yang akan menggantikan konteks sebelumnya. |
// User pindah ke step checkout pengiriman
window.Takonai.setStep(2, {
selectedItems: ['item_001', 'item_002'],
total: 320000,
});jssetContext(context)
MethodUpdate konteks tanpa mengubah step aktif. Berguna saat data halaman berubah tapi posisi step tidak berubah. Mengirim TAKONAI_CONTEXT_UPDATE.
window.Takonai.setContext(context: Record<string, unknown>): voidts// User memilih produk lain tanpa pindah step
window.Takonai.setContext({
selectedProduct: 'SKU-9921',
color: 'black',
size: 'XL',
});jsopen() / close()
MethodBuka atau tutup chat panel secara programmatic, tanpa user harus klik bubble button.
window.Takonai.open(): void
window.Takonai.close(): voidts// Buka widget otomatis setelah 5 detik
setTimeout(() => {
window.Takonai.open();
}, 5000);
// Tutup widget setelah form selesai diisi
window.Takonai.onFill = (payload) => {
fillMyForm(payload.data);
window.Takonai.close();
};jsonFill(payload)
CallbackDipanggil ketika AI berhasil mengisi form (tool use selesai). Gunakan callback ini untuk mengisi form di halaman Anda dengan data yang dikirim AI.
window.Takonai.onFill = (payload: TakonaiFillPayload) => void
interface TakonaiFillPayload {
step: number; // Step yang di-fill
formName: string; // Nama form (dari konfigurasi widget)
data: Record<string, unknown>; // Field-value hasil fill AI
}tsParameters
| Field | Type | Description |
|---|---|---|
step | number | Nomor step yang baru saja di-fill oleh AI. |
formName | string | Nama form sesuai konfigurasi widget di dashboard. |
data | object | Key-value hasil isian AI. Key sesuai field name di konfigurasi form. |
Example
window.Takonai.onFill = ({ step, formName, data }) => {
console.log('Form filled:', formName, data);
// Isi field HTML dengan data dari AI
Object.entries(data).forEach(([field, value]) => {
const el = document.querySelector(`[name="${field}"]`);
if (el) el.value = value;
});
};jsonError(payload)
CallbackDipanggil ketika terjadi error di dalam widget (streaming gagal, config tidak ditemukan, dll).
window.Takonai.onError = (payload: TakonaiErrorPayload) => void
interface TakonaiErrorPayload {
code: string; // Error code, contoh: 'STREAM_ERROR', 'CONFIG_NOT_FOUND'
message: string; // Pesan error human-readable
}tswindow.Takonai.onError = ({ code, message }) => {
console.error('[TakonAI]', code, message);
// Log ke Sentry, tampilkan fallback UI, dll
};jssendImage(url)
MethodLampirkan gambar dari URL publik ke composer chat widget secara programatik. Gambar belum dikirim sampai user mengetik pesan dan menekan tombol Send — sehingga Anda bisa pra-lampirkan gambar produk sebelum user mulai chat.
URL harus menggunakan skema https:// dan dapat diakses publik, karena Anthropic akan men-fetch URL tersebut langsung saat memproses pesan.
window.Takonai.sendImage(url: string): voidtsParameters
| Name | Type | Description |
|---|---|---|
url* | string | URL gambar publik (https:// wajib). Tidak mendukung base64 atau URL yang memerlukan autentikasi. |
Example
// Pra-lampirkan foto produk saat user membuka detail produk
window.Takonai.sendImage('https://cdn.toko.com/products/kaos-putih.jpg');
// User bisa langsung tanya "berapa harga ini?" dan AI sudah bisa melihat gambarnyajsCatatan
- Maksimal 3 gambar per pesan. Memanggil
sendImagesaat sudah mencapai batas akan diabaikan. - Gambar yang sudah dilampirkan via
sendImageakan dibersihkan otomatis setelah pesan terkirim. - Callback
onImageUploadakan dipanggil setiap kali gambar berhasil dilampirkan, termasuk darisendImage.
onImageUpload(payload)
CallbackDipanggil setiap kali gambar berhasil dilampirkan ke composer chat — baik via tombol paperclip di widget, paste dari clipboard, drag-and-drop, maupun panggilan sendImage().
window.Takonai.onImageUpload = (payload: TakonaiImagePayload) => void
interface TakonaiImagePayload {
url: string; // URL publik gambar di Supabase Storage (atau URL asli untuk sendImage)
mimeType: string; // MIME type gambar, contoh: "image/jpeg"
sizeBytes: number; // Ukuran file dalam bytes (0 untuk sendImage)
fileName: string; // Nama file asli
}tsParameters
| Field | Type | Description |
|---|---|---|
url | string | URL gambar yang siap diakses. Untuk upload file, ini adalah URL Supabase Storage. Untuk sendImage, ini adalah URL yang dipass. |
mimeType | string | MIME type gambar (image/jpeg, image/png, image/webp, image/gif). |
sizeBytes | number | Ukuran file dalam bytes. Bernilai 0 untuk gambar yang dilampirkan via sendImage(url). |
fileName | string | Nama file asli dari upload, atau bagian akhir URL untuk sendImage. |
Example
// Analytics: lacak setiap gambar yang diupload user
window.Takonai.onImageUpload = ({ url, mimeType, sizeBytes, fileName }) => {
console.log('Image attached:', fileName, '(' + Math.round(sizeBytes / 1024) + 'KB)');
// Contoh: tampilkan preview di sidebar halaman host
document.getElementById('image-preview').src = url;
};jspostMessage Events
Widget berkomunikasi dengan halaman host via window.postMessage. Anda dapat meng-intercept event ini langsung jika perlu kontrol lebih dalam.
Host → Widget
Pesan yang dikirim dari halaman host ke iframe widget.
| Type | Payload | Dikirim oleh |
|---|---|---|
TAKONAI_INIT | TakonaiInitOptions | window.Takonai.init() |
TAKONAI_STEP_CHANGED | { currentStep, context? } | window.Takonai.setStep() |
TAKONAI_CONTEXT_UPDATE | { context } | window.Takonai.setContext() |
TAKONAI_SEND_IMAGE | { url: string } | window.Takonai.sendImage() |
Widget → Host
Pesan yang dikirim dari iframe widget ke halaman host.
| Type | Payload | Kapan dikirim |
|---|---|---|
TAKONAI_READY | {} | Widget iframe selesai dimuat dan config berhasil di-fetch. |
TAKONAI_INIT_ACK | { widgetName, steps } | Setelah host memanggil init() dan widget memproses request. |
TAKONAI_FILL | TakonaiFillPayload | AI berhasil menggunakan tool untuk mengisi form. |
TAKONAI_IMAGE_UPLOADED | TakonaiImagePayload | Gambar berhasil dilampirkan (dari upload file atau sendImage). |
TAKONAI_ERROR | TakonaiErrorPayload | Terjadi error di dalam widget. |
Intercept Manual
// Intercept langsung jika perlu (biasanya tidak diperlukan)
window.addEventListener('message', (event) => {
if (event.data?.type === 'TAKONAI_FILL') {
console.log('Fill event:', event.data.payload);
}
});jsType Reference
// Opsi untuk window.Takonai.init()
interface TakonaiInitOptions {
externalId: string;
currentStep?: number;
context?: Record<string, unknown>;
}
// Payload dari callback onFill
interface TakonaiFillPayload {
step: number;
formName: string;
data: Record<string, unknown>;
}
// Payload dari callback onError
interface TakonaiErrorPayload {
code: string;
message: string;
}
// Payload dari callback onImageUpload
interface TakonaiImagePayload {
url: string;
mimeType: string;
sizeBytes: number;
fileName: string;
}
// Global window.Takonai object
interface TakonaiWidget {
init(opts: TakonaiInitOptions): void;
setStep(step: number, context?: Record<string, unknown>): void;
setContext(context: Record<string, unknown>): void;
open(): void;
close(): void;
sendImage(url: string): void;
onFill: ((payload: TakonaiFillPayload) => void) | null;
onError: ((payload: TakonaiErrorPayload) => void) | null;
onImageUpload: ((payload: TakonaiImagePayload) => void) | null;
}
declare global {
interface Window {
Takonai: TakonaiWidget;
}
}tsDashboard Configuration Guide
Sebelum widget bisa mengisi form, Anda perlu mengkonfigurasi Form di TakonAI dashboard. Form mendefinisikan tool yang digunakan AI untuk mengekstrak data dari percakapan dan mengirimkannya ke halaman Anda.
Konsep: Form sebagai AI Tool
Setiap form di TakonAI adalah sebuah Anthropic tool. Saat AI memutuskan data sudah cukup untuk mengisi form, ia akan memanggil tool tersebut dengan output berupa JSON yang sesuai skema yang Anda definisikan. Output inilah yang dikirim via callback onFill ke halaman Anda.
Struktur Payload Kompleks (Nested JSON)
Anthropic Tool Schema sepenuhnya mendukung stuktur nested seperti objects dan arrays. Ini sangat bermanfaat ketika Anda ingin output payload dari onFill siap pakai untuk request ke backend API Anda (seperti format produk dengan berbagai atribut dan varian).
Berikut adalah contoh konversi payload untuk produk (Tiket Wisata) yang kompleks:
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Nama produk tiket"
},
"sku": {
"type": "string",
"description": "Kode SKU tiket"
},
"description": {
"type": "string",
"description": "Deskripsi lengkap terkait produk wisata"
},
"category_id": {
"type": "integer",
"description": "ID kategori produk (misal: 3 untuk tiket wisata)"
},
"price": {
"type": "number",
"description": "Harga jual"
},
"publish_rate": {
"type": "number",
"description": "Harga coret / harga publish"
},
"product_advantages_item": {
"type": "array",
"description": "Keunggulan produk",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" }
}
}
},
"attributes": {
"type": "array",
"description": "Atribut varian (contoh: paket, waktu)",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"items": {
"type": "array",
"items": { "type": "string" }
},
"priority": { "type": "integer" }
}
}
},
"varian_items": {
"type": "array",
"description": "Kombinasi hasil varian beserta spesifikasinya",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"sku": { "type": "string" },
"price": { "type": "number" },
"stok": { "type": "integer" }
}
}
},
"tracking_adds": {
"type": "object",
"description": "Pengaturan tracking pixel",
"properties": {
"all_event": { "type": "boolean" },
"facebook_pixel": {
"type": "object",
"properties": {
"pixel_id": { "type": "array", "items": { "type": "string"} },
"event": { "type": "array", "items": { "type": "string"} }
}
}
}
}
},
"required": ["name", "sku", "description", "price", "attributes", "varian_items"]
}jsonTips Penting: Untuk skema yang sangat kompleks seperti pembuatan varian produk, disarankan menggunakan system prompt tambahan di dashboard agar AI tahu bagaimana cara mengisi field tertentu (misal: "Pastikan sku formatnya kebab-case"). Anda juga bisa langsung mem-pass sebagian struktur default (seperti properti tracking_adds) tersebut pada halaman host Anda setelah menerima callback onFill, alih-alih memaksa AI membuat keseluruhan payload statis.
Full Example
Contoh integrasi lengkap untuk form checkout multi-step. Widget di-init saat user login, step di-update saat user berpindah halaman, dan form diisi otomatis saat AI selesai.
<!DOCTYPE html>
<html>
<head>
<title>Checkout</title>
</head>
<body>
<!-- Step 1: Data Pembeli -->
<form id="form-buyer">
<input name="full_name" placeholder="Nama Lengkap" />
<input name="email" placeholder="Email" />
<input name="phone" placeholder="No. HP" />
<button type="button" onclick="goToStep2()">Lanjut</button>
</form>
<!-- Step 2: Alamat Pengiriman -->
<form id="form-shipping" style="display:none">
<input name="address" placeholder="Alamat" />
<input name="city" placeholder="Kota" />
<input name="postal_code" placeholder="Kode Pos" />
<button type="submit">Bayar</button>
</form>
<!-- 1. Embed widget -->
<script
src="https://cdn.ztakonai.com/widget.js"
data-widget-id="wgt_abc123"
data-api-key="tk_live_xxxx">
</script>
<script>
// 2. Init saat halaman load
window.Takonai.init({
externalId: 'usr_' + currentUserId,
currentStep: 1,
context: {
cartItems: 3,
totalAmount: 450000,
},
});
// 3. Isi form otomatis saat AI selesai
window.Takonai.onFill = ({ step, formName, data }) => {
const formEl = step === 1
? document.getElementById('form-buyer')
: document.getElementById('form-shipping');
Object.entries(data).forEach(([field, value]) => {
const el = formEl.querySelector('[name="' + field + '"]');
if (el) el.value = value;
});
};
// 4. Handle error
window.Takonai.onError = ({ code, message }) => {
console.error('[TakonAI Error]', code, message);
};
// 5. Update step saat user pindah halaman
function goToStep2() {
document.getElementById('form-buyer').style.display = 'none';
document.getElementById('form-shipping').style.display = 'block';
window.Takonai.setStep(2, {
buyerName: document.querySelector('[name="full_name"]').value,
});
}
</script>
</body>
</html>html