# Double opt-in untuk formulir newsletter buatan Anda sendiri

> Ikiform tidak mengirim email konfirmasi, jadi double opt-in berjalan di alat email Anda: relay menambahkan setiap pendaftaran sebagai belum terkonfirmasi dan alat itu mengirim tautannya.

Terbit 2026-10-25 · https://ikiform.com/id/guides/newsletter-signup/double-opt-in

Ikiform tidak pernah mengirim email ke orang yang mendaftar, jadi email konfirmasi harus datang dari alat yang mengirim newsletter Anda. Relay menerima webhook bertanda tangan dari Ikiform dan menambahkan pembaca ke alat itu sebagai belum terkonfirmasi, alat itu mengirimi mereka tautan, dan hanya klik yang menjadikan mereka subscriber. Setiap alat mengaktifkan ini dengan cara berbeda, dan relay tidak boleh mengirim konfirmasi kedua ke orang yang sudah berlangganan.

## Apa yang berbeda di sini

Ikiform tidak mengirim email ke orang yang mengisi formulir. Email notifikasi hanya dikirim ke Anda dan tim Anda, jadi tidak ada autoresponder, email konfirmasi, atau double opt-in. Kirim semua itu dari alat email Anda, dipicu oleh [webhook](https://ikiform.com/id/docs/webhooks.md). Dengan embed dari penyedia, konfirmasi adalah pengaturan di formulir penyedia. Dengan formulir sendiri, ada dua sistem yang terlibat, dan konfirmasi menjadi milik sistem yang menyimpan daftar. Pekerjaannya adalah memastikan setiap pendaftaran sampai ke alat itu dalam status yang memicu konfirmasinya, dan tidak memicunya saat tidak seharusnya.

Double opt-in adalah state machine di dalam alat email. Pembaca mulai dalam status belum terkonfirmasi, tidak bisa dikirimi edisi, dan baru menjadi subscriber saat mereka mengklik. Bagian Ikiform berakhir saat relay menjawab `204`.

Diagram: Perjalanan pendaftaran double opt-in, dari formulir hingga subscriber terkonfirmasi

1. Pembaca mencentang kotak persetujuan dan mengirim formulir Anda, yang mengirim ke Ikiform.
2. Ikiform menyimpan pendaftaran dan mengirim webhook bertanda tangan ke relay Anda.
3. Relay memverifikasi tanda tangan dan menambahkan pembaca ke alat email sebagai belum terkonfirmasi.
4. Alat email mengirimi pembaca tautan konfirmasi.
5. Jika mereka mengklik, alat menandai mereka terkonfirmasi dan mengirimi mereka setiap edisi.
6. Jika mereka tidak pernah mengklik, mereka tetap belum terkonfirmasi dan tidak menerima newsletter.

Semua setelah relay terjadi di alat email, termasuk kata-kata email konfirmasi, halaman yang dibuka tautan, dan pengingat.

## Pengaturan di setiap alat

Setiap alat punya konsep belum terkonfirmasi sendiri, dan caranya sendiri untuk menjadikan subscriber baru dari API berstatus itu. Salah langkah di sini dan subscriber ditambahkan sebagai sudah terkonfirmasi, tanpa email sama sekali:

| Alat | Cara pendaftaran lewat API mendapat email konfirmasi | Jebakannya |
| --- | --- | --- |
| [Kit](https://ikiform.com/id/guides/newsletter-signup/kit.md) | Buat subscriber dengan `state: "inactive"`, lalu tambahkan ke formulir yang incentive email-nya aktif. Dokumentasi bulk form Kit menyatakan ini mengirim incentive email; uji endpoint tunggalnya dengan alamat milik Anda | Create subscriber default-nya `state: "active"`, dan state tidak bisa diubah setelahnya lewat endpoint itu |
| [MailerLite](https://ikiform.com/id/guides/newsletter-signup/mailerlite.md) | Aktifkan **Double opt-in for API and integrations** di pengaturan subscribe. Kirim juga `status: "unconfirmed"`, yang dibutuhkan MailerLite sebelum mengirim email ke subscriber yang sudah ada | Mengirim `unconfirmed` untuk alamat yang sudah aktif akan meminta mereka mengonfirmasi lagi |
| [beehiiv](https://ikiform.com/id/guides/newsletter-signup/beehiiv.md) | Kirim `double_opt_override: "on"` saat create subscription, atau `"not_set"` untuk memakai pengaturan publikasi sendiri | `"off"` langsung membuat subscriber aktif, tanpa email |

Uji masing-masing dengan alamat milik Anda sebelum mengandalkannya. Pengaturan alat bisa berubah, dan email itu sendiri diatur di alat: subjek, kata-kata, dan halaman yang dibuka tautannya.

## Relay yang mengonfirmasi sekali

Relay biasa meminta konfirmasi setiap kali webhook datang. Dua kasus membuat itu keliru: pembaca yang mengirim tiga kali dalam semenit mendapat tiga email, dan bot yang mendaftarkan alamat korban membuat konfirmasi Anda masuk ke inbox korban itu setiap kali mencoba. Cloudflare Worker ini meminta alat mengirim paling banyak satu konfirmasi per alamat per hari:

`src/index.ts`:

```ts
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
import { addUnconfirmed } from "./tool";

export interface Env {
  IKIFORM_WEBHOOK_SECRET: string;
  TOOL_API_KEY: string;
  SEEN: KVNamespace;
}

const DAY = 86_400;

async function digest(text: string) {
  const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
  return [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

export default {
  async fetch(request: Request, env: Env) {
    if (request.method !== "POST") return new Response(null, { status: 405 });
    const payload = await request.text();
    let event;
    try {
      event = await verifyWebhook({ payload, headers: request.headers, secret: env.IKIFORM_WEBHOOK_SECRET });
    } catch (error) {
      if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
      throw error;
    }
    if (event.type !== "submission.created" || event.data.fields.consent !== true) {
      return new Response(null, { status: 204 });
    }

    const email = String(event.data.fields.email).trim().toLowerCase();
    const key = `confirm:${await digest(email)}`;
    if (await env.SEEN.get(key)) return new Response("Confirmation already requested today", { status: 200 });

    const answer = await addUnconfirmed(env, email, event.data.fields.first_name);
    if (answer.status === 429) {
      return new Response("Rate limited", { status: 503, headers: { "retry-after": answer.headers.get("retry-after") ?? "60" } });
    }
    if (!answer.ok) return new Response(`Email tool answered ${answer.status}`, { status: 502 });

    await env.SEEN.put(key, event.id, { expirationTtl: DAY });
    return new Response(null, { status: 204 });
  },
};
```

`wrangler.jsonc`:

```json
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "newsletter-relay",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "routes": [{ "pattern": "hooks.example.com", "custom_domain": true }],
  "kv_namespaces": [{ "binding": "SEEN", "id": "<your KV namespace id>" }]
}
```

- `addUnconfirmed` di `./tool` adalah panggilan alat dari tabel di atas. Salin isinya dari halaman Kit, MailerLite, atau beehiiv.
- Key KV adalah SHA-256 dari alamat dalam huruf kecil, jadi store tidak pernah menyimpan alamat itu sendiri. Key kedaluwarsa setelah satu hari.
- Key hanya ditulis setelah alat menerima request. Jika alat gagal, Ikiform mencoba ulang dan percobaan ulang itu tidak terhalang.
- Menjawab `200` untuk pengulangan memberi tahu Ikiform bahwa pengiriman berhasil, jadi tidak dicoba ulang, dan body-nya menjelaskan alasannya di log pengiriman.
- Worker berjalan di domain kustom. Ikiform menolak hostname `workers.dev` sebagai URL webhook. [Dokumentasi webhook](https://ikiform.com/id/docs/webhooks.md) mendaftar setiap aturan URL dan arti setiap jawaban, dan [server Anda sendiri](https://ikiform.com/blog/form-submissions-to-your-own-server.md) menunjukkan relay yang menyimpan setiap pengiriman sekali saja.

> KV bersifat eventually consistent antarlokasi, jadi dua pengiriman untuk alamat yang sama dalam beberapa detik bisa sama-sama lolos. Itu bisa diterima untuk email konfirmasi. Jika Anda butuh jaminan ketat, simpan key di Durable Object atau database dengan kolom unik.

## Apa yang sebaiknya disampaikan formulir

Pembaca yang melihat "Terima kasih sudah berlangganan" lalu tidak menemukan apa pun di folder newsletter-nya mengira prosesnya gagal. Beri tahu apa yang terjadi selanjutnya, di halaman tempat mereka mendarat:

1. Atur baris sukses, atau halaman terima kasih Anda, untuk menyatakan ada email yang perlu dibuka: "Hampir selesai. Buka email yang kami kirim dan konfirmasi alamat Anda."
2. Sebutkan nama pengirim yang perlu mereka cari, dan sarankan folder spam jika tidak ada yang masuk dalam beberapa menit.
3. Di alat email, atur halaman yang dibuka tautan konfirmasi ke halaman "Anda sudah berlangganan" milik Anda sendiri, agar perjalanannya berakhir di situs Anda.

Checkbox persetujuan di formulir dan email konfirmasi menjalankan tugas berbeda. Checkbox mencatat bahwa seseorang menyatakan ya di halaman Anda. Klik membuktikan bahwa alamat itu milik orang yang menyatakan ya. Sebagian besar daftar menginginkan keduanya. [Template formulir newsletter](https://ikiform.com/forms/newsletter-signup) punya checkbox wajib itu.

## Hal yang sering menjebak

- **Subscriber yang sudah ada.** Seseorang yang sudah terkonfirmasi mendaftar lagi dari halaman baru. Jangan kembalikan mereka ke status belum terkonfirmasi; [halaman MailerLite](https://ikiform.com/id/guides/newsletter-signup/mailerlite.md) menunjukkan relay yang mencari alamatnya lebih dulu.
- **Orang yang sudah berhenti berlangganan.** Pendaftaran tidak selalu berarti izin untuk membatalkan unsubscribe. beehiiv hanya mengaktifkan kembali saat Anda mengirim `reactivate_existing: true`, dan MailerLite hanya berlangganan ulang dengan `resubscribe: true`. Kirim keduanya hanya jika formulir menyatakannya.
- **Pemindai tautan.** Sebagian filter email perusahaan membuka tautan di email masuk untuk memeriksanya. Jika alat mengonfirmasi hanya dengan memuat halaman, pemindai bisa mengonfirmasi alamat yang tidak pernah diklik siapa pun. Periksa apakah halaman konfirmasi alat Anda meminta penekanan tombol.
- **Deliverability.** Konfirmasi adalah email pertama yang diterima pembaca dari Anda. Kirim dari domain yang terautentikasi di alat Anda, atau email itu masuk ke spam dan pendaftarannya tidak pernah selesai.
- **Orang yang belum terkonfirmasi menumpuk.** Mereka belum menjadi subscriber. Putuskan di alat Anda apakah akan mengirim pengingat, lalu biarkan saja.

## Pastikan berfungsi

1. Kirim formulir dengan alamat milik Anda. Halaman meminta Anda memeriksa inbox.
2. Buka pengiriman di **Webhooks** di Ikiform. Statusnya `succeeded` dengan `204` dari relay.
3. Buka subscriber di alat email Anda. Statusnya unconfirmed, inactive, atau pending, tergantung alatnya.
4. Buka email konfirmasi dan klik. Subscriber menjadi aktif atau terkonfirmasi.
5. Kirim alamat yang sama lagi dalam sehari. Pengiriman menampilkan `200` dengan "Confirmation already requested today", dan tidak ada email kedua yang datang.
6. Daftarkan alamat yang sudah terkonfirmasi. Alamat itu tetap terkonfirmasi dan tidak mendapat email konfirmasi baru.

## Pertanyaan

### Bisakah Ikiform mengirim email konfirmasi double opt-in?

Tidak. Ikiform tidak pernah mengirim email ke orang yang mengirim formulir. Alat email Anda yang mengirim konfirmasi, dipicu oleh webhook Ikiform melalui relay atau alat otomasi.

### Apakah saya masih butuh checkbox persetujuan jika memakai double opt-in?

Keduanya menjalankan tugas berbeda. Checkbox mencatat bahwa orang itu setuju di halaman Anda, lengkap dengan timestamp. Klik konfirmasi membuktikan mereka pemilik alamat itu. Sebagian besar daftar mempertahankan keduanya.

### Mengapa subscriber saya tidak mendapat email konfirmasi?

Kemungkinan besar relay membuat mereka sebagai sudah terkonfirmasi: create subscriber di Kit default-nya active, MailerLite butuh pengaturan double opt-in API-nya aktif, ditambah status unconfirmed untuk subscriber yang sudah ada, dan double_opt_override beehiiv yang diatur ke off melewati email. Periksa status subscriber di alat itu.

### Bisakah saya memakai Zapier atau Make alih-alih relay?

Bisa. Arahkan webhook Ikiform ke otomasi dan gunakan action-nya untuk alat email Anda. Pastikan opsi action itu membuat subscriber dalam status belum terkonfirmasi; Anda kehilangan pengaman sekali-sehari kecuali Anda menambahkan langkah filter.

## Panduan lainnya

- [Formulir pendaftaran newsletter](https://ikiform.com/id/guides/newsletter-signup.md): Buat formulir pendaftaran newsletter dengan markup Anda sendiri, catat persetujuan, blokir pendaftaran bot, dan teruskan setiap subscriber ke Kit, MailerLite, beehiiv, atau alat apa pun.
- [Kit (ConvertKit)](https://ikiform.com/id/guides/newsletter-signup/kit.md): Hubungkan formulir newsletter Anda sendiri ke Kit dengan relay yang membuat subscriber, menambahkannya ke formulir Kit untuk incentive email, dan memberi tag penempatannya.
- [MailerLite](https://ikiform.com/id/guides/newsletter-signup/mailerlite.md): Hubungkan formulir pendaftaran Anda sendiri ke MailerLite: relay menambahkan pembaca baru sebagai belum terkonfirmasi untuk double opt-in dan tidak pernah meminta subscriber mengonfirmasi dua kali.
- [beehiiv](https://ikiform.com/id/guides/newsletter-signup/beehiiv.md): Hubungkan formulir pendaftaran Anda sendiri ke beehiiv: relay membuat setiap subscription dengan double opt-in aktif, penempatan sebagai UTM source, dan halaman sebagai referrer.
- [Situs statis](https://ikiform.com/id/guides/newsletter-signup/static-site.md): Tambahkan formulir pendaftaran newsletter ke situs statis Hugo, Jekyll, Eleventy, atau Astro, jauhkan API key alat email dari halaman, dan lakukan konfirmasi di alat itu.
- [Formulir newsletter Next.js](https://ikiform.com/id/guides/newsletter-signup/nextjs.md): Formulir newsletter di footer Next.js: server action dengan pemeriksaan persetujuan dan Turnstile, mengirim ke Ikiform, plus route handler yang menambahkan pembaca ke Kit.
