# Eventbrite を使わない、無料コミュニティイベントの参加登録

> 無料のコミュニティイベントの参加登録を自分のサイトで運営します。セッションの選択、自分のツールからの確認メール、部屋ごとの人数、受付リストまで。

公開日 2026-10-25 · https://ikiform.com/ja/guides/event-registration/without-eventbrite

無料イベントなら、自分のサイトの参加登録フォームで Eventbrite の申し込みを置き換えられます。フォームは Ikiform に送信し、Ikiform が各登録を保存してチームにメールで通知します。自分のメールプロバイダーから確認メールを送る Webhook を追加し、メールアドレスごとの最新の登録からセッションごとの席数を数えます。有料チケット、厳密な定員管理、受付でのスキャンには Eventbrite や他のチケットプラットフォームを使い続けてください。

## チケットプラットフォームなしで変わること

Eventbrite は 5 つの仕事を同時にこなしているので、これから自分でやる仕事を見落としがちです。無料のコミュニティデイ、ミートアップのシリーズ、ワークショップなら、ほとんどは小さな仕事です。正直に分けると次のようになります:

図: Eventbrite から自分の環境に移る仕事と、それぞれの担い手

1. イベントページは Eventbrite のページから、自分のデザインの自分のサイトに移ります。
2. 参加登録は Eventbrite のチェックアウトから、Ikiform に送信する自分のフォームに移ります。
3. 確認メールは自動では送られなくなります。Webhook が自分のメールプロバイダーから送ります。
4. 定員は厳密な上限ではなくなります。セッションごとに登録数を数え、満員になったらフォームを一時停止します。
5. 受付は QR スキャン付きのアプリではなくなります。CSV エクスポートから印刷したリストを使います。

最初の 3 つは自分のサイトのほうが優れています。残りの 2 つは劣り、大規模なイベントや有料イベントではそれがチケットプラットフォームに残る理由になります。

Eventbrite の料金は変わるので、コストを比較する前に公式の料金ページを確認してください。無料イベントの場合、離れる理由はたいてい手数料ではありません。参加者リストが他社のプラットフォームにあること、ページが相手のデザインになること、登録者が独自のアカウントやメール設定を持つ別の会社に情報を渡すことです。有料イベントなら、そのまま使い続けてください。Ikiform に決済機能はありません。

## セッションを選べる参加登録フォーム

コミュニティデイでは並行セッションがよくあり、部屋の広さもまちまちです。参加予定のセッションを尋ねておけば、当日までに人気のワークショップを大きな部屋に移せます。この定義では、2 つが同時に行われるので、4 つのうち最大 3 つまで選べるようにしています:

フォーム: Community day registration

- **名札に載せる名前** (`name`, text, 必須)
- **メールアドレス** (`email`, email, 必須)
- **参加するセッション** (`sessions`, multi_select, 必須)
- **会社または団体** (`organisation`, text)
- **昼食** (`lunch`, radio, 必須)
- **今後のコミュニティデイについてメールで知らせてほしい** (`updates`, checkbox)

`sessions` は配列として保存される `multi_select` です。HTML ではチェックボックスの name を `sessions[]` にすると、1 つだけ選んだ場合もリストとして保存されます。

- `name` のラベルを名札用にしているので、本人が呼ばれたい名前を集められます。
- `lunch` は `No lunch` の選択肢がある `radio` なので、食べる人の分だけ注文できます。
- `updates` は初期状態でチェックの入っていないチェックボックスで、独自の `created_at` を持つ送信データに `true` か `false` として保存されます。ニュースレターに追加するのは `true` の人だけにしてください。
- 各スタックのマークアップは[メインガイドの出欠フォーム](https://ikiform.com/ja/guides/event-registration.md#form) を使い、フィールドをここのものに差し替えてください。

> 参加登録フォームで今後のお知らせも案内する場合は、そのチェックボックスを初期状態でオフにし、何を送るのかを具体的に書いてください。チェックボックスは同意の記録になります。下の確認メールはマーケティングではないので、同意は不要です。

## 確認メールは自分のメールツールから送る

Ikiform はフォームを入力した本人にはメールを送りません。通知メールが届くのはあなたとチームだけなので、自動返信、確認メール、ダブルオプトインはありません。それらは [Webhook](https://ikiform.com/ja/docs/webhooks.md) をきっかけに、自分のメールツールから送ってください。イベントでは確認メールを必ず送りましょう。参加者は上司に転送したり、当日の朝に検索したりするからです。このルートハンドラーは Ikiform の署名付き Webhook を受け取り、Resend の API でメールを送ります。送信用のエンドポイントがあるプロバイダーなら、どれでも同じように使えます。

`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` が署名を確認するので、他人があなたのドメインからメールを送らせることはできません。
- `Idempotency-Key` には配信の `webhook-id` を使います。この値は自動のリトライでも、失敗した配信の手動の **Retry** でも変わらないので、応答が失われた配信で 2 通目のメールが送られることはありません。
- 名前とセッション名は、HTML に入れる前にエスケープします。フィールドの値は信頼できない入力として扱ってください。
- `502` を返すと Ikiform がリトライするので、メールプロバイダーの短い障害で確認メールが失われることはありません。スパムでは Webhook が発火しないので、ボットのせいで見知らぬ人にメールを送ることもありません。

ダッシュボードの **Webhooks** でルートを追加し、そのシークレットを `IKIFORM_WEBHOOK_SECRET` にコピーします。Ikiform は失敗した配信を約 3 日間リトライし、配信ログに各試行が表示されます。コードを書かずに、[Zapier](https://ikiform.com/blog/form-submissions-to-zapier.md) や [Make](https://ikiform.com/blog/form-submissions-to-make.md) などの自動化ツールで同じメールを送ることもできます。

## セッションごとの席数

Ikiform は、部屋が満員になったセッションの登録を止めることも、満員の選択肢を隠すこともできません。代わりに各参加者の最新の登録を使って数え、数字が必要なときにいつでも実行してください:

`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" : ""}`);
}
```

ワークショップが満員になったら、ページで満員と表示し、フォームとフィールド定義からその選択肢を削除して、新しい送信で選べないようにします。イベント全体が満員になったら **Pause form** を選びます。送信には `403 form_paused` が返るので、ページには登録を締め切ったと表示しましょう。

| 状況 | 対処法 |
| --- | --- |
| ワークショップの 1 つが満員 | フォームとフィールド定義からその選択肢を削除し、ページでその旨を伝える |
| イベント全体が満員 | **Pause form** を選び、フォームをキャンセル待ち用のメールアドレスに置き換える |
| キャンセルが出た | 本人が確認メールに返信してくる。送信データを削除して、集計上の席を空ける |
| 無断欠席が見込まれる | 無料イベントでは一定の割合で無断欠席が出がち。自分たちの割合を記録し、次回は少し多めに受け付ける |

## 受付で

1. 前日の夜に **Submissions** を CSV でエクスポートし、メールアドレスの重複を最新のものを残して削除します。
2. 名前順に並べ替え、`name`、`organisation`、`lunch` を残して、受付用に 2 部印刷します。
3. 同じシートから差し込み印刷で `name` 列を使って名札を印刷します。
4. 当日参加者は手書きで記入します。イベント後は、本人が同意した場合にだけ自分のリストに追加してください。

## 告知する前に確認する

1. フォームの **Allowed domains** に自分のサイトのドメインを追加し、開発中は `localhost` も追加します。空のままにすると、どこからの送信も受け付けます。
2. 自分のメールアドレスで、セッションを 2 つ選んで登録します。
3. 自分のドメインから、両方のセッションが記載された確認メールが届きます。
4. Webhook を追加した場合は、**Webhooks** でエンドポイントを開きます。配信が `succeeded` になり、サーバーの応答が表示されます。
5. 席数の集計を実行します。選んだ 2 つのセッションがそれぞれ 1 席埋まっています。
6. 何も届かない場合は、ダッシュボードのステータスフィルターを **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 を選んでください。 |

## よくある質問

### Eventbrite の代わりに参加登録フォームだけで十分ですか？

席を数えてリストを印刷できる無料イベントなら十分です。有料チケット、厳密な定員制限、キャンセル待ち、QR での受付はチケットプラットフォームの仕事で、Ikiform にはできません。

### 登録者はどうやって確認メールを受け取りますか？

自分で送ります。メールプロバイダーの API を呼ぶか、自動化ツールにつなぐ Ikiform の Webhook を追加し、自分のドメインから確認メールを送ってください。

### ワークショップごとに席数を制限できますか？

自動ではできません。短いスクリプトやスプレッドシートでセッションごとの登録を数え、満員になったワークショップの選択肢をフォームから削除してください。

### Ikiform は重複した送信データを削除しますか？

いいえ。受け付けた送信はすべて保存されます。24 時間以内のまったく同じ再送信はスパムスコアを上げますが、それだけではスパムになりません。リスト、データベース、CSV エクスポートでメールアドレスごとに重複を取り除いてください。

### Ikiform は無料ですか？

いいえ、無料プランはありません。テストは無料で、支払う前に localhost から月 50 件のテスト送信ができます。本番運用するには、月 $6 で 500 件からの Pro か、1 回払いで 10,000 件 $49 または 50,000 件 $149 のパックを選べます。クレジットに有効期限はありません。

## その他のガイド

- [イベント登録](https://ikiform.com/ja/guides/event-registration.md): 自分のイベントページで出欠を受け付けます。フォーム、同伴者の上限、正確な人数集計、満員時の締め切り、受付リストまで、チケットアプリなしで。
- [ボランティア募集](https://ikiform.com/ja/guides/event-registration/volunteer-signup.md): シフトを選べるボランティア募集フォーム。当日の電話番号を集め、人手が足りないシフトを示してシフト表を作るスクリプト付き。
- [結婚式の出欠](https://ikiform.com/ja/guides/event-registration/wedding-rsvp.md): 自作の結婚式サイト用の出欠フォーム。招待ごとに 1 回答、名前のあるゲストごとに料理を選び、締め切りと未回答者のリストも用意します。
