# Monte um formulário de consulta de projeto para agência ou freelancer

> Um formulário de "comece um projeto" para estúdios e freelancers que separa as consultas em quentes, mornas e sem fit por orçamento e prazo antes de alguém ler o briefing.

Publicado em 2026-10-25 · https://ikiform.com/pt-br/guides/lead-capture/project-inquiry

Peça os serviços como checkboxes, orçamento e data de início como escolhas fixas, e uma descrição longa o bastante para avaliar o fit. Envie cada consulta por webhook para um pequeno relay que a separa nas filas quente, morna ou sem fit por orçamento e prazo. Depois responda a fila quente no mesmo dia e recuse a fila sem fit com educação em até um dia, porque as duas respostas constroem a sua reputação.

## O que muda numa consulta de projeto

Um pedido de orçamento pede o preço de um trabalho conhecido. Uma consulta de projeto faz uma pergunta maior: temos fit? O visitante muitas vezes ainda está moldando o projeto, e você está decidindo se vale gastar uma reunião de discovery com ele. Para um estúdio ou um freelancer, o que falta não são leads, são as horas dos sócios gastas lendo briefings que nunca iam sair do papel.

Então este formulário coleta estrutura suficiente para separar antes de ler. Três respostas resolvem: do que a pessoa precisa, mais ou menos quanto pode gastar e quando. Tudo o que você gostaria de discutir fica numa descrição longa que só é lida inteira quando as respostas estruturadas dizem que vale a pena.

Diagrama: Como um relay separa as consultas de projeto em filas

1. A consulta chega como um webhook assinado com serviços, orçamento e data de início.
2. O relay verifica a assinatura e pontua orçamento e prazo.
3. Ele confere a pontuação.
4. Um orçamento de US$ 30.000 ou mais com início em até três meses vai para a fila quente.
5. Um orçamento menor ou um início mais tarde vai para a fila morna.
6. Menos de US$ 10.000 para qualquer coisa que não seja um site vai para a fila sem fit, para uma recusa rápida e gentil.

As filas são canais de chat. Ninguém é recusado automaticamente: uma pessoa ainda responde todas as filas, em ordens diferentes.

## Os campos

Para um formulário mais leve, com um único assunto, comece pelo [modelo de formulário de contato](https://ikiform.com/forms/contact-form). Este acrescenta as três perguntas de triagem. Marque vários serviços na prévia para vê-los armazenados como lista.

Formulário: Project inquiry

- **Nome** (`name`, text, obrigatório)
- **E-mail** (`email`, email, obrigatório)
- **Seu site atual** (`website`, url)
- **Do que você precisa?** (`services`, multi_select, obrigatório)
- **Orçamento** (`budget`, select, obrigatório)
- **Quando deve começar?** (`start`, radio, obrigatório)
- **Conte sobre o projeto** (`description`, textarea, obrigatório)

`services` é um `multi_select`, armazenado como um array como `["brand", "website"]`. `website` é um campo `url`, então `example.com` é armazenado como `https://example.com/`.

| Campo | Por que ele tem esse formato |
| --- | --- |
| `services` | Checkboxes, porque projetos reais combinam serviços. Chega como array no webhook |
| `budget` | Obrigatório aqui, diferente de um formulário de orçamento. As suas faixas devem começar onde começa o seu valor mínimo de contrato |
| `start` | **Só explorando por enquanto** é uma resposta honesta, e útil: vai para a fila morna |
| `description` | Pelo menos 40 caracteres, no máximo 4.000. Longo o bastante para avaliar o fit, curto o bastante para as pessoas terminarem |

## O formulário

As checkboxes compartilham um mesmo `name`. O navegador envia `services=brand&services=website`, e o Ikiform junta as repetições numa lista. Terminar o nome com `[]` também funciona, se as suas ferramentas esperam isso.

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

## Separe as consultas por webhook

Este servidor Express recebe cada consulta, verifica, escolhe uma fila e publica um resumo curto no canal do Slack dessa fila. Ele lê o corpo bruto com `express.raw`, porque a assinatura cobre exatamente os bytes que o Ikiform enviou, e passa os `req.headers` do Node para `verifyWebhook` como estão.

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

- Mude `lane()` para refletir como você vende. Os limites acima são um exemplo, não um conselho.
- O resumo são os primeiros 280 caracteres da descrição. O texto completo fica no painel e em `event.data.fields`.
- Um `502` quando o Slack falha faz o Ikiform tentar de novo a mesma entrega por cerca de 3 dias, para que nenhuma consulta se perca numa queda do chat.

Adicione a URL pública `https:` do servidor em **Webhooks**. Se você prefere não rodar um servidor, a mesma ramificação funciona como um passo de router no [Zapier](https://ikiform.com/blog/form-submissions-to-zapier.md), no [Make](https://ikiform.com/blog/form-submissions-to-make.md) ou no [n8n](https://ikiform.com/blog/form-submissions-to-n8n.md).

## Quando os seus próprios serviços parecem spam

A pontuação de spam inclui frases conhecidas de pitch de vendas, como `seo services`, `backlinks` e `rank your website`, cada uma somando 2. Se você vende trabalho de busca, um cliente real pode escrever exatamente isso. Links também se somam: `website` é armazenado como link, e três ou mais links somam 2.

| Uma consulta real que contém | Pontuação | Resultado |
| --- | --- | --- |
| "We need SEO services" e um site | +2 | Recebido |
| O mesmo, mais dois links de concorrentes na descrição | +2 e +2 | Recebida, a um sinal do limite |
| Tudo isso, enviado duas vezes em até 24 horas | +2, +2 e +3 | Spam, acima de 5 |

Uma opção de busca e conteúdo em `services` deixa os clientes dizerem do que precisam sem digitar a frase. Mesmo assim, confira o filtro **Spam** toda semana; perder uma consulta de US$ 50.000 custa mais do que ler dez envios de spam.

## Confira se funciona

1. Envie com dois serviços marcados. O envio armazena `services` como uma lista de dois itens.
2. Envie com **Mais de US$ 75.000** e **Este mês**. O resumo cai no canal quente.
3. Envie com **Menos de US$ 10.000** e só **Identidade visual**. Ele cai no canal sem fit.
4. Cole uma descrição de 3.000 caracteres. O e-mail de notificação corta o valor em 500 caracteres; o painel mostra tudo.
5. Pare o seu servidor e envie. A entrega mostra tentativas com falha em **Webhooks** e depois dá certo quando você o inicia de novo e escolhe **Retry**.

## Pegadinhas

- **Nenhuma checkbox marcada.** Um grupo de checkboxes vazio não envia nada, então o `required` do HTML não consegue exigi-lo. O Ikiform recusa o envio com `Choose at least one option`; mostre esse erro na página com a versão `fetch` do [guia de captação de leads](https://ikiform.com/pt-br/guides/lead-capture.md#form).
- **Renomear opções.** Mude os rótulos à vontade. Mude os valores só junto com o relay, ou as consultas caem na fila errada.
- **Briefings longos no e-mail.** Os e-mails de notificação mostram até 20 campos e 500 caracteres por valor. A descrição é cortada ali. Os membros do workspace recebem no e-mail um link para o envio completo.
- **A recusa.** O Ikiform não envia nada para quem preencheu o formulário, então um lead sem fit não fica sabendo de nada a menos que alguém responda. Uma recusa de duas linhas com uma indicação mantém a porta aberta.

## Perguntas

### O que um formulário de consulta de projeto deve perguntar?

Dados de contato, os serviços de que a pessoa precisa, uma faixa de orçamento, uma data de início e uma descrição do projeto. As três perguntas de escolha fixa permitem separar as consultas antes de alguém ler a descrição.

### Como as respostas de checkbox são armazenadas?

Checkboxes que compartilham um nome são reunidas numa lista. Com um campo multi_select definido, o Ikiform só aceita os valores listados e os armazena como array, que é o que o webhook leva.

### Devo exigir orçamento num formulário de consulta?

Numa consulta de projeto, geralmente sim: é o melhor sinal isolado de fit, e faixas que começam no seu valor mínimo de contrato fazem a pergunta parecer normal. Num pedido de orçamento, em que você define o preço, deixe opcional.

### Por que uma consulta real sobre SEO caiu no spam?

Frases como seo services contam como sinal de spam, e links somam na pontuação. Junto com uma repetição idêntica em até 24 horas, isso atinge o limite de 5. Marque como não spam para disparar o e-mail e o webhook dela, e ofereça trabalho de busca como checkbox para os clientes não precisarem digitar a frase.

## Mais guias

- [Formulário de captação de leads](https://ikiform.com/pt-br/guides/lead-capture.md): Um formulário de leads no seu próprio site que envia e-mail com reply-to, avisa o chat da equipe e alimenta seu CRM, para você responder enquanto o lead ainda está lá.
- [Formulário de pedido de orçamento](https://ikiform.com/pt-br/guides/lead-capture/quote-request.md): Um formulário de pedido de orçamento que recebe briefings como links compartilhados em vez de uploads, coloca um prazo em cada pedido e mantém leads cheios de links fora do spam.
- [Leads no HubSpot ou no Pipedrive](https://ikiform.com/pt-br/guides/lead-capture/leads-to-crm.md): Mapeie cada webhook assinado do Ikiform para o upsert de contatos do HubSpot ou para as chamadas de pessoa e lead do Pipedrive, sem contatos duplicados quando uma entrega é repetida.
- [Formulário de pedido de consulta](https://ikiform.com/pt-br/guides/lead-capture/consultation-request.md): Um formulário de pedido de consulta para contadores, advogados, coaches e clínicas que pergunta como e quando ligar, e deixa os detalhes sensíveis para a conversa.
- [Formulário de pedido de demonstração](https://ikiform.com/pt-br/guides/lead-capture/demo-request.md): Um formulário de agendar demonstração que armazena o lead e depois manda o visitante para o Cal.com ou o Calendly com nome e e-mail já preenchidos.
- [Formulário de leads em Next.js](https://ikiform.com/pt-br/guides/lead-capture/nextjs.md): Um formulário de leads no App Router do Next.js que valida com Zod numa server action, guarda as UTMs do primeiro toque num cookie e manda leads qualificados para a sua agenda.
