Guias

Guias17 min de leitura

Adicione um formulário de feedback ao seu site ou app

Coloque um formulário de feedback em qualquer página ou dentro do seu app: uma nota, um comentário, a página de origem, filtro de spam e alertas para notas baixas.

Preet SutharFundador, Ikiform

Adicione um formulário curto com uma nota de 1 a 5, um comentário opcional e um e-mail opcional, e envie a um backend de formulários para não precisar rodar um servidor para isso. Mande o endereço da página junto com cada resposta, porque o navegador não informa a URL completa por conta própria. Encaminhe as notas baixas para o chat da equipe no mesmo dia e guarde todas as respostas em um só lugar para ver tendências.

A maioria das pessoas nunca conta o que está errado no seu site. Elas simplesmente vão embora. Um pequeno formulário de feedback pega as poucas que vão falar, no momento em que percebem, na página que causou o problema. Este guia monta um que serve para qualquer site ou app, envia a página de origem, mantém os bots longe e coloca as respostas insatisfeitas na frente da sua equipe no mesmo dia.

Como funciona um formulário de feedback

O formulário envia ao Ikiform. O Ikiform valida a nota, verifica se o envio é spam, armazena, avisa sua equipe por e-mail e envia um webhook assinado. A partir do webhook, as notas baixas vão para um canal de chat e todas as respostas podem ir para uma planilha ou banco de dados.

Como um feedback vai da sua página até a sua equipequalquerpágina outela do appnota,comentário,endereço dapáginaIkiformvalida, filtraspam, armazenapainelfiltrar porformulário edata, exportarCSVe-mail denotificaçãopara a equipe,resposta vai aovisitantewebhookassinadosubmission.createdcom campos emetachat daequipesó notas 1 ou 2enviorelayComo um feedback vai da sua página até a sua equipequalquerpágina outela do appnota,comentário,endereço dapáginaIkiformvalida, filtraspam, armazenapainelfiltrar porformulário e data,exportar CSVe-mail denotificaçãopara a equipe,resposta vai aovisitantewebhookassinadosubmission.createdcom campos e metachat da equipesó notas 1 ou 2enviorelay
  1. Um visitante escolhe uma nota, talvez escreva um comentário, e o formulário envia tudo com o endereço da página.
  2. O Ikiform confere se a nota é um número inteiro de 1 a 5, roda as verificações de spam e armazena a resposta.
  3. A resposta aparece no painel, onde você pode filtrá-la e exportá-la como CSV.
  4. O Ikiform envia um e-mail para a sua equipe. Quando o visitante deixou um e-mail, o Reply (responder) vai direto para ele.
  5. O Ikiform envia um webhook submission.created assinado com os campos e os metadados do navegador.
  6. Um pequeno relay posta só as notas baixas no chat da equipe, para que sejam lidas no mesmo dia.
O relay é opcional. Comece com o e-mail e o painel, e adicione o alerta no chat quando as respostas começarem a se acumular.

Formas de coletar feedback

Cada tipo de ferramenta foi feito para um trabalho diferente. Escolha pelo que você precisa ver quando chega uma resposta, não pela aparência do widget.

AbordagemBom emContras
Ferramentas de feedback para sites, como Hotjar ou UsersnapCapturas de tela, anotações e contexto da página sem código além de uma tag script.Um script de terceiros em todas as páginas, respostas armazenadas no produto deles e preço definido pelos planos deles.
O widget de um rastreador de erros, como o Sentry User FeedbackLiga um relato ao erro e, com o session replay ligado, a uma gravação do que aconteceu.Feito para bugs, não para opiniões. Você precisa do SDK do rastreador no seu app primeiro.
Criadores de formulários, como Typeform, Tally ou Google FormsFormulários caprichados sem código. Bom para uma pesquisa que você manda por link.Um iframe ou uma página separada, então a resposta perde a página a que se refere, a menos que você a passe na URL.
Quadros de feedback, como o CannyVotação pública e atualizações de status em pedidos de funcionalidades.Feito para ideias, não para reações rápidas. As respostas são públicas por definição.
Sua própria rota de API e banco de dadosControle total sobre os dados e qualquer lógica.Você mesmo constrói filtro de spam, limites de taxa, e-mail de notificação e exportação, e precisa de um servidor.
Um backend de formulários, como o IkiformSeu próprio markup em qualquer site ou app. Validação, filtro de spam, armazenamento, e-mail e webhooks assinados sem servidor.Sem capturas de tela, porque upload de arquivos não é suportado, e sem votação nem session replay.

Se você precisa de capturas de tela em todo relato, uma ferramenta de feedback ou um rastreador de erros justifica o script. Se você quer que o formulário tenha a cara do seu site, manter as respostas portáteis e decidir você mesmo para onde elas vão, use um backend de formulários. O resto deste guia faz isso.

O formulário

Três perguntas bastam: uma nota, um comentário e um e-mail opcional. A nota é a que as pessoas respondem; o comentário é onde está o valor; o e-mail é como você fecha o ciclo. Escolha sua stack abaixo; a escolha vale para todos os exemplos de código destes guias.

Um bloco de markup e um script curto. Sem JavaScript, o formulário ainda envia e redireciona; com ele, o visitante fica na página e vê o erro do servidor ao lado do botão. O script preenche page com o endereço sem a query string, para que tokens em URLs nunca cheguem à sua caixa de entrada.

feedback.html
<form id="feedback" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <fieldset>
    <legend>How useful was this page?</legend>
    <label><input type="radio" name="rating" value="1" required /> 1</label>
    <label><input type="radio" name="rating" value="2" /> 2</label>
    <label><input type="radio" name="rating" value="3" /> 3</label>
    <label><input type="radio" name="rating" value="4" /> 4</label>
    <label><input type="radio" name="rating" value="5" /> 5</label>
  </fieldset>
  <label for="comment">What would make it better?</label>
  <textarea id="comment" name="comment" rows="4" maxlength="4000"></textarea>
  <label for="feedback-email">Email, if you'd like a reply</label>
  <input id="feedback-email" name="email" type="email" />
  <input type="hidden" name="page" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send feedback</button>
  <p id="feedback-status" role="status"></p>
</form>

<script>
  const form = document.getElementById("feedback");
  const status = document.getElementById("feedback-status");
  form.elements.page.value = location.origin + location.pathname;

  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const button = form.querySelector("button");
    button.disabled = true;
    status.textContent = "Sending";
    try {
      const response = await fetch(form.action, {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(form),
      });
      const result = await response.json();
      if (result.ok) {
        form.replaceChildren(Object.assign(document.createElement("p"), { textContent: "Thanks. The team reads every note." }));
        return;
      }
      const fields = result.error.fields ?? {};
      status.textContent = fields.rating?.[0] ?? fields.comment?.[0] ?? fields.email?.[0] ?? result.error.message;
    } catch {
      status.textContent = "Couldn't send it. Try again in a moment.";
    }
    button.disabled = false;
  });
</script>
  • Troque frm_xxxxxxxxxxxxxxxx pelo id do seu formulário, que está no painel.
  • rating é um grupo de radio com cinco valores. O Ikiform o armazena como número, então médias não exigem parsing.
  • email é opcional. As pessoas escrevem com mais honestidade quando não precisam se identificar, e quem quer uma resposta vai deixá-lo.
  • O input oculto _gotcha é o honeypot. As pessoas nunca o veem; bots que preenchem todos os inputs se marcam como spam.
  • page registra a qual página a resposta se refere. A próxima seção explica por que você mesmo a envia.
As versões no servidor enviam com uma chave secreta, então o Ikiform pula Allowed domains e a verificação humana. Todo envio passa a vir do IP do seu servidor, e o limite Standard de 5 por minuto por visitante conta todos os seus visitantes juntos. Escolha o limite de taxa Relaxed ou Custom para um formulário que você envia por um servidor, e mantenha IKIFORM_SECRET_KEY em variáveis de ambiente só do servidor.

Os guias de frameworks na documentação cobrem a configuração com mais detalhes: Next.js, Astro, SvelteKit, Nuxt, React, Vue e HTML puro. O modelo de formulário de feedback gera os mesmos campos em HTML, React e server action; os modelos de relato de bug e de pesquisa cobrem os formulários mais longos.

Defina os campos

Cole uma definição na aba Fields do formulário e o Ikiform a aplica em todo envio, de qualquer página. Teste abaixo: a prévia roda o validador do Ikiform no seu navegador, então uma nota 0 ou um e-mail malformado mostra o 422 que você receberia de volta.

Prévia

Roda o validador do Ikiform no seu navegador. Nada é enviado.

Quão útil foi esta página?

Preenchido pelo script com o endereço da página, sem a query string.

Um rating aceita um número inteiro de 1 até o seu max, aqui 5. Ele pode ir até 10, mas cinco opções são mais rápidas de responder.
CampoTipoPor quê
ratingrating, máx. 5Um clique. Armazenado como número, então dá para tirar a média por página
commenttextarea, até 4.000 caracteresO motivo por trás da nota
emailemail, opcionalResponder a quem faz uma pergunta. Vira o reply-to da notificação
pageurl, opcionalA qual página a resposta se refere

Com campos definidos, qualquer outro nome no envio é recusado como Unknown field. Se depois você mandar mais contexto, como uma versão do app ou o nome de um plano, adicione um campo para ele antes. Ids de campo usam snake_case em minúsculas.

Saiba a qual página se refere

Uma nota sem página é difícil de usar. O Ikiform registra os metadados do navegador em cada envio, mas um desses valores é menos útil do que parece:

ValorDe onde vemO que você recebe
meta.user_agentRegistrado pelo IkiformO navegador e o sistema operacional, de um envio pelo navegador
meta.originRegistrado pelo IkiformA origem do seu site, como https://example.com
meta.referrerRegistrado pelo IkiformNormalmente só a origem. Os navegadores usam por padrão a política strict-origin-when-cross-origin, que remove o caminho ao enviar para outro site
meta.countryRegistrado pelo IkiformUm código de país de duas letras
pageEnviado pelo seu formulárioO caminho completo, para você saber a qual página a resposta se refere

É por isso que todos os exemplos acima enviam page por conta própria. As versões HTML e SPA leem location; as versões de servidor leem o endereço que o próprio framework já conhece. Todas removem a query string, que pode conter termos de busca, ids de rastreamento ou tokens de uso único que você não quer armazenar.

As versões de servidor enviam a partir do seu servidor, então meta.user_agent é o runtime do seu servidor, não o navegador do visitante. Para feedback sobre páginas isso raramente importa. Para relatos de bug importa, e o guia de relato de bug encaminha o user agent do navegador como um campo.

Onde perguntar

O lugar do formulário decide o que você ouve. Um formulário no rodapé de todas as páginas recebe um fio de opiniões fortes. Uma pergunta no fim de uma tarefa recebe respostas constantes e específicas.

PosiçãoBom paraCuidado com
Fim de uma página de documentação ou artigoEncontrar páginas que não respondem à perguntaPouco volume por página. Leia por seção, não por página
Depois de uma tarefa no seu app, como uma exportação ou o primeiro projetoComo um fluxo específico é percebido, enquanto ainda está frescoPergunte uma vez por pessoa, não toda vez que ela terminar a tarefa
Um botão flutuante em todas as telasQualquer coisa, a qualquer hora. Veja o widget em ReactEle não pode cobrir seus próprios botões, banners de cookies ou bolhas de chat
Um link num e-mailNotas que você quer acompanhar ao longo do tempo, como o NPSO cliente de e-mail não é a sua página, então o formulário precisa de uma landing page no seu site

Mantenha o formulário pequeno onde quer que ele fique. Peça a nota primeiro e mostre a caixa de comentário junto, não numa segunda etapa. Uma segunda etapa perde a maioria das pessoas, e uma nota sem motivo ainda vale a pena.

Coloque as notas baixas na frente das pessoas

O que acontece com uma resposta conforme a notarespostaarmazenadatoda nota, todapáginawebhooksubmission.createdrelayconferea nota3, 4 ou 5:nada maisrevisãosemanalmédias porpágina do CSVchat daequipenota, página,comentárioalguémrespondequando deixoue-mailassinadoexportar1 ou 2O que acontece com uma resposta conforme a notarespostaarmazenadatoda nota, toda páginawebhooksubmission.createdrelayconfere anota3, 4 ou 5: nadamaisrevisão semanalmédias por página doCSVchat daequipenota, página,comentárioalguémrespondequandodeixoue-mailassinadoexportar1 ou 2
  1. Toda resposta é armazenada, seja qual for a nota e a página de origem.
  2. O Ikiform envia um webhook submission.created assinado para o seu relay.
  3. O relay lê a nota. Notas de 3 a 5 não precisam de mais nada de imediato.
  4. Uma nota 1 ou 2 vai para o chat da equipe com a página e o comentário.
  5. Se o visitante deixou um e-mail, alguém responde no mesmo dia.
  6. Uma vez por semana, a exportação mostra as médias por página, que é onde as tendências aparecem.
Alerte só sobre as notas ruins. Um canal que apita a cada 5 de 5 é silenciado em uma semana.

Os e-mails de notificação vão para até 10 destinatários confirmados por formulário e chegam a cada resposta. Isso funciona para algumas respostas por dia. Acima disso, mande as notas baixas para o chat com um relay como esta rota do Next.js; o mesmo código roda num Cloudflare Worker:

app/api/feedback-alerts/route.ts
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";

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 { rating, comment, page, email } = event.data.fields;
    if (Number(rating) > 2) return new Response(null, { status: 204 });

    const lines = [
      `*${rating}/5* on ${page ?? event.data.meta.origin ?? "an unknown page"}`,
      comment ? `> ${String(comment).slice(0, 500)}` : "_No comment._",
      email ? `Reply to ${email}` : "Anonymous",
    ];
    const response = await fetch(process.env.SLACK_WEBHOOK_URL!, {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ text: lines.join("\n") }),
    });
    if (!response.ok) return new Response(`Slack 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 confere a assinatura e o timestamp, para que ninguém mais consiga postar no seu canal por esta URL.
  • Notas acima de 2 respondem 204 e param. O Ikiform trata qualquer 2xx como entregue.
  • Uma chamada ao Slack que falha responde 502, e o Ikiform tenta de novo com o mesmo webhook-id, então uma queda curta não faz perder um alerta.
  • Os valores dos campos são o que o visitante digitou. O relay corta o comentário em 500 caracteres antes de chegar ao chat.

Adicione o endpoint em Webhooks e copie o secret whsec_ dele para IKIFORM_WEBHOOK_SECRET. Um workspace pode ter 3 endpoints. Para caminhos sem código, veja Slack, Discord e Google Sheets. Para feedback que deve virar um ticket, Linear e GitHub Issues tem um relay que cria um por envio.

Não há integrações de um clique. Toda ferramenta é alcançada por um webhook assinado, diretamente ou por uma ferramenta de automação como Zapier ou n8n.

Mantenha os bots longe

Um formulário de feedback em todas as páginas é um formulário público em todas as páginas. Os bots o encontram, e quase tudo o que mandam são links. Os padrões do Ikiform cuidam da maior parte:

DefesaO que ela barraConfiguração
HoneypotBots que preenchem todos os inputsO input oculto _gotcha nos exemplos
Pontuação de spamTrês ou mais links (+2), frases de spam conhecidas (+2), e-mails descartáveis (+2), repetições idênticas (+3). Com 5, é armazenado como spamNenhuma
Limites de taxaScripts que enviam em loopLigado por padrão: Standard, 5 por minuto por visitante, e 300 por minuto para o formulário inteiro
Domínios permitidosEnvios de outros sitesAdicione seu domínio nas configurações do formulário
Verificação humanaBots que rodam um navegador de verdadeDefina Spam check como Ikiform. Envios por fetch no navegador passam a precisar de um token de challenge()

O spam recebe a mesma resposta de sucesso que um envio real, não dispara e-mail nem webhook e não conta no uso. Um visitante real que cola três links num comentário pode acionar a regra de links junto com uma repetição, então olhe o filtro Spam de vez em quando. Marcar uma resposta como não spam envia o webhook dela nesse momento. A documentação de spam explica cada verificação.

Leia as respostas

Leia todos os comentários nas primeiras semanas. Depois disso, a visão útil é a nota média por página, da menor para a maior, com os comentários ao lado.

Exportar

Abra Submissions, escolha o formulário de feedback, selecione um intervalo de datas e clique em Export CSV. As colunas são id, created_at, form e status, depois uma por campo, então com os campos acima rating é a coluna E e page é a coluna H. Uma exportação comporta até 100.000 linhas; o guia de exportação cobre a API para mais que isso.

Importe o arquivo no Google Sheets e coloque isto numa planilha vazia. Ela lista cada página com sua nota média e o número de respostas, da pior para a melhor:

Google Sheets
=QUERY(A2:H, "select H, avg(E), count(E) where D = 'received' and E is not null group by H order by avg(E) asc label avg(E) 'average', count(E) 'answers'", 0)
  1. Ignore páginas com só uma ou duas respostas. Um visitante irritado não é uma tendência.
  2. Leia os comentários das três páginas com notas mais baixas. A correção costuma estar nos primeiros.
  3. Depois de mudar uma página, compare a média dela nas semanas antes e depois, não o número de todos os tempos.
O feedback não é anônimo para o Ikiform mesmo sem e-mail: cada resposta registra o user agent, a origem, o referrer e o país, além de um hash do IP que nunca é devolvido. Diga o que você coleta no seu aviso de privacidade.

Escolha o seu caso

O formulário acima cobre reações rápidas em qualquer página. Estas páginas cobrem feedback com outro objetivo: um bug para reproduzir, um pedido para avaliar, uma nota para acompanhar ou um cliente de saída.

Confira se funciona

Repasse isto antes de colocar o formulário em todas as páginas. O Ikiform não tem plano gratuito. Testar é grátis: um workspace sem plano aceita 50 envios de teste por mês a partir de localhost. Para entrar no ar, escolha o Pro a partir de US$ 6/mês para 500 envios, ou pague uma vez: 10.000 envios por US$ 49 ou 50.000 envios por US$ 149, com créditos que nunca expiram. Veja os preços.

  1. Em Allowed domains do formulário, adicione o domínio do seu site, mais localhost enquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar.
  2. Escolha uma nota, escreva um comentário e envie. A frase de agradecimento substitui o formulário, ou o navegador cai na sua página de redirecionamento na versão em HTML puro.
  3. Abra Submissions no painel. A resposta mostra rating como número e page com o caminho completo.
  4. Envie uma nota 6 com curl ou pelo console do navegador. O Ikiform responde 422 apontando rating.
  5. Confira a caixa de entrada de cada destinatário das notificações. Cada um recebe um e-mail com os campos, e Reply vai para quem enviou quando o formulário tem um campo email.
  6. Envie uma nota 1. Seu relay a posta no chat da equipe, e a entrega em Webhooks mostra succeeded.
  7. Envie com o honeypot preenchido, _gotcha=bot. Ele ainda recebe uma resposta de sucesso, mas o envio é armazenado como spam e não dispara e-mail nem webhook.
  8. Não chegou nada? Mude o filtro de status do painel para Spam. Spam recebe a mesma resposta de sucesso de um envio real.

Solução de problemas

ProblemaO que fazer
403 origin_not_allowed, ou todo envio cai no spamO domínio da página não está em Allowed domains do formulário. Adicione-o, mais localhost para testes locais. Subdomínios de um domínio listado são permitidos.
422 com Rating must be at most 5O formulário manda uma nota maior que o max do campo. Mude os valores do radio ou aumente o max na definição, até 10.
422 com um Unknown fieldO formulário manda um nome que não está na definição, geralmente um input oculto novo. Adicione um campo com esse id ou remova o input.
page está vazioO script que o preenche não rodou, ou rodou antes de o formulário existir. Coloque-o depois do formulário, ou defina page no momento do envio como fazem os exemplos de SPA.
meta.referrer só mostra seu domínioEsperado. Por padrão, os navegadores mandam só a origem em envios entre sites. Use o campo page no lugar.
O envio está no painel, mas nenhum e-mail ou webhook chegouEle foi armazenado como spam. Spam não envia nada. Abra-o no filtro Spam para ver os motivos e marque-o como não spam para enviar o e-mail e os webhooks dele.
429 rate_limitedUm visitante enviou mais do que o limite de taxa do formulário permite. O Standard permite 5 por minuto por visitante. Espere o Retry-After, ou escolha Relaxed ou Custom para formulários que enviam a partir de um único IP compartilhado.
402 test_limit_reachedO workspace não tem plano e já usou os 50 testes gratuitos de localhost deste mês. Escolha um plano ou use Send test no painel.

Perguntas

Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.