Pendaftaran acara

Pendaftaran acara6 menit baca

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.

Preet SutharPendiri, Ikiform

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:

Tugas mana yang pindah dari Eventbrite ke setup Anda sendiri, dan siapa yang mengerjakannyahalaman acarahalaman & brandmerekahalaman Andapendaftarancheckout merekaformulir Anda,disimpan Ikiformemail konfirmasidikirimkan untukAndawebhook ke alatemailkapasitasbatas keras, daftartungguAnda hitung dan jedacheck-inaplikasi, scan QRdaftar cetaktugasdi Eventbritedi situs AndaTugas mana yang pindah dari Eventbrite ke setup Anda sendiri, dan siapa yang mengerjakannyahalamanacarahalaman& brandmerekahalamanAndapendaftarancheckoutmerekaformulirAnda,disimpanIkiformemailkonfirmasidikirimkanuntukAndawebhookke alatemailkapasitasbataskeras,daftartungguAndahitungdanjedacheck-inaplikasi,scan QRdaftarcetaktugasdiEventbritedi situsAnda
  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:

Pratinjau

Menjalankan validator Ikiform di browser Anda. Tidak ada yang dikirim.

Sesi yang akan Anda hadiri
Makan siang
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 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. 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
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 atau Make 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
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.

SituasiYang harus dilakukan
Satu workshop penuhHapus opsinya dari formulir dan definisi field, lalu umumkan di halaman
Seluruh acara penuhPause form lalu ganti formulir dengan alamat email untuk daftar tunggu
Seseorang membatalkanMereka membalas email konfirmasi. Hapus kirimannya agar hitungan membebaskan kursi itu
Ada yang diperkirakan tidak datangAcara 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

MasalahYang harus dilakukan
422 yang meminta memilih maksimal 3 opsiSeseorang memilih keempat sesi. Itu tandanya aturan max_items bekerja; tampilkan pesan Ikiform di samping checkbox.
Hanya satu sesi tersimpan saat seseorang memilih satuBeri nama checkbox sessions[]. Dengan field didefinisikan sebagai multi_select, satu nilai pun tetap disimpan sebagai daftar.
Tidak ada email konfirmasi, tetapi pendaftaran ada di IkiformBuka 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 datangKiriman 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_limitedSatu 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

Mentok di salah satu langkah, atau ingin panduan untuk situasi Anda? Email hello@ikiform.com.