# Buat formulir inquiry proyek untuk agensi atau freelancer

> Formulir mulai proyek untuk studio dan freelancer yang memilah inquiry menjadi hot, warm, dan tidak cocok berdasarkan anggaran dan waktu sebelum ada yang membaca brief-nya.

Terbit 2026-10-25 · https://ikiform.com/id/guides/lead-capture/project-inquiry

Tanyakan layanan sebagai checkbox, anggaran dan tanggal mulai sebagai pilihan tetap, serta deskripsi yang cukup panjang untuk menilai kecocokan. Kirim setiap inquiry lewat webhook ke relay kecil yang memilahnya ke jalur hot, warm, atau tidak cocok berdasarkan anggaran dan waktu. Lalu jawab jalur hot di hari yang sama, dan tolak jalur tidak cocok dengan sopan dalam sehari, karena kedua balasan membangun reputasi Anda.

## Apa yang berbeda dari inquiry proyek

Permintaan penawaran menanyakan harga untuk pekerjaan yang sudah jelas. Inquiry proyek mengajukan pertanyaan yang lebih besar: apakah kita cocok? Pengunjung sering masih membentuk proyeknya, dan Anda sedang memutuskan apakah layak menghabiskan satu discovery call untuknya. Bagi studio atau freelancer, yang langka bukan lead, melainkan jam partner yang habis untuk membaca brief yang tidak akan pernah terwujud.

Jadi formulir ini mengumpulkan cukup struktur untuk memilah sebelum membaca. Tiga jawaban sudah cukup: apa yang mereka butuhkan, kira-kira berapa yang bisa mereka belanjakan, dan kapan. Semua yang ingin Anda diskusikan ada di satu deskripsi panjang yang hanya dibaca lengkap saat jawaban terstruktur menunjukkan bahwa itu layak.

Diagram: Bagaimana relay memilah inquiry proyek ke jalur-jalur

1. Inquiry tiba sebagai webhook bertanda tangan berisi layanan, anggaran, dan tanggal mulai.
2. Relay memverifikasi tanda tangan dan memberi skor pada anggaran dan waktu.
3. Relay memeriksa skornya.
4. Anggaran $30.000 atau lebih yang dimulai dalam tiga bulan masuk ke jalur hot.
5. Anggaran lebih rendah atau mulai lebih lambat masuk ke jalur warm.
6. Di bawah $10.000 untuk apa pun selain website masuk ke jalur tidak cocok, untuk penolakan yang cepat dan ramah.

Jalur-jalur itu adalah channel chat. Tidak ada yang ditolak otomatis: seseorang tetap menjawab setiap jalur, dengan urutan berbeda.

## Field-nya

Untuk formulir lebih ringan dengan satu topik, mulailah dari [template formulir kontak](https://ikiform.com/forms/contact-form). Yang ini menambahkan tiga pertanyaan pemilah. Centang beberapa layanan di preview untuk melihatnya disimpan sebagai daftar.

Formulir: Project inquiry

- **Nama** (`name`, text, wajib)
- **Email** (`email`, email, wajib)
- **Website Anda saat ini** (`website`, url)
- **Apa yang Anda butuhkan?** (`services`, multi_select, wajib)
- **Budget** (`budget`, select, wajib)
- **Kapan sebaiknya dimulai?** (`start`, radio, wajib)
- **Ceritakan tentang proyeknya** (`description`, textarea, wajib)

`services` adalah `multi_select`, disimpan sebagai array seperti `["brand", "website"]`. `website` adalah field `url`, jadi `example.com` disimpan sebagai `https://example.com/`.

| Field | Mengapa bentuknya begini |
| --- | --- |
| `services` | Checkbox, karena proyek nyata menggabungkan beberapa layanan. Tiba sebagai array di webhook |
| `budget` | Wajib di sini, berbeda dengan formulir penawaran. Rentang Anda sebaiknya dimulai dari nilai engagement minimum Anda |
| `start` | **Exploring for now** (masih menjajaki) adalah jawaban yang jujur, dan berguna: masuk ke jalur warm |
| `description` | Minimal 40 karakter, maksimal 4.000. Cukup panjang untuk menilai kecocokan, cukup pendek agar orang menyelesaikannya |

## Formulirnya

Checkbox berbagi satu `name`. Browser mengirim `services=brand&services=website`, dan Ikiform mengumpulkan pengulangannya menjadi satu daftar. Mengakhiri nama dengan `[]` juga bisa, jika tooling Anda mengharapkannya.

`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>
```

## Pilah inquiry lewat webhook

Server Express ini menerima setiap inquiry, memverifikasinya, memilih jalur, dan mengirim ringkasan pendek ke channel Slack jalur itu. Server membaca raw body dengan `express.raw`, karena tanda tangan mencakup byte persis yang dikirim Ikiform, dan meneruskan `req.headers` milik Node ke `verifyWebhook` apa adanya.

`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);
```

- Ubah `lane()` agar sesuai cara Anda berjualan. Ambang batas di atas hanyalah contoh, bukan saran.
- Ringkasannya adalah 280 karakter pertama dari deskripsi. Teks lengkapnya ada di dashboard dan di `event.data.fields`.
- `502` saat Slack gagal membuat Ikiform mencoba ulang pengiriman yang sama selama sekitar 3 hari, jadi inquiry tidak hilang karena chat sedang down.

Tambahkan URL `https:` publik server di **Webhooks**. Jika Anda tidak ingin menjalankan server, percabangan yang sama bisa dibuat sebagai langkah router di [Zapier](https://ikiform.com/blog/form-submissions-to-zapier.md), [Make](https://ikiform.com/blog/form-submissions-to-make.md), atau [n8n](https://ikiform.com/blog/form-submissions-to-n8n.md).

## Saat layanan Anda sendiri terdengar seperti spam

Penilaian spam mencakup frasa penawaran penjualan yang dikenal, seperti `seo services`, `backlinks`, dan `rank your website`, masing-masing menambah 2. Jika Anda menjual jasa search, klien sungguhan mungkin menulis persis itu. Tautan juga bertambah: `website` disimpan sebagai tautan, dan tiga tautan atau lebih menambah 2.

| Inquiry asli yang berisi | Skor | Hasil |
| --- | --- | --- |
| "We need SEO services" dan sebuah website | +2 | Diterima |
| Sama, ditambah dua tautan kompetitor di deskripsi | +2 dan +2 | Diterima, satu sinyal dari baris itu |
| Semua yang di atas, dikirim dua kali dalam 24 jam | +2, +2 dan +3 | Spam, di atas 5 |

Opsi search dan konten di `services` memungkinkan klien menyatakan kebutuhannya tanpa mengetik frasa itu. Tetap periksa filter **Spam** setiap minggu; inquiry $50.000 yang hilang lebih mahal daripada membaca sepuluh kiriman spam.

## Pastikan berfungsi

1. Kirim dengan dua layanan dicentang. Kiriman menyimpan `services` sebagai daftar dua item.
2. Kirim dengan **Over $75,000** dan **This month**. Ringkasannya masuk ke channel hot.
3. Kirim dengan **Under $10,000** dan hanya **Brand identity**. Masuk ke channel tidak cocok.
4. Tempel deskripsi 3.000 karakter. Email notifikasi memotong nilainya di 500 karakter; dashboard menampilkan semuanya.
5. Hentikan server Anda lalu kirim. Pengiriman menampilkan percobaan gagal di **Webhooks**, lalu berhasil saat Anda menjalankannya lagi dan memilih **Retry**.

## Hal yang sering menjebak

- **Tidak ada checkbox yang dicentang.** Grup checkbox kosong tidak mengirim apa pun, jadi `required` HTML tidak bisa menegakkannya. Ikiform menolak kiriman dengan `Choose at least one option`; tampilkan error itu di halaman dengan versi `fetch` dari [panduan lead capture](https://ikiform.com/id/guides/lead-capture.md#form).
- **Mengganti nama opsi.** Ubah label sesuka Anda. Ubah nilai hanya bersamaan dengan relay, atau inquiry masuk ke jalur yang salah.
- **Brief panjang di email.** Email notifikasi menampilkan hingga 20 field dan 500 karakter per nilai. Deskripsi terpotong di sana. Anggota workspace mendapat tautan ke kiriman lengkap di email.
- **Penolakan.** Ikiform tidak mengirim apa pun ke orang yang mengisi formulir, jadi lead yang tidak cocok tidak mendengar apa-apa kecuali ada yang membalas. Penolakan dua baris dengan rujukan menjaga pintu tetap terbuka.

## Pertanyaan

### Apa yang sebaiknya ditanyakan formulir inquiry proyek?

Detail kontak, layanan yang dibutuhkan, rentang anggaran, tanggal mulai, dan deskripsi proyek. Tiga pertanyaan pilihan tetap memungkinkan Anda memilah inquiry sebelum ada yang membaca deskripsinya.

### Bagaimana jawaban checkbox disimpan?

Checkbox yang berbagi nama dikumpulkan menjadi satu daftar. Dengan field multi_select terdefinisi, Ikiform hanya menerima nilai yang terdaftar dan menyimpannya sebagai array, yang juga dibawa webhook.

### Haruskah saya mewajibkan anggaran di formulir inquiry?

Untuk inquiry proyek, biasanya ya: itu sinyal kecocokan terbaik, dan rentang yang dimulai dari engagement minimum Anda membuat pertanyaan itu terasa wajar. Untuk permintaan penawaran, saat Anda yang menentukan harga, jadikan opsional.

### Mengapa inquiry asli tentang SEO masuk ke spam?

Frasa seperti seo services dihitung sebagai sinyal spam, dan tautan menambah skor. Bersama pengulangan identik dalam 24 jam, skornya mencapai ambang batas 5. Tandai sebagai bukan spam untuk mengirim email dan webhook-nya, dan tawarkan jasa search sebagai checkbox agar klien tidak perlu mengetik frasa itu.

## Panduan lainnya

- [Formulir lead capture](https://ikiform.com/id/guides/lead-capture.md): Formulir lead capture di situs Anda sendiri yang mengirimi Anda email dengan reply-to, memberi tahu chat tim, dan mengisi CRM, agar Anda menjawab selagi lead masih ada.
- [Formulir permintaan penawaran](https://ikiform.com/id/guides/lead-capture/quote-request.md): Formulir minta penawaran yang mengumpulkan brief sebagai tautan bersama alih-alih unggahan, memberi tenggat pada setiap permintaan, dan menjauhkan lead yang penuh tautan dari spam.
- [Lead ke HubSpot atau Pipedrive](https://ikiform.com/id/guides/lead-capture/leads-to-crm.md): Petakan setiap webhook Ikiform bertanda tangan ke contact upsert HubSpot atau panggilan person dan lead Pipedrive, tanpa kontak duplikat saat pengiriman dicoba ulang.
- [Formulir permintaan konsultasi](https://ikiform.com/id/guides/lead-capture/consultation-request.md): Formulir permintaan konsultasi untuk akuntan, pengacara, coach, dan klinik yang menanyakan cara dan waktu menghubungi, dan menyimpan detail sensitif untuk panggilannya.
- [Formulir permintaan demo](https://ikiform.com/id/guides/lead-capture/demo-request.md): Formulir pesan demo yang menyimpan lead, lalu mengarahkan pengunjung ke Cal.com atau Calendly dengan nama dan email yang sudah terisi.
- [Formulir lead Next.js](https://ikiform.com/id/guides/lead-capture/nextjs.md): Formulir lead App Router Next.js yang memvalidasi dengan Zod di server action, menyimpan UTM first-touch di cookie, dan mengirim lead yang lolos kualifikasi ke kalender Anda.
