# エージェンシーやフリーランス向けのプロジェクト問い合わせフォームを作る

> スタジオやフリーランス向けのプロジェクト依頼フォームです。誰かが概要を読む前に、予算と時期で問い合わせを有望、検討、対象外に振り分けます。

公開日 2026-10-25 · https://ikiform.com/ja/guides/lead-capture/project-inquiry

サービスはチェックボックスで、予算と開始時期は選択式で尋ね、相性を判断できるだけの長さの説明を求めます。各問い合わせを Webhook で小さなリレーに送り、予算と時期で有望、検討、対象外のレーンに振り分けます。有望なレーンにはその日のうちに返信し、対象外のレーンにも 1 日以内に丁寧に断りの返信をしましょう。どちらの返信も評判を築きます。

## プロジェクトの問い合わせならではの違い

見積もり依頼は、内容のわかっている仕事の価格を尋ねるものです。プロジェクトの問い合わせはもっと大きな問い、つまり相性が合うかを尋ねます。訪問者はまだプロジェクトの形を固めている途中のことが多く、あなたはヒアリングの時間を割くかどうかを判断しています。スタジオやフリーランスにとって足りないのはリードではなく、実現しない概要を読むのに費やされるパートナーの時間です。

そこでこのフォームは、読む前に振り分けられるだけの構造を集めます。それには 3 つの答えで足ります。何が必要か、おおよそいくら使えるか、いつか、です。話し合いたいことはすべて 1 つの長い説明欄に入れてもらい、全文を読むのは構造化された答えから見て読む価値があるときだけです。

図: リレーがプロジェクトの問い合わせをレーンに振り分ける仕組み

1. 問い合わせは、サービス、予算、開始日を含む署名付きの Webhook として届きます。
2. リレーが署名を検証し、予算と時期を点数化します。
3. 点数を確認します。
4. 予算が $30,000 以上で 3 か月以内に開始なら、有望なレーンへ。
5. 予算が低いか開始が遅いなら、検討のレーンへ。
6. ウェブサイト以外で $10,000 未満なら、対象外のレーンへ。手早く丁寧に断ります。

レーンはチャットのチャンネルです。自動で断られる人はいません。どのレーンにも人が返信し、順番が違うだけです。

## フィールド

トピックが 1 つだけの軽いフォームなら、[お問い合わせフォームのテンプレート](https://ikiform.com/forms/contact-form)から始めてください。このフォームは、振り分け用の 3 つの質問を追加したものです。プレビューで複数のサービスにチェックを入れると、リストとして保存される様子がわかります。

フォーム: Project inquiry

- **名前** (`name`, text, 必須)
- **メールアドレス** (`email`, email, 必須)
- **現在のウェブサイト** (`website`, url)
- **ご依頼の内容は？** (`services`, multi_select, 必須)
- **予算** (`budget`, select, 必須)
- **いつ開始しますか？** (`start`, radio, 必須)
- **プロジェクトについて教えてください** (`description`, textarea, 必須)

`services` は `multi_select` で、`["brand", "website"]` のような配列として保存されます。`website` は `url` フィールドなので、`example.com` は `https://example.com/` として保存されます。

| フィールド | この形にしている理由 |
| --- | --- |
| `services` | 実際のプロジェクトはサービスを組み合わせるので、チェックボックスにします。Webhook では配列として届きます |
| `budget` | 見積もりフォームと違い、ここでは必須です。範囲は最低限の契約額から始めてください |
| `start` | **今は検討中** は正直で、役に立つ答えです。検討のレーンに入ります |
| `description` | 40 文字以上、4,000 文字以下。相性を判断できる長さで、最後まで書き切れる短さです |

## フォーム

チェックボックスは 1 つの `name` を共有します。ブラウザーは `services=brand&services=website` を送り、Ikiform は繰り返しを 1 つのリストにまとめます。ツールが求めるなら、name の末尾を `[]` にしても動きます。

`start-a-project.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="name">Name</label>
  <input id="name" name="name" autocomplete="name" required />
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="website">Your current website</label>
  <input id="website" name="website" inputmode="url" placeholder="example.com" />

  <fieldset>
    <legend>What do you need?</legend>
    <label><input type="checkbox" name="services" value="brand" /> Brand identity</label>
    <label><input type="checkbox" name="services" value="website" /> Website</label>
    <label><input type="checkbox" name="services" value="app" /> Web or mobile app</label>
    <label><input type="checkbox" name="services" value="seo" /> Search and content</label>
  </fieldset>

  <label for="budget">Budget</label>
  <select id="budget" name="budget" required>
    <option value="under_10k">Under $10,000</option>
    <option value="10k_30k">$10,000 to $30,000</option>
    <option value="30k_75k">$30,000 to $75,000</option>
    <option value="over_75k">Over $75,000</option>
  </select>

  <fieldset>
    <legend>When should it start?</legend>
    <label><input type="radio" name="start" value="this_month" required /> This month</label>
    <label><input type="radio" name="start" value="next_quarter" /> In the next three months</label>
    <label><input type="radio" name="start" value="exploring" /> Exploring for now</label>
  </fieldset>

  <label for="description">Tell us about the project</label>
  <textarea id="description" name="description" rows="6" minlength="40" maxlength="4000" required></textarea>

  <input type="hidden" name="_redirect" value="https://studio.example/inquiry/thanks" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send inquiry</button>
</form>
```

## Webhook で問い合わせを振り分ける

この Express サーバーは各問い合わせを受け取って検証し、レーンを選び、そのレーンの Slack チャンネルに短い要約を投稿します。署名は Ikiform が送ったバイト列そのものが対象なので、生のボディを `express.raw` で読み、Node の `req.headers` をそのまま `verifyWebhook` に渡します。

`server.ts`:

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

const BUDGET: Record<string, number> = { under_10k: 0, "10k_30k": 1, "30k_75k": 2, over_75k: 3 };
const START: Record<string, number> = { this_month: 2, next_quarter: 1, exploring: 0 };
const CHANNEL = {
  hot: process.env.SLACK_HOT_LEADS!,
  warm: process.env.SLACK_LEADS!,
  "no-fit": process.env.SLACK_NO_FIT!,
};

function lane(fields: Record<string, unknown>): keyof typeof CHANNEL {
  const budget = BUDGET[String(fields.budget)] ?? 0;
  const start = START[String(fields.start)] ?? 0;
  const services = Array.isArray(fields.services) ? fields.services : [];
  if (budget === 0 && !services.includes("website")) return "no-fit";
  if (budget >= 2 && start >= 1) return "hot";
  return "warm";
}

const app = express();

app.post("/webhooks/inquiries", express.raw({ type: "application/json" }), async (req, res) => {
  let event;
  try {
    event = await verifyWebhook({
      payload: req.body.toString("utf8"),
      headers: req.headers,
      secret: process.env.IKIFORM_WEBHOOK_SECRET!,
    });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return res.status(400).send(error.reason);
    throw error;
  }
  if (event.type !== "submission.created") return res.sendStatus(204);

  const fields = event.data.fields;
  const which = lane(fields);
  const summary = String(fields.description ?? "").slice(0, 280);
  const response = await fetch(CHANNEL[which], {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      text: `[${which}] ${fields.name}: ${(fields.services as string[]).join(", ")}, ${fields.budget}, ${fields.start}\n> ${summary}\nmailto:${fields.email}`,
    }),
  });
  res.sendStatus(response.ok ? 204 : 502);
});

app.listen(3000);
```

- `lane()` は自分の売り方に合わせて変えてください。上のしきい値は例であり、助言ではありません。
- 要約は説明の最初の 280 文字です。全文はダッシュボードと `event.data.fields` にあります。
- Slack が失敗したときに `502` を返すと Ikiform が同じ配信を約 3 日間リトライするので、チャットの障害で問い合わせが失われることはありません。

サーバーの公開 `https:` URL を **Webhooks** に追加します。サーバーを動かしたくなければ、同じ分岐を [Zapier](https://ikiform.com/blog/form-submissions-to-zapier.md)、[Make](https://ikiform.com/blog/form-submissions-to-make.md)、[n8n](https://ikiform.com/blog/form-submissions-to-n8n.md) のルーターのステップで組めます。

## 自分のサービスがスパムのように聞こえるとき

スパムスコアには、`seo services`、`backlinks`、`rank your website` のような既知の売り込みの言い回しが含まれ、それぞれ 2 が加わります。検索関連の仕事を売っているなら、本物の顧客がまさにそう書くかもしれません。リンクも加算されます。`website` はリンクとして保存され、リンクが 3 つ以上あると 2 が加わります。

| 本物の問い合わせに含まれるもの | スコア | 結果 |
| --- | --- | --- |
| 「SEO サービスが必要です」とウェブサイト | +2 | 受信 |
| 同じものに加え、説明に競合のリンクが 2 つ | +2 と +2 | 受信。言い回しによる兆候が 1 つ |
| 上記すべてを 24 時間以内に 2 回送信 | +2、+2 と +3 | 5 を超えてスパム |

`services` に検索とコンテンツの選択肢があれば、顧客はその言い回しを入力せずに必要なものを伝えられます。それでも **Spam** フィルターは毎週確認してください。$50,000 の問い合わせを 1 件失うほうが、スパムを 10 件読むよりも高くつきます。

## 動作を確認する

1. サービスを 2 つチェックして送信します。送信データの `services` は 2 項目のリストとして保存されます。
2. **$75,000 超** と **今月** で送信します。要約が有望なチャンネルに届きます。
3. **$10,000 未満** と **ブランドアイデンティティ** だけで送信します。対象外のチャンネルに届きます。
4. 3,000 文字の説明を貼り付けます。通知メールでは値が 500 文字で切れますが、ダッシュボードではすべて表示されます。
5. サーバーを止めて送信します。**Webhooks** で配信の失敗した試行が表示され、サーバーを再起動して **Retry** を選ぶと成功します。

## ハマりどころ

- **チェックボックスが 1 つもチェックされていない。** 空のチェックボックスのグループは何も送らないので、HTML の `required` では強制できません。Ikiform は `Choose at least one option` で送信を拒否します。[リード獲得ガイド](https://ikiform.com/ja/guides/lead-capture.md#form)の `fetch` の版を使って、そのエラーをページに表示してください。
- **選択肢の名前を変える。** ラベルは自由に変えてかまいません。値を変えるときはリレーと一緒に変えてください。そうしないと、問い合わせが間違ったレーンに入ります。
- **メールでの長い概要。** 通知メールに表示されるのは 20 フィールドまで、値ごとに 500 文字までです。説明はそこで切れます。ワークスペースのメンバーには、メールに送信データ全体へのリンクが付きます。
- **断りの返信。** Ikiform はフォームに入力した人に何も送らないので、誰かが返信しない限り、対象外のリードには何も届きません。紹介先を添えた 2 行の断りで、関係をつないでおけます。

## よくある質問

### プロジェクトの問い合わせフォームでは何を尋ねるべきですか？

連絡先、必要なサービス、予算の範囲、開始時期、プロジェクトの説明です。選択式の 3 つの質問があれば、誰かが説明を読む前に問い合わせを振り分けられます。

### チェックボックスの回答はどう保存されますか？

name を共有するチェックボックスは 1 つのリストにまとめられます。multi_select フィールドを定義すると、Ikiform は一覧にある値だけを受け付けて配列として保存し、Webhook にもその形で入ります。

### 問い合わせフォームで予算を必須にすべきですか？

プロジェクトの問い合わせなら、たいていは必須にします。相性を示す最良の兆候で、最低限の契約額から始まる範囲にすれば自然な質問に感じられます。価格を自分で決める見積もり依頼では任意にしてください。

### SEO についての本物の問い合わせがスパムになったのはなぜですか？

seo services のような言い回しはスパムの兆候として数えられ、リンクもスコアに加算されます。24 時間以内の同一の再送と合わせると、しきい値の 5 に達します。スパムではないとマークしてメールと Webhook を送り、顧客がその言い回しを入力しなくて済むよう、検索関連の仕事はチェックボックスで選べるようにしてください。

## その他のガイド

- [リード獲得フォーム](https://ikiform.com/ja/guides/lead-capture.md): 自分のサイトに置くリード獲得フォームです。返信先付きでメールを送り、チームチャットに通知し、CRM に流し込むので、見込み客がまだいるうちに返信できます。
- [見積もり依頼フォーム](https://ikiform.com/ja/guides/lead-capture/quote-request.md): 資料をアップロードではなく共有リンクで受け取り、すべての依頼に期限を付け、リンクの多いリードがスパムにならないようにする見積もり依頼フォームです。
- [HubSpot や Pipedrive にリードを送る](https://ikiform.com/ja/guides/lead-capture/leads-to-crm.md): 署名付きの Ikiform の Webhook を、HubSpot の連絡先 upsert や Pipedrive の人物とリードの呼び出しに変換し、配信がリトライされても連絡先が重複しないようにします。
- [相談申し込みフォーム](https://ikiform.com/ja/guides/lead-capture/consultation-request.md): 会計士、弁護士、コーチ、クリニック向けの相談申し込みフォームです。連絡方法と時間を尋ね、デリケートな詳細は電話のときに回します。
- [デモ依頼フォーム](https://ikiform.com/ja/guides/lead-capture/demo-request.md): リードを保存してから、名前とメールアドレスを入力済みの状態で訪問者を Cal.com や Calendly に送るデモ予約フォームです。
- [Next.js のリードフォーム](https://ikiform.com/ja/guides/lead-capture/nextjs.md): Next.js App Router のリードフォームです。サーバーアクションで Zod による検証を行い、ファーストタッチの UTM を Cookie に保持し、条件に合うリードをカレンダーに送ります。
