# Kirim pendaftaran dari formulir newsletter Anda sendiri ke MailerLite

> 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.

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

Kirim formulir Anda sendiri ke Ikiform dan arahkan webhook ke relay yang memanggil API MailerLite. Relay mencari alamatnya lebih dulu: pembaca baru dibuat sebagai `unconfirmed`, yang membuat MailerLite mengirim email double opt-in-nya saat pengaturan API aktif, dan subscriber yang sudah ada hanya mendapat grup baru. Pencarian itulah yang mencegah subscriber terkonfirmasi diminta mengonfirmasi lagi.

## Apa yang berbeda dengan MailerLite

Endpoint create subscriber MailerLite adalah upsert: satu `POST` ke `/api/subscribers` membuat subscriber baru atau memperbarui yang sudah ada, dengan jawaban `201` atau `200`. Endpoint ini tidak destruktif, jadi grup dan field yang tidak Anda sertakan tetap seperti semula. Masalahnya ada di `status`. Dengan pengaturan akun **Double opt-in for API and integrations** aktif, MailerLite mengirim konfirmasi ke subscriber API baru. Subscriber yang sudah ada dan berstatus active atau unsubscribed hanya mendapatkannya jika panggilan mengirim `status: "unconfirmed"`.

Bantuan MailerLite menyatakan subscriber yang sudah ada dan berstatus active atau unsubscribed tidak mendapat email konfirmasi kecuali panggilannya menyertakan `"status": "unconfirmed"`. Jadi relay yang selalu mengirim `unconfirmed` mengubah setiap pendaftaran ulang dari pembaca setia menjadi permintaan konfirmasi baru. Solusinya adalah mencari alamatnya sebelum memutuskan apa yang dikirim:

Diagram: Bagaimana relay memutuskan apa yang dikirim ke MailerLite

1. Relay memverifikasi webhook Ikiform.
2. Relay meminta subscriber berdasarkan email ke MailerLite.
3. Tidak ditemukan: relay membuatnya dengan status unconfirmed dan grup penempatannya, dan MailerLite mengirim email konfirmasi.
4. Ditemukan dan berstatus active atau unconfirmed: relay menambahkan grup tanpa status, jadi tidak ada yang berubah dari konfirmasinya.
5. Ditemukan dan berstatus unsubscribed: relay tidak melakukan apa pun, jadi pendaftaran tidak pernah diam-diam membatalkan unsubscribe.

Dua panggilan API per pendaftaran, dan yang kedua bergantung pada temuan yang pertama.

## Siapkan MailerLite

1. Di MailerLite, buka pengaturan subscribe dan aktifkan **Double opt-in for API and integrations**. Edit email konfirmasi di sana; MailerLite mengirim email yang sama ke setiap subscriber yang ditambahkan lewat API.
2. Buat grup per penempatan, seperti "Footer website" dan "Artikel blog", dan catat ID setiap grup.
3. Di **Integrations**, buat API token dan simpan untuk environment relay.

> FAQ harga MailerLite menyatakan akses API dibatasi di paket terendahnya. Uji bahwa token bisa membuat subscriber di paket Anda sebelum mengandalkannya.

## Relay

Ini adalah server Express. Server membaca raw body sebagai teks, karena tanda tangan mencakup byte persis yang dikirim Ikiform, dan mem-parsing JSON lebih dulu akan mengubahnya.

`server.ts`:

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

const API = "https://connect.mailerlite.com/api";
const GROUPS: Record<string, string> = {
  footer: process.env.MAILERLITE_GROUP_FOOTER!,
  post: process.env.MAILERLITE_GROUP_POST!,
};

function mailerlite(path: string, init: RequestInit = {}) {
  return fetch(`${API}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.MAILERLITE_API_KEY}`,
      "Content-Type": "application/json",
      Accept: "application/json",
    },
  });
}

async function subscribe(email: string, name: string | undefined, source: string) {
  const found = await mailerlite(`/subscribers/${encodeURIComponent(email)}`);
  if (found.status !== 200 && found.status !== 404) return found;

  const groups = [GROUPS[source] ?? process.env.MAILERLITE_GROUP_FOOTER!];
  const fields = name ? { name } : {};

  if (found.status === 404) {
    return mailerlite("/subscribers", {
      method: "POST",
      body: JSON.stringify({ email, fields, groups, status: "unconfirmed" }),
    });
  }

  const existing = await found.json();
  if (existing.data.status === "unsubscribed") return new Response(null, { status: 208 });
  return mailerlite("/subscribers", { method: "POST", body: JSON.stringify({ email, fields, groups }) });
}

const app = express();

app.post("/hooks/mailerlite", express.text({ type: "application/json", limit: "512kb" }), async (req, res) => {
  let event;
  try {
    event = await verifyWebhook({ payload: req.body, headers: req.headers, secret: process.env.IKIFORM_WEBHOOK_SECRET! });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return res.status(400).send(error.reason);
    return res.status(500).end();
  }
  if (event.type !== "submission.created") return res.status(204).end();

  const { email, first_name, consent, source } = event.data.fields;
  if (consent !== true || typeof email !== "string") return res.status(200).send("Skipped");

  const answer = await subscribe(
    email,
    typeof first_name === "string" ? first_name : undefined,
    typeof source === "string" ? source : "footer",
  );
  if (answer.status === 208) return res.status(200).send("Unsubscribed earlier, left alone");
  if (answer.status === 429) {
    return res.status(503).set("retry-after", answer.headers.get("retry-after") ?? "60").send("MailerLite rate limit");
  }
  if (!answer.ok) return res.status(502).send(`MailerLite answered ${answer.status}: ${await answer.text()}`);
  res.status(204).end();
});

app.listen(Number(process.env.PORT ?? 3000));
```

- MailerLite menerima token sebagai `Authorization: Bearer`. Base URL-nya `https://connect.mailerlite.com/api`.
- `GET /api/subscribers/{email}` menerima email atau ID dan menjawab `404` saat subscriber tidak ada.
- `groups` menerima ID grup yang sudah ada. ID yang salah ditolak dengan `422`, yang diteruskan relay sebagai `502` dengan pesan MailerLite.
- `fields.name` adalah field nama depan default MailerLite. Custom field harus ada di MailerLite sebelum Anda mengirimnya.
- `208` adalah penanda internal untuk pembaca yang sudah unsubscribe. Ikiform melihat `200` dan catatan di log pengiriman.

Deploy di mana saja yang memberi Anda URL HTTPS publik di port 443, tambahkan URL itu di **Webhooks** di Ikiform, dan taruh secret `whsec_` di `IKIFORM_WEBHOOK_SECRET`. [Dokumentasi webhook](https://ikiform.com/id/docs/webhooks.md) membahas percobaan ulang dan payload, dan [server Anda sendiri](https://ikiform.com/blog/form-submissions-to-your-own-server.md) punya penyiapan Express yang sama dengan database.

## Di mana catatan persetujuan disimpan

Panggilan create MailerLite menerima `subscribed_at`, `ip_address`, `opted_in_at`, dan `optin_ip`. Jangan sertakan field IP. Webhook Ikiform tidak pernah menyertakan alamat IP pengunjung maupun hash-nya, jadi relay tidak punya nilai benar untuk dikirim, dan nilai karangan lebih buruk daripada tidak ada.

Catatan pendaftaran tetap di Ikiform: kiriman menyimpan `consent: true` bersama timestamp, origin, referrer, dan negaranya. Catatan konfirmasi ada di MailerLite, yang mencatat kapan pembaca mengklik tautan. Dari keduanya, Anda bisa menunjukkan kapan seseorang mencentang kotak dan kapan mereka membuktikan alamat itu milik mereka. Ekspor sisi Ikiform sebagai CSV dari **Submissions** saat Anda membutuhkannya.

## Rate limit

Batas API global MailerLite adalah 120 request per menit. Relay melakukan dua per pendaftaran, jadi sekitar 60 pendaftaran per menit muat. Lebih dari itu, MailerLite menjawab `429`, relay menjawab `503` dengan `Retry-After`, dan Ikiform mencoba lagi nanti dengan pengiriman yang sama.

| Jawaban MailerLite | Jawaban relay | Ikiform |
| --- | --- | --- |
| `201` atau `200` | `204` | Pengiriman berhasil |
| `429` | `503` dengan `Retry-After` | Menunggu, lalu mencoba ulang |
| `401` | `502` | Mencoba ulang. Perbaiki token, lalu gunakan **Retry now** pada pengiriman yang gagal |
| `422` | `502` dengan error-nya | Mencoba ulang. Biasanya ID grup atau nama field yang salah |

## Hal yang sering menjebak

- **Jangan kirim `status: "active"`.** Status itu menandai orang tersebut sebagai sudah berlangganan, dan dokumentasi MailerLite tidak menyebutkan apakah konfirmasi tetap dikirim. Uji dengan status yang Anda kirim.
- **Berlangganan ulang adalah pilihan.** MailerLite punya flag `resubscribe` untuk orang yang sudah unsubscribe. Kirim hanya jika formulir Anda menyatakannya, dan saat pembaca tahu mereka mendaftar kembali.
- **Toggle-nya penting.** MailerLite hanya mengirim email konfirmasi untuk pendaftaran API saat **Double opt-in for API and integrations** aktif.
- **Satu email konfirmasi.** Email double opt-in API dipakai bersama oleh setiap pendaftaran API. Jika Anda butuh kata-kata berbeda per penempatan, gunakan formulir MailerLite terpisah.
- **Duplikat di Ikiform.** Ikiform menyimpan setiap kiriman yang diterima, sedangkan MailerLite menyimpan satu subscriber per email. Hitung subscriber di MailerLite, bukan di dashboard Ikiform.

## Pastikan berfungsi

1. Kirim uji dari endpoint di Ikiform. Pengiriman menampilkan `204`.
2. Berlangganan dengan alamat baru milik Anda. MailerLite menampilkan subscriber sebagai unconfirmed di grup footer, dan email konfirmasi tiba.
3. Konfirmasi, lalu berlangganan lagi dari artikel blog. Subscriber tetap active, bergabung ke grup kedua, dan tidak mendapat email konfirmasi baru.
4. Unsubscribe alamat itu di MailerLite lalu berlangganan sekali lagi. Log pengiriman menampilkan catatan unsubscribed, dan MailerLite tetap menampilkannya sebagai unsubscribed.

## Pertanyaan

### Bisakah saya memakai formulir HTML sendiri dengan MailerLite alih-alih embed-nya?

Bisa. Kirim formulir ke Ikiform, dan biarkan relay menambahkan setiap pendaftaran lewat API MailerLite dengan grup yang tepat. Formulir tetap di markup Anda dan MailerLite tetap mengirim newsletter.

### Mengapa MailerLite tidak mengirim email konfirmasi ke pendaftaran API?

Entah Double opt-in for API and integrations mati di pengaturan subscribe MailerLite, atau relay membuat subscriber sebagai active. Biarkan pengaturan itu aktif, kirim status unconfirmed, dan uji dengan alamat milik Anda.

### Apakah subscriber yang mendaftar dua kali akan mendapat dua email konfirmasi?

Tidak dengan relay ini. Relay mencari alamatnya lebih dulu dan hanya mengirim unconfirmed untuk subscriber baru. Subscriber yang sudah ada ditambahkan ke grup baru dan tidak ada hal lain yang berubah.

### Bagaimana cara memasukkan pendaftaran dari footer dan blog ke grup MailerLite yang berbeda?

Beri setiap penempatan nilai berbeda di input source tersembunyi formulir, lalu petakan setiap nilai ke ID grup MailerLite di relay. Subscriber yang sudah ada dan mendaftar dari penempatan kedua juga bergabung ke grup itu, dan tetap berada di grup pertama.

### Apakah Ikiform mengirim sesuatu ke subscriber?

Tidak. Ikiform tidak pernah mengirim email ke orang yang mengirim formulir. MailerLite yang mengirim konfirmasi, setiap newsletter, dan tautan unsubscribe.

## 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.
- [Double opt-in](https://ikiform.com/id/guides/newsletter-signup/double-opt-in.md): 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.
- [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.
- [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.
