# Pendaftaran acara tanpa Eventbrite, untuk acara komunitas gratis

> Jalankan pendaftaran acara komunitas gratis di situs Anda sendiri: pilihan sesi, email konfirmasi dari alat Anda sendiri, hitungan per ruangan, dan daftar check-in.

Terbit 2026-10-25 · https://ikiform.com/id/guides/event-registration/without-eventbrite

Untuk acara gratis, formulir pendaftaran di situs Anda sendiri bisa menggantikan pendaftaran Eventbrite: formulir mengirim ke Ikiform, yang menyimpan setiap pendaftaran dan mengirim email ke tim Anda. Tambahkan webhook yang mengirim email konfirmasi dari penyedia email Anda sendiri, dan hitung kursi per sesi dari pendaftaran terbaru per email. Tetap pakai Eventbrite, atau platform tiket lain, untuk tiket berbayar, batas kapasitas yang ketat, dan pemindaian check-in.

## Apa yang berbeda tanpa platform tiket

Eventbrite mengerjakan lima tugas sekaligus, dan mudah lupa mana saja yang sekarang harus Anda kerjakan sendiri. Untuk hari komunitas gratis, seri meetup, atau workshop, sebagian besar tugas itu kecil. Berikut pembagiannya, apa adanya:

Diagram: Tugas mana yang pindah dari Eventbrite ke setup Anda sendiri, dan siapa yang mengerjakannya

1. Halaman acara pindah dari halaman Eventbrite ke situs Anda sendiri, dengan desain Anda.
2. Pendaftaran pindah dari checkout Eventbrite ke formulir Anda, yang mengirim ke Ikiform.
3. Email konfirmasi tidak lagi dikirimkan untuk Anda. Webhook mengirimnya dari penyedia email Anda sendiri.
4. Kapasitas tidak lagi berupa batas keras. Anda menghitung pendaftaran per sesi dan menjeda formulir saat penuh.
5. Check-in tidak lagi berupa aplikasi dengan pemindaian QR. Anda mencetak daftar dari ekspor CSV.

Tiga yang pertama lebih baik di situs Anda sendiri. Dua yang terakhir lebih buruk, dan untuk acara besar atau berbayar, keduanya adalah alasan untuk tetap memakai platform tiket.

Harga Eventbrite bisa berubah, jadi cek halaman harganya sendiri sebelum membandingkan biaya. Untuk acara gratis, alasan untuk pindah biasanya bukan biaya: daftar peserta ada di platform orang lain, halamannya terlihat seperti milik mereka, dan pendaftar menyerahkan data mereka ke perusahaan lain dengan pengaturan akun dan email sendiri. Untuk acara berbayar, tetaplah di sana. Ikiform tidak punya pembayaran.

## Formulir pendaftaran dengan pilihan sesi

Hari komunitas sering punya sesi paralel, dan ukuran ruangan berbeda-beda. Tanyakan sesi mana yang ingin dihadiri orang, agar Anda bisa memindahkan workshop populer ke ruangan lebih besar sebelum hari H. Definisi ini membatasi pilihan maksimal tiga dari empat, karena dua di antaranya berjalan bersamaan:

Formulir: Community day registration

- **Nama untuk badge Anda** (`name`, text, wajib)
- **Email** (`email`, email, wajib)
- **Sesi yang akan Anda hadiri** (`sessions`, multi_select, wajib)
- **Perusahaan atau komunitas** (`organisation`, text)
- **Makan siang** (`lunch`, radio, wajib)
- **Kirimi saya email tentang hari komunitas berikutnya** (`updates`, checkbox)

`sessions` adalah `multi_select`, disimpan sebagai array. Di HTML, beri nama checkbox `sessions[]` agar satu pilihan pun tetap disimpan sebagai daftar.

- Label `name` ditujukan untuk badge, sehingga Anda mendapat nama yang ingin dipakai orang untuk dipanggil.
- `lunch` adalah `radio` dengan opsi `No lunch`, jadi Anda memesan untuk orang yang memang akan makan.
- `updates` adalah checkbox yang tidak dicentang, disimpan sebagai `true` atau `false` pada kiriman yang menyimpan `created_at`-nya sendiri. Tambahkan orang ke newsletter Anda hanya jika nilainya `true`.
- Pakai [formulir RSVP dari panduan utama](https://ikiform.com/id/guides/event-registration.md#form) untuk markup di stack Anda, dengan field-field ini sebagai gantinya.

> Jika formulir pendaftaran juga menawarkan kabar berikutnya, biarkan checkbox itu tidak dicentang secara default dan sebutkan dengan jelas apa yang akan Anda kirim. Checkbox itu adalah catatan persetujuan Anda; email konfirmasi di bawah bukan pemasaran dan tidak memerlukannya.

## Kirim konfirmasi dari alat email Anda sendiri

Ikiform tidak mengirim email ke orang yang mengisi formulir. Email notifikasi hanya dikirim ke Anda dan tim, 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). Untuk acara, tetap kirim konfirmasi: orang meneruskannya ke atasan mereka dan mencarinya di pagi hari acara. Route handler ini menerima webhook bertanda tangan dari Ikiform dan mengirim email lewat API Resend. Penyedia mana pun yang punya endpoint pengiriman bekerja dengan cara yang sama.

`app/api/registered/route.ts`:

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

const TITLES: Record<string, string> = {
  keynote: "Opening talk, 10:00",
  workshop_a: "Workshop A, 11:30",
  workshop_b: "Workshop B, 11:30",
  panel: "Closing panel, 15:00",
};

function escape(text: string) {
  return text.replace(/[&<>"']/g, (char) => `&#${char.charCodeAt(0)};`);
}

export async function POST(request: Request) {
  const payload = await request.text();
  try {
    const event = await verifyWebhook({
      payload,
      headers: request.headers,
      secret: process.env.IKIFORM_WEBHOOK_SECRET!,
    });
    if (event.type !== "submission.created") return new Response(null, { status: 204 });

    const fields = event.data.fields;
    const email = String(fields.email ?? "");
    const chosen = (Array.isArray(fields.sessions) ? fields.sessions : []).map((id) => TITLES[String(id)] ?? String(id));
    const response = await fetch("https://api.resend.com/emails", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
        "Content-Type": "application/json",
        "Idempotency-Key": request.headers.get("webhook-id") ?? event.data.submission_id,
      },
      body: JSON.stringify({
        from: "Community Day <hello@community.example>",
        to: email,
        reply_to: "hello@community.example",
        subject: "You're registered for Community Day, 14 March",
        html: [
          `<p>Hi ${escape(String(fields.name ?? ""))},</p>`,
          "<p>You're on the list for Community Day on 14 March at The Old Library. Doors open at 9:30.</p>",
          `<p>Your sessions: ${chosen.map(escape).join(", ")}.</p>`,
          '<p><a href="https://community.example/day.ics">Add it to your calendar</a>. Can\'t come after all? Reply to this email.</p>',
        ].join(""),
      }),
    });
    if (!response.ok) return new Response(`Email API answered ${response.status}`, { status: 502 });
    return new Response(null, { status: 204 });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
    throw error;
  }
}
```

- `verifyWebhook` memeriksa tanda tangan, sehingga tidak ada orang lain yang bisa membuat domain Anda mengirim email.
- `Idempotency-Key` memakai `webhook-id` milik pengiriman, yang tetap sama di setiap percobaan ulang otomatis dan pada **Retry** manual untuk pengiriman yang gagal, sehingga pengiriman yang jawabannya hilang tidak mengirim email kedua.
- Nama dan judul sesi di-escape sebelum masuk ke HTML. Perlakukan nilai field sebagai input yang tidak tepercaya.
- `502` membuat Ikiform mencoba ulang, sehingga gangguan singkat di penyedia email tidak menghilangkan konfirmasi. Spam tidak pernah memicu webhook, jadi bot tidak membuat Anda mengirim email ke orang asing.

Tambahkan route di **Webhooks** pada dashboard dan salin secret-nya ke `IKIFORM_WEBHOOK_SECRET`. Ikiform mencoba ulang pengiriman yang gagal selama sekitar 3 hari, dan log pengiriman menampilkan setiap percobaan. Tanpa kode, alat otomasi seperti [Zapier](https://ikiform.com/blog/form-submissions-to-zapier.md) atau [Make](https://ikiform.com/blog/form-submissions-to-make.md) bisa mengirim email yang sama.

## Kursi per sesi

Ikiform tidak akan menghentikan pendaftaran untuk satu sesi saat ruangannya penuh, dan tidak bisa menyembunyikan opsi yang penuh. Sebagai gantinya, hitung memakai pendaftaran terbaru tiap orang, dan jalankan kapan pun Anda butuh angkanya:

`seats.ts`:

```ts
import { createClient } from "@ikiform/sdk";

const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY! });
const ROOMS: Record<string, number> = { keynote: 200, workshop_a: 30, workshop_b: 30, panel: 200 };
const latest = new Map<string, string[]>();

for await (const submission of ikiform.submissions.iterate({ formId: process.argv[2], status: "received", limit: 100 })) {
  const email = String(submission.fields.email ?? "").trim().toLowerCase();
  const chosen = Array.isArray(submission.fields.sessions) ? submission.fields.sessions.map(String) : [];
  if (email && !latest.has(email)) latest.set(email, chosen);
}

for (const [session, seats] of Object.entries(ROOMS)) {
  const taken = [...latest.values()].filter((chosen) => chosen.includes(session)).length;
  console.log(`${session.padEnd(12)} ${String(taken).padStart(4)} of ${seats}${taken >= seats ? "  FULL" : ""}`);
}
```

Saat workshop penuh, edit halaman untuk menandainya penuh dan hapus opsinya dari formulir dan definisi field, agar kiriman baru tidak bisa memilihnya. Saat seluruh acara penuh, pilih **Pause form**: kiriman mendapat `403 form_paused`, dan halaman sebaiknya menyatakan pendaftaran sudah ditutup.

| Situasi | Yang harus dilakukan |
| --- | --- |
| Satu workshop penuh | Hapus opsinya dari formulir dan definisi field, lalu umumkan di halaman |
| Seluruh acara penuh | **Pause form** lalu ganti formulir dengan alamat email untuk daftar tunggu |
| Seseorang membatalkan | Mereka membalas email konfirmasi. Hapus kirimannya agar hitungan membebaskan kursi itu |
| Ada yang diperkirakan tidak datang | Acara gratis sering kali punya sebagian pendaftar yang tidak datang. Catat persentase Anda sendiri dan terima pendaftaran sedikit lebih banyak lain kali |

## Di pintu masuk

1. Malam sebelumnya, ekspor **Submissions** sebagai CSV dan hapus email duplikat, simpan yang terbaru.
2. Urutkan berdasarkan nama, pertahankan `name`, `organisation`, dan `lunch`, lalu cetak dua salinan untuk meja registrasi.
3. Cetak badge dari sheet yang sama dengan mail merge, memakai kolom `name`.
4. Tulis tangan peserta yang datang tanpa mendaftar. Setelah acara, tambahkan mereka ke daftar Anda hanya jika mereka setuju.

## Cek sebelum mengumumkan

1. Di **Allowed domains** formulir, tambahkan domain situs Anda, ditambah `localhost` selama pengembangan. Biarkan kosong untuk menerima kiriman dari mana saja.
2. Daftar dengan email Anda sendiri, pilih dua sesi.
3. Email konfirmasi datang dari domain Anda, mencantumkan kedua sesi.
4. Jika Anda menambahkan webhook, buka endpoint-nya di **Webhooks**. Pengiriman menampilkan `succeeded` dengan jawaban dari server Anda.
5. Jalankan hitungan kursi. Masing-masing dari dua sesi Anda menampilkan satu kursi terisi.
6. Tidak ada yang masuk? Ubah filter status di dashboard ke **Spam**. Spam mendapat jawaban sukses yang sama dengan kiriman asli.

## Hal yang sering menjebak

| Masalah | Yang harus dilakukan |
| --- | --- |
| `422` yang meminta memilih maksimal 3 opsi | Seseorang memilih keempat sesi. Itu tandanya aturan `max_items` bekerja; tampilkan pesan Ikiform di samping checkbox. |
| Hanya satu sesi tersimpan saat seseorang memilih satu | Beri nama checkbox `sessions[]`. Dengan field didefinisikan sebagai `multi_select`, satu nilai pun tetap disimpan sebagai daftar. |
| Tidak ada email konfirmasi, tetapi pendaftaran ada di Ikiform | Buka pengiriman itu di log endpoint. `502` dengan status dari penyedia berarti penyedia menolak email tersebut, sering kali karena domain pengirim belum diverifikasi. |
| Kiriman ada di dashboard tetapi tidak ada email atau webhook yang datang | Kiriman itu disimpan sebagai spam. Spam tidak mengirim apa pun. Buka di filter **Spam** untuk melihat alasannya, dan tandai sebagai bukan spam untuk mengirim email dan webhook-nya. |
| `429 rate_limited` | Satu pengunjung mengirim melebihi rate limit formulir. Standard mengizinkan 5 per menit per pengunjung. Tunggu sesuai `Retry-After`, atau pilih Relaxed atau Custom untuk formulir yang mengirim dari satu IP bersama. |

## Pertanyaan

### Apakah formulir pendaftaran cukup sebagai pengganti Eventbrite?

Untuk acara gratis di mana Anda bisa menghitung kursi dan mencetak daftar, ya. Untuk tiket berbayar, batas kapasitas ketat, daftar tunggu, atau check-in QR, platform tiket menyediakannya dan Ikiform tidak.

### Bagaimana pendaftar mendapat email konfirmasi?

Kirim sendiri. Tambahkan webhook Ikiform yang memanggil API penyedia email Anda, atau terhubung lewat alat otomasi, lalu kirim konfirmasi dari domain Anda sendiri.

### Bisakah saya membatasi kursi di setiap workshop?

Tidak secara otomatis. Hitung pendaftaran per sesi dengan skrip pendek atau sheet, dan hapus opsi workshop yang penuh dari formulir saat sudah terisi.

### Apakah Ikiform menghapus kiriman duplikat?

Tidak. Setiap kiriman yang diterima disimpan. Kiriman identik yang berulang dalam 24 jam menambah skor spam tetapi tidak otomatis dianggap spam, jadi lakukan deduplikasi berdasarkan email di daftar, database, atau ekspor CSV Anda.

### Apakah Ikiform gratis?

Tidak, tidak ada paket gratis. Pengujian gratis: Anda bisa mengirim 50 kiriman uji per bulan dari localhost sebelum membayar. Untuk go live, Pro mulai $6/bln untuk 500 kiriman, atau Anda bisa bayar sekali untuk 10.000 kiriman seharga $49 atau 50.000 kiriman seharga $149, dengan kredit yang tidak pernah kedaluwarsa.

## Panduan lainnya

- [Pendaftaran acara](https://ikiform.com/id/guides/event-registration.md): Terima RSVP di halaman acara Anda sendiri: formulir, batas tamu, jumlah peserta yang jujur, menutup saat penuh, dan daftar check-in, tanpa aplikasi tiket.
- [Pendaftaran relawan](https://ikiform.com/id/guides/event-registration/volunteer-signup.md): Formulir pendaftaran relawan tempat orang memilih shift, dengan nomor telepon untuk hari H, dan skrip yang menunjukkan shift mana yang kurang orang dan menyusun jadwalnya.
- [RSVP pernikahan](https://ikiform.com/id/guides/event-registration/wedding-rsvp.md): Formulir RSVP untuk website pernikahan yang Anda buat sendiri: satu balasan per undangan, satu menu per tamu yang disebut namanya, tenggat, dan daftar siapa yang belum membalas.
