イベント登録2 分で読めます
Eventbrite を使わない、無料コミュニティイベントの参加登録
無料のコミュニティイベントの参加登録を自分のサイトで運営します。セッションの選択、自分のツールからの確認メール、部屋ごとの人数、受付リストまで。
無料イベントなら、自分のサイトの参加登録フォームで Eventbrite の申し込みを置き換えられます。フォームは Ikiform に送信し、Ikiform が各登録を保存してチームにメールで通知します。自分のメールプロバイダーから確認メールを送る Webhook を追加し、メールアドレスごとの最新の登録からセッションごとの席数を数えます。有料チケット、厳密な定員管理、受付でのスキャンには Eventbrite や他のチケットプラットフォームを使い続けてください。
チケットプラットフォームなしで変わること
Eventbrite は 5 つの仕事を同時にこなしているので、これから自分でやる仕事を見落としがちです。無料のコミュニティデイ、ミートアップのシリーズ、ワークショップなら、ほとんどは小さな仕事です。正直に分けると次のようになります:
- イベントページは Eventbrite のページから、自分のデザインの自分のサイトに移ります。
- 参加登録は Eventbrite のチェックアウトから、Ikiform に送信する自分のフォームに移ります。
- 確認メールは自動では送られなくなります。Webhook が自分のメールプロバイダーから送ります。
- 定員は厳密な上限ではなくなります。セッションごとに登録数を数え、満員になったらフォームを一時停止します。
- 受付は QR スキャン付きのアプリではなくなります。CSV エクスポートから印刷したリストを使います。
Eventbrite の料金は変わるので、コストを比較する前に公式の料金ページを確認してください。無料イベントの場合、離れる理由はたいてい手数料ではありません。参加者リストが他社のプラットフォームにあること、ページが相手のデザインになること、登録者が独自のアカウントやメール設定を持つ別の会社に情報を渡すことです。有料イベントなら、そのまま使い続けてください。Ikiform に決済機能はありません。
セッションを選べる参加登録フォーム
コミュニティデイでは並行セッションがよくあり、部屋の広さもまちまちです。参加予定のセッションを尋ねておけば、当日までに人気のワークショップを大きな部屋に移せます。この定義では、2 つが同時に行われるので、4 つのうち最大 3 つまで選べるようにしています:
プレビュー
Ikiform のバリデーターをブラウザーで実行します。何も送信されません。
sessions は配列として保存される multi_select です。HTML ではチェックボックスの name を sessions[] にすると、1 つだけ選んだ場合もリストとして保存されます。nameのラベルを名札用にしているので、本人が呼ばれたい名前を集められます。lunchはNo lunchの選択肢があるradioなので、食べる人の分だけ注文できます。updatesは初期状態でチェックの入っていないチェックボックスで、独自のcreated_atを持つ送信データにtrueかfalseとして保存されます。ニュースレターに追加するのはtrueの人だけにしてください。- 各スタックのマークアップはメインガイドの出欠フォーム を使い、フィールドをここのものに差し替えてください。
確認メールは自分のメールツールから送る
Ikiform はフォームを入力した本人にはメールを送りません。通知メールが届くのはあなたとチームだけなので、自動返信、確認メール、ダブルオプトインはありません。それらは Webhook をきっかけに、自分のメールツールから送ってください。イベントでは確認メールを必ず送りましょう。参加者は上司に転送したり、当日の朝に検索したりするからです。このルートハンドラーは Ikiform の署名付き Webhook を受け取り、Resend の API でメールを送ります。送信用のエンドポイントがあるプロバイダーなら、どれでも同じように使えます。
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が署名を確認するので、他人があなたのドメインからメールを送らせることはできません。Idempotency-Keyには配信のwebhook-idを使います。この値は自動のリトライでも、失敗した配信の手動の Retry でも変わらないので、応答が失われた配信で 2 通目のメールが送られることはありません。- 名前とセッション名は、HTML に入れる前にエスケープします。フィールドの値は信頼できない入力として扱ってください。
502を返すと Ikiform がリトライするので、メールプロバイダーの短い障害で確認メールが失われることはありません。スパムでは Webhook が発火しないので、ボットのせいで見知らぬ人にメールを送ることもありません。
ダッシュボードの Webhooks でルートを追加し、そのシークレットを IKIFORM_WEBHOOK_SECRET にコピーします。Ikiform は失敗した配信を約 3 日間リトライし、配信ログに各試行が表示されます。コードを書かずに、Zapier や Make などの自動化ツールで同じメールを送ることもできます。
セッションごとの席数
Ikiform は、部屋が満員になったセッションの登録を止めることも、満員の選択肢を隠すこともできません。代わりに各参加者の最新の登録を使って数え、数字が必要なときにいつでも実行してください:
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" : ""}`);
}ワークショップが満員になったら、ページで満員と表示し、フォームとフィールド定義からその選択肢を削除して、新しい送信で選べないようにします。イベント全体が満員になったら Pause form を選びます。送信には 403 form_paused が返るので、ページには登録を締め切ったと表示しましょう。
| 状況 | 対処法 |
|---|---|
| ワークショップの 1 つが満員 | フォームとフィールド定義からその選択肢を削除し、ページでその旨を伝える |
| イベント全体が満員 | Pause form を選び、フォームをキャンセル待ち用のメールアドレスに置き換える |
| キャンセルが出た | 本人が確認メールに返信してくる。送信データを削除して、集計上の席を空ける |
| 無断欠席が見込まれる | 無料イベントでは一定の割合で無断欠席が出がち。自分たちの割合を記録し、次回は少し多めに受け付ける |
受付で
- 前日の夜に Submissions を CSV でエクスポートし、メールアドレスの重複を最新のものを残して削除します。
- 名前順に並べ替え、
name、organisation、lunchを残して、受付用に 2 部印刷します。 - 同じシートから差し込み印刷で
name列を使って名札を印刷します。 - 当日参加者は手書きで記入します。イベント後は、本人が同意した場合にだけ自分のリストに追加してください。
告知する前に確認する
- フォームの Allowed domains に自分のサイトのドメインを追加し、開発中は
localhostも追加します。空のままにすると、どこからの送信も受け付けます。 - 自分のメールアドレスで、セッションを 2 つ選んで登録します。
- 自分のドメインから、両方のセッションが記載された確認メールが届きます。
- Webhook を追加した場合は、Webhooks でエンドポイントを開きます。配信が
succeededになり、サーバーの応答が表示されます。 - 席数の集計を実行します。選んだ 2 つのセッションがそれぞれ 1 席埋まっています。
- 何も届かない場合は、ダッシュボードのステータスフィルターを Spam に切り替えてください。スパムにも本物の送信と同じ成功の応答が返ります。
ハマりどころ
| 問題 | 対処法 |
|---|---|
選択肢は最大 3 つまでという 422 | 4 つのセッションすべてを選んだ人がいます。これは max_items のルールが機能している状態です。Ikiform のメッセージをチェックボックスの横に表示してください。 |
| 1 つだけ選ぶとセッションが 1 つしか保存されない | チェックボックスの name を sessions[] にしてください。フィールドを multi_select として定義していれば、値が 1 つでもリストとして保存されます。 |
| 登録は Ikiform にあるのに確認メールが届かない | エンドポイントのログで配信を開いてください。プロバイダーのステータス付きの 502 は、メールが拒否されたことを意味します。送信ドメインが未認証であることがよくあります。 |
| 送信データはダッシュボードにあるのに、メールも Webhook も届かない | スパムとして保存されています。スパムでは何も送られません。Spam フィルターで開いて理由を確認し、スパムではないとマークすると、メールと Webhook が送られます。 |
429 rate_limited | 1 人の訪問者がフォームのレート制限を超えて送信しました。Standard では訪問者ごとに 1 分あたり 5 件までです。Retry-After まで待つか、共有の IP 1 つから送信するフォームには Relaxed か Custom を選んでください。 |
よくある質問
席を数えてリストを印刷できる無料イベントなら十分です。有料チケット、厳密な定員制限、キャンセル待ち、QR での受付はチケットプラットフォームの仕事で、Ikiform にはできません。
自分で送ります。メールプロバイダーの API を呼ぶか、自動化ツールにつなぐ Ikiform の Webhook を追加し、自分のドメインから確認メールを送ってください。
自動ではできません。短いスクリプトやスプレッドシートでセッションごとの登録を数え、満員になったワークショップの選択肢をフォームから削除してください。
いいえ。受け付けた送信はすべて保存されます。24 時間以内のまったく同じ再送信はスパムスコアを上げますが、それだけではスパムになりません。リスト、データベース、CSV エクスポートでメールアドレスごとに重複を取り除いてください。
いいえ、無料プランはありません。テストは無料で、支払う前に localhost から月 50 件のテスト送信ができます。本番運用するには、月 $6 で 500 件からの Pro か、1 回払いで 10,000 件 $49 または 50,000 件 $149 のパックを選べます。クレジットに有効期限はありません。
手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com