イベント登録

イベント登録2 分で読めます

イベントやフェスティバル向け、シフトを選べるボランティア募集フォーム

シフトを選べるボランティア募集フォーム。当日の電話番号を集め、人手が足りないシフトを示してシフト表を作るスクリプト付き。

Preet SutharIkiform 創業者

ボランティアが 1 つのフォームで参加できるシフトをすべてチェックし、電話番号、T シャツのサイズ、緊急連絡先を入力して Ikiform に送信できるようにします。Ikiform は各申し込みを保存してコーディネーターにメールで通知しますが、シフトを埋めたり締め切ったりはしません。そこで、必要人数に対してシフトごとのボランティア数を数え、シフト表を書き出す短いスクリプトを実行します。足りないシフトは、手の空いているボランティアに直接頼んで埋めます。

ボランティアならではの違い

出欠確認が尋ねるのは「来ますか?」の 1 つだけです。ボランティア募集が尋ねるのは「いつ」で、その答えは各シフトの必要人数と照らし合わせて初めて意味を持ちます。朝 7 時の設営は 6 人必要なのに 2 人しか集まらず、晴れた午後は 10 人必要なところに 19 人集まります。仕事は人数を数えることではなく、穴を埋めることです。

  • 選択は 1 つではなく、参加できる時間帯。 人は複数のシフトに入れます。何が必要かを推測させるのではなく、入れるシフトをすべて尋ね、そこから割り当ててください。
  • 当日の連絡先。 メールは計画用です。当日は携帯電話の番号と、ボランティアごとの緊急連絡先が必要です。
  • 発注するもの。 T シャツ、ストラップ、昼食を、サイズと数ごとに。
  • 年齢。 多くのイベントでは、ボランティアごとに成人であることか保護者の同意が必要です。何が適用されるかは所属団体に確認してください。チェックボックスは回答を記録しますが、法的な確認にはなりません。

SignUpGenius などのボランティア向けプラットフォームは、枠ごとに申し込みを受け付け、満員になると締め切ります。枠ごとの厳密な上限が必要なら、それを使ってください。Ikiform は、フォームを自分のサイトに置き、整ったリストから手作業でシフトを割り当てたい主催者に向いています。

ボランティアの参加可能時間を、穴が見えるシフト表に変える申し込みフォーム入れるシフトすべてIkiform保存、コーディネーターに通知シフト表スクリプトシフトごとの人数と必要数rota.csvシフトごとの名前と電話番号設営: 6 人中 2 人手の空いた人に頼む送信API不足ボランティアの参加可能時間を、穴が見えるシフト表に変える申し込みフォーム入れるシフトすべてIkiform保存、コーディネーターに通知シフト表スクリプトシフトごとの人数と必要数rota.csvシフトごとの名前と電話番号設営: 6 人中 2人手の空いた人に頼む送信API不足
  1. ボランティアは申し込みフォームで入れるシフトをすべてチェックし、フォームは Ikiform に送信されます。
  2. Ikiform は各申し込みを保存し、コーディネーターにメールで通知します。
  3. スクリプトが API で申し込みを読み込み、シフトごとのボランティア数を必要人数と比べて数えます。
  4. 各シフトの名前と電話番号を載せた rota.csv を書き出します。
  5. 6 人中 2 人の設営のように、人手が足りないシフトがすぐにわかるので、他で手の空いているボランティアに頼めます。
Ikiform が参加可能時間を保持し、スクリプトがそれを充足状況に変え、最終的な判断はコーディネーターが行います。

フォーム

一覧しやすいよう、シフトを日ごとにまとめます。チェックボックスの name は shifts[] なので、1 つだけチェックしてもリストとして保存されます。プレーンな HTML として、埋め込みを受け付けるどのサイトやビルダーでも動きます:

volunteer.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label>Name <input name="name" autocomplete="name" required></label>
  <label>Email <input name="email" type="email" autocomplete="email" required></label>
  <label>Mobile number for the day <input name="phone" type="tel" autocomplete="tel" placeholder="+44 7700 900123" required></label>

  <fieldset>
    <legend>Shifts you can do</legend>
    <p>Saturday</p>
    <label><input type="checkbox" name="shifts[]" value="sat_setup"> 7:00 to 10:00, setup</label>
    <label><input type="checkbox" name="shifts[]" value="sat_day"> 10:00 to 14:00</label>
    <label><input type="checkbox" name="shifts[]" value="sat_late"> 14:00 to 18:00</label>
    <p>Sunday</p>
    <label><input type="checkbox" name="shifts[]" value="sun_day"> 10:00 to 14:00</label>
    <label><input type="checkbox" name="shifts[]" value="sun_pack"> 14:00 to 17:00, pack-down</label>
  </fieldset>

  <label>Where you'd like to help
    <select name="role">
      <option value="anywhere">Anywhere</option>
      <option value="welcome">Welcome desk</option>
      <option value="food">Food stall</option>
      <option value="stewarding">Stewarding</option>
    </select>
  </label>
  <label>T-shirt size
    <select name="tshirt" required>
      <option value="s">S</option><option value="m" selected>M</option><option value="l">L</option>
      <option value="xl">XL</option><option value="xxl">XXL</option>
    </select>
  </label>
  <label>Emergency contact name and number <input name="emergency_contact" required maxlength="160"></label>
  <label><input type="checkbox" name="adult" required> I'm 18 or over, or a parent or guardian is filling this in with me</label>

  <input type="hidden" name="_redirect" value="https://fair.example/volunteers/thanks">
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden>
  <button type="submit">Sign me up</button>
</form>

この定義をフォームの Fields タブに貼り付けます。これで、どのページから来た送信でも、シフトが選ばれていない申し込み、電話番号として正しくない番号、年齢のチェックボックスが未チェックの申し込みをサーバーが拒否します:

プレビュー

Ikiform のバリデーターをブラウザーで実行します。何も送信されません。

シフトの変更は SMS でお知らせします。国番号も入力してください。

参加できるシフト
shifts は min_items: 1 の multi_select です。phone は番号の形式を確認する phone フィールドです。adult はチェックが必須です。
フィールド尋ねる理由
phoneシフト変更の連絡と、当日の人探し
shifts割り当ての元になる参加可能時間
role希望。受付を希望した人を受付に配置するため
tshirt2 週間前に出す発注
emergency_contact救護チームのためで、マーケティング用ではない
adult団体の年齢ルール。独自の created_at を持つ送信データに記録される
電話番号と緊急連絡先は、申し込んだ本人以外の人の個人データも含みます。エクスポートは非公開の場所に保管し、シフト表はシフトリーダーとだけ共有し、イベント後に送信データを削除してください。

シフト表を作り、穴を確認する

状況を知りたいときはいつでも、Node とシークレット API キーでこれを実行します。各ボランティアの最新の申し込みを使い、シフトごとに充足、不足、余裕を表示し、シフトごとの名前と番号を載せた rota.csv を書き出します:

rota.ts
import { writeFileSync } from "node:fs";
import { createClient } from "@ikiform/sdk";

const NEEDED: Record<string, number> = { sat_setup: 6, sat_day: 10, sat_late: 10, sun_day: 8, sun_pack: 6 };
const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY! });
const people = new Map<string, Record<string, unknown>>();

for await (const submission of ikiform.submissions.iterate({ formId: "frm_xxxxxxxxxxxxxxxx", status: "received", limit: 100 })) {
  const email = String(submission.fields.email ?? "").trim().toLowerCase();
  if (email && !people.has(email)) people.set(email, submission.fields);
}

const cell = (value: unknown) => `"${String(value ?? "").replaceAll('"', '""')}"`;
const rows = [["shift", "name", "phone", "role", "tshirt"].join(",")];

for (const [shift, needed] of Object.entries(NEEDED)) {
  const team = [...people.values()].filter((fields) => (fields.shifts as string[] | undefined)?.includes(shift));
  const state = team.length < needed ? `SHORT ${needed - team.length}` : team.length > needed ? "spare" : "ok";
  console.log(`${shift.padEnd(10)} ${team.length}/${needed} ${state}`);
  for (const fields of team) {
    rows.push([shift, fields.name, fields.phone, fields.role, fields.tshirt].map(cell).join(","));
  }
}

writeFileSync("rota.csv", `${rows.join("\n")}\n`);
  • 一覧は新しい順に返るので、参加可能時間を変えて申し込み直したボランティアは、最新の回答で数えられます。
  • 各人はチェックしたすべてのシフトの下に表示されます。これは参加可能時間です。CSV で割り当てに絞り込み、各人に確定したシフトを伝えてください。
  • 名前に含まれるカンマや引用符はエスケープされるので、CSV はどのスプレッドシートでも問題なく開けます。

コードなしでざっと見るなら、Submissions から CSV をエクスポートし、shifts 列を sat_setup のようなシフトの値で絞り込みます。エクスポートでは、複数選択の値は 1 つのセルにまとめられます。

参加可能時間から割り当てへ

  1. 2 週間前にシフト表を作り、tshirt の数で T シャツを発注します。
  2. 不足しているシフトごとに、手が空いていて、そのシフトにもチェックを入れたボランティアに連絡します。参加できると本人がすでに答えています。
  3. 自分のメールやメッセージツールから、各ボランティアに確定したシフトを送ります。通知メールの Reply は本人に直接届きます。
  4. 前日に、電話番号付きのシフト表をシフトリーダー用に印刷します。

Ikiform はフォームを入力した本人にはメールを送りません。通知メールが届くのはあなたとチームだけなので、自動返信、確認メール、ダブルオプトインはありません。それらは Webhook をきっかけに、自分のメールツールから送ってください。ボランティアは何に申し込んだかを忘れるので、確定したシフト表を 1 週間前と前日の夜に個別に送りましょう。

チームがふだん使っている場所で申し込みを知るには、Webhook を Slack や Discord に送ります。そうすれば、不足していたシフトが埋まっていく様子をコーディネーターがその場で見られます。

募集を始める前に確認する

  1. フォームの Allowed domains に自分のサイトのドメインを追加し、開発中は localhost も追加します。空のままにすると、どこからの送信も受け付けます。
  2. シフトを 1 つチェックして申し込みます。ダッシュボードでは、shifts が値 1 つのリストになっています。
  3. シフトを選ばずに、または年齢のチェックボックスをオフにして申し込んでみます。ブラウザーが止め、細工した送信には 422 が返ります。
  4. 通知の各受信者の受信トレイを確認します。それぞれにフィールド入りのメールが届き、フォームに email フィールドがあれば Reply で送信者に返信できます。
  5. シフト表のスクリプトを実行します。テストの申し込みがそのシフトの下に表示され、他のシフトはすべて不足と表示されます。
  6. rota.csv をスプレッドシートで開き、電話番号の列を確認します。

ハマりどころ

問題対処法
シフトが 1 つだとリストではなくテキストとして保存されるチェックボックスの name が [] なしの shifts で、フィールドも定義されていません。name を shifts[] に変えるか、shifts を multi_select として定義してください。
phone で 422番号が電話番号の形式になっていません。定義のように、ヘルプテキストで国番号の入力を求めてください。
シフト表に同じボランティアが 2 回出てくる2 つの異なるメールアドレスで申し込んでいます。スクリプトはメールアドレスで区別するので、手作業でまとめてください。
422 validation_failed送信がフォームのフィールド定義に合っていません。error.fields に各フィールドと理由が示されます。入力欄の name をフィールド ID に合わせてください。
429 rate_limited1 人の訪問者がフォームのレート制限を超えて送信しました。Standard では訪問者ごとに 1 分あたり 5 件までです。Retry-After まで待つか、共有の IP 1 つから送信するフォームには Relaxed か Custom を選んでください。

よくある質問

手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com