---
type: tutorial
title: Kemudikan verifikasi sendiri dengan mode manual
summary: Mode manual membiarkan kodemu sendiri mengemudikan siklus hidup verifikasi. Ia ada di dua elemen (widget checkbox dan host game) dengan pekerjaan berbeda; halaman ini membangun keduanya dan menunjukkan kapan memakai masing-masing.
---

Di akhir tutorial ini kamu akan telah mengemudikan siklus hidup verifikasi Caputchin dari kodemu sendiri alih-alih UI bawaan, pada mana pun dari dua elemen yang cocok dengan kasusmu. **Mode manual** (`trigger="manual"`) ada di dua elemen berbeda, dan mereka melakukan pekerjaan yang sungguh berbeda:

| Elemen | Apa yang diberikan mode manual | Kamu kemudikan |
|---|---|---|
| `<caputchin-widget>` | Checkbox bawaan disembunyikan; kamu menembakkan pemecahan proof-of-work dari **pemicumu sendiri** (sebuah submit formulir, tombol kustom). Tanpa game. | `start()` (lalu pemecahan biasanya selesai sendiri) |
| `<caputchin-game>` | Tanpa iframe; kamu menyelipkan **markup game-mu sendiri** ke shell tata-letak widget dan memutuskan hasil dari gameplay. | `pass()` / `fail()` (tanpa `start()`; ronde hidup saat mount) |

Pilih berdasarkan pertanyaan yang kamu jawab:

- *"Aku mau verifikasi tak-kasatmata/checkbox normal, tapi dipicu oleh gestur-ku sendiri dan tanpa checkbox baku."* → **widget checkbox**, di bawah.
- *"Aku mau tantangan interaktifku sendiri dirender di DOM-ku sendiri, bukan game iframe, dan aku memutuskan lolos/gagal."* → **host game**, di bawah.

Baca [jalankan game-mu sendiri](/docs/custom-game-development/overview) untuk di mana jalur game cocok. Kamu butuh widget di halamanmu sudah; jika tidak, lakukan [tambahkan widget](/docs/getting-started/add-the-widget) dulu.

Satu batas yang dibagi keduanya: ronde mode-manual **tak bisa memenuhi [gerbang game](/docs/site-keys/games)**. Elemen checkbox tak pernah menggerbang sebuah key sama sekali (hanya `<caputchin-game>` yang bisa), dan ronde `<caputchin-game>` manual tak punya trace yang bisa-diputar-ulang, jadi key bergerbang menolaknya. Mode manual untuk key tak-bergerbang (verifikasi proof-of-work) atau pemakaian hanya-game.

## Jalur A: widget checkbox, pemicumu sendiri

Pakai ini saat kamu mau verifikasi standar tapi ingin menembakkannya sendiri, misalnya untuk menjalankan pemecahan hanya saat pengunjung mengirim formulir, atau di balik tombolmu sendiri alih-alih checkbox bawaan.

### 1. Tandai elemen manual

```html
<caputchin-widget id="cap" sitekey="cpt_pub_..." trigger="manual"></caputchin-widget>
<button id="go" type="button">Verify and continue</button>
```

Dengan `trigger="manual"`, UI checkbox bawaan disembunyikan; elemen menunggu kamu memulai pemecahan.

### 2. Mulai pemecahan dari gesturmu

Elemen checkbox dalam mode manual memaparkan satu metode, `start()`:

- `start()` memicu pemecahan proof-of-work, menggantikan klik checkbox. Sah dengan `trigger="manual"`.

Widget checkbox tak punya `pass()` / `fail()`; begitu kamu memanggil `start()`, pemecahan selesai sendiri dan memancarkan event `pass`. (Handle release/abort hidup di host game, dibahas di Jalur B.)

```js
const widget = document.getElementById("cap");

document.getElementById("go").addEventListener("click", () => {
  widget.start(); // begin verification now
});

widget.addEventListener("pass", () => {
  // token issued; submit your form / continue
});
```

Saat pemecahan selesai, elemen menuntaskan verifikasi dan (di sebuah formulir) menyuntikkan field `caputchin-token` seperti widget lain mana pun. Backend-mu [memverifikasi token itu](/docs/integration-guides/verify-on-your-backend) persis seperti biasa; mode manual tak mengubah apa pun di sisi-server.

## Jalur B: host game, DOM-mu sendiri

Pakai ini saat kamu mau merender tantangan interaktifmu sendiri di markup-mu sendiri, alih-alih memuat game iframe, dan memutuskan hasilnya sendiri.

### 1. Tandai elemen manual dan selipkan markup-mu

Taruh `trigger="manual"` pada `<caputchin-game>` dan tempatkan markup-mu sendiri di dalamnya. Di setiap mode lain widget mengabaikan anak light-DOM; mode manual adalah satu mode di mana ia memproyeksikannya ke shell tata-letaknya lewat sebuah `<slot>`.

```html
<caputchin-game id="cap" sitekey="cpt_pub_..." trigger="manual">
  <!-- Your own markup. The widget renders it inside its shell. -->
  <div id="my-game">
    <p>Tap the banana three times.</p>
    <button id="banana" type="button">🍌</button>
  </div>
</caputchin-game>
```

Dengan sitekey hadir dan key tak bergerbang, widget menjalankan pemeriksaan proof-of-work-nya di latar; interaksimu adalah bagian yang terlihat. Tanpa sitekey (atau `no-verify`), ia hanya-game: interaksimu berjalan tanpa apa pun untuk diverifikasi.

### 2. Kemudikan hasil dari kodemu

Host game dalam mode manual memaparkan `pass()` dan `fail()`. Tak ada **`start()`**: ronde hidup begitu elemen mount (factory yang ter-mount adalah sinyal mulai).

- `pass(payload?)` melepaskan verifikasi: pengunjung berhasil. Panggil ia sekali; panggilan berikutnya diabaikan (vonis terkunci).
- `fail(payload?)` membatalkan ronde. Opsional; ronde yang tak selesai diperlakukan sebagai non-lolos toh.

Payload-nya:

- `pass({ trace })`: `trace` adalah catatan ronde opaque yang dihasilkan interaksimu. Pada ronde bergerbang server memutarnya-ulang untuk vonis; pada key tak-bergerbang atau hanya-game ia diterima apa adanya, jadi lewatkan string kosong (atau penanda sederhana) saat tak ada yang diputar-ulang. Tak ada skor yang dipasok-klien di sini.
- `fail({ code?, message? })`: `code` dan `message` diagnostik opsional, keduanya metadata klien, tak pernah sinyal kepercayaan.

```js
const widget = document.getElementById("cap");
let taps = 0;

document.getElementById("banana").addEventListener("click", () => {
  taps += 1;
  if (taps >= 3) {
    widget.pass({ trace: `banana:${taps}` }); // visitor won
  }
});

// Optional: give up explicitly.
// widget.fail({ code: "gave-up", message: "closed the prompt" });
```

Seperti dengan jalur checkbox, `pass()` menuntaskan verifikasi dan menyuntikkan token; backend-mu memverifikasinya dengan cara yang sama.

## Bereaksi terhadap hasil (kedua jalur)

Dengarkan event widget untuk memperbarui UI-mu sendiri:

```js
widget.addEventListener("pass", () => {
  // verification released
});
widget.addEventListener("error", (e) => {
  console.warn("verification error", e.detail);
});
```

Keputusan kepercayaan selalu backend-mu yang memastikan token, bukan event; event untuk UX.

## Apa yang tak bisa dilakukan mode manual

- **Menggerbang sebuah kunci situs.** Sebuah key dengan [wajibkan game](/docs/site-keys/games) menyala tak bisa dipenuhi elemen checkbox sama sekali, dan menolak `<caputchin-game>` manual (ia memunculkan galat konfigurasi saat penyiapan) karena tak ada trace yang bisa-diputar-ulang. Mode manual untuk key tak-bergerbang atau hanya-game.
- **Memutar-ulang ronde game kustom.** Jika kamu butuh game yang menggerbang, render ia sebagai [game iframe swahosting](/docs/custom-game-development/self-hosted-game) dan hasilkan sebuah trace, bukan mode manual.

## Lihat juga

- [Metode dan event widget](/docs/references/widget-methods-and-events): referensi penuh untuk `start()` / `pass()` / `fail()` dan setiap event yang mereka pancarkan.
- [Game iframe swahosting](/docs/custom-game-development/self-hosted-game): game ber-sandbox, bisa-diputar-ulang yang bisa menggerbang.
- [Jalankan game-mu sendiri](/docs/custom-game-development/overview): dua mode pengiriman dibandingkan.
- [Verifikasi di backend-mu](/docs/integration-guides/verify-on-your-backend): memastikan token yang dihasilkan sebuah pass.
