Formulário de inscrição em newsletter7 min de leitura
Double opt-in para um formulário de newsletter feito por você
O Ikiform não envia e-mails de confirmação, então o double opt-in roda na sua ferramenta de e-mail: um relay adiciona cada inscrição como não confirmada e a ferramenta envia o link.
O Ikiform nunca envia e-mail para quem se inscreve, então o e-mail de confirmação precisa sair da ferramenta que envia a sua newsletter. Um relay recebe o webhook assinado do Ikiform e adiciona o leitor a essa ferramenta como não confirmado, a ferramenta envia um link por e-mail, e só um clique o torna assinante. Cada ferramenta liga isso de um jeito, e o relay nunca deve enviar uma segunda confirmação para quem já é assinante.
O que muda aqui
O Ikiform não envia e-mail para quem preenche o formulário. Os e-mails de notificação vão só para você e sua equipe, então não há resposta automática, e-mail de confirmação nem double opt-in. Envie esses e-mails pela sua ferramenta de e-mail, disparados por um webhook. Com o embed de um provedor, a confirmação é uma opção do formulário do provedor. Com o seu próprio formulário, há dois sistemas envolvidos, e a confirmação pertence ao que guarda a lista. O trabalho é garantir que cada inscrição chegue a essa ferramenta num estado que dispare a confirmação, e que não dispare quando não deve.
O double opt-in é uma máquina de estados dentro da ferramenta de e-mail. O leitor começa não confirmado, não pode receber edições e só vira assinante quando clica. A parte do Ikiform termina quando o relay responde 204.
- O leitor marca a caixa de consentimento e envia seu formulário, que envia ao Ikiform.
- O Ikiform armazena a inscrição e envia um webhook assinado ao seu relay.
- O relay verifica a assinatura e adiciona o leitor à ferramenta de e-mail como não confirmado.
- A ferramenta de e-mail envia ao leitor um link de confirmação.
- Se ele clicar, a ferramenta o marca como confirmado e envia todas as edições.
- Se ele nunca clicar, continua não confirmado e não recebe a newsletter.
A chave em cada ferramenta
Cada ferramenta tem sua própria ideia de não confirmado, e seu próprio jeito de transformar um novo assinante via API em um. Se errar isso, os assinantes são adicionados como já confirmados, sem e-mail nenhum:
| Ferramenta | Como uma inscrição via API recebe um e-mail de confirmação | A armadilha |
|---|---|---|
| Kit | Crie o assinante com state: "inactive" e depois adicione-o a um formulário com o incentive email ligado. A documentação do bulk form do Kit diz que isso envia o incentive email; teste o endpoint individual com um endereço seu | Create subscriber usa state: "active" por padrão, e o estado não pode ser alterado depois por esse endpoint |
| MailerLite | Ligue Double opt-in for API and integrations nas configurações de inscrição. Envie também status: "unconfirmed", que o MailerLite exige antes de enviar e-mail a um assinante existente | Enviar unconfirmed para um endereço que já está ativo pede que ele confirme de novo |
| beehiiv | Envie double_opt_override: "on" no create subscription, ou "not_set" para usar a configuração da própria publicação | "off" deixa o assinante ativo na hora, sem e-mail |
Teste cada uma com um endereço seu antes de confiar nela. As configurações das ferramentas mudam, e o e-mail em si é configurado na ferramenta: o assunto, o texto e a página que o link abre.
Um relay que confirma uma vez
Um relay simples pede uma confirmação toda vez que chega um webhook. Dois casos tornam isso errado: um leitor que envia três vezes em um minuto recebe três e-mails, e um bot que inscreve o endereço de uma vítima coloca sua confirmação na caixa de entrada dela a cada tentativa. Este Cloudflare Worker pede à ferramenta no máximo uma confirmação por endereço por dia:
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
import { addUnconfirmed } from "./tool";
export interface Env {
IKIFORM_WEBHOOK_SECRET: string;
TOOL_API_KEY: string;
SEEN: KVNamespace;
}
const DAY = 86_400;
async function digest(text: string) {
const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
return [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}
export default {
async fetch(request: Request, env: Env) {
if (request.method !== "POST") return new Response(null, { status: 405 });
const payload = await request.text();
let event;
try {
event = await verifyWebhook({ payload, headers: request.headers, secret: env.IKIFORM_WEBHOOK_SECRET });
} catch (error) {
if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
throw error;
}
if (event.type !== "submission.created" || event.data.fields.consent !== true) {
return new Response(null, { status: 204 });
}
const email = String(event.data.fields.email).trim().toLowerCase();
const key = `confirm:${await digest(email)}`;
if (await env.SEEN.get(key)) return new Response("Confirmation already requested today", { status: 200 });
const answer = await addUnconfirmed(env, email, event.data.fields.first_name);
if (answer.status === 429) {
return new Response("Rate limited", { status: 503, headers: { "retry-after": answer.headers.get("retry-after") ?? "60" } });
}
if (!answer.ok) return new Response(`Email tool answered ${answer.status}`, { status: 502 });
await env.SEEN.put(key, event.id, { expirationTtl: DAY });
return new Response(null, { status: 204 });
},
};{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "newsletter-relay",
"main": "src/index.ts",
"compatibility_date": "2026-10-01",
"routes": [{ "pattern": "hooks.example.com", "custom_domain": true }],
"kv_namespaces": [{ "binding": "SEEN", "id": "<your KV namespace id>" }]
}addUnconfirmedem./toolé a chamada da ferramenta da tabela acima. Copie o corpo dela da página do Kit, MailerLite ou beehiiv.- A chave do KV é um SHA-256 do endereço em minúsculas, então o armazenamento nunca guarda o endereço em si. Ela expira depois de um dia.
- A chave só é gravada depois que a ferramenta aceita a requisição. Se a ferramenta falhar, o Ikiform tenta de novo e a nova tentativa não é bloqueada.
- Responder
200a uma repetição diz ao Ikiform que a entrega deu certo, então ela não é refeita, e o corpo explica o motivo no log de entregas. - O Worker roda num domínio personalizado. O Ikiform recusa hostnames
workers.devcomo URLs de webhook. A documentação de webhooks lista cada regra de URL e o que cada resposta significa, e seu próprio servidor mostra um relay que armazena cada entrega uma única vez.
O que o formulário deve dizer
Um leitor que vê "Obrigado por se inscrever" e depois não encontra nada na pasta de newsletters acha que falhou. Diga o que acontece em seguida, na página em que ele cai:
- Configure a frase de sucesso, ou sua página de agradecimento, para dizer que há um e-mail para abrir: "Quase lá. Abra o e-mail que enviamos e confirme seu endereço."
- Diga o nome do remetente que ele deve procurar e sugira a pasta de spam se nada chegar em alguns minutos.
- Na ferramenta de e-mail, defina a página que o link de confirmação abre como a sua própria página "Inscrição confirmada", para a jornada terminar no seu site.
A caixa de consentimento do formulário e o e-mail de confirmação fazem trabalhos diferentes. A caixa registra que alguém disse sim na sua página. O clique prova que o endereço pertence a quem disse sim. A maioria das listas quer os dois. O modelo de formulário de newsletter tem a caixa obrigatória.
Pegadinhas
- Assinantes existentes. Alguém já confirmado se inscreve de novo a partir de uma nova página. Não o volte para não confirmado; a página do MailerLite mostra um relay que procura o endereço primeiro.
- Pessoas que se descadastraram. Uma inscrição nem sempre é permissão para desfazer um descadastro. O beehiiv só reativa quando você envia
reactivate_existing: true, e o MailerLite só reinscreve comresubscribe: true. Envie esses valores só quando o formulário disser isso. - Scanners de links. Alguns filtros de e-mail corporativos abrem os links das mensagens recebidas para verificá-los. Se uma ferramenta confirma só com o carregamento de uma página, um scanner pode confirmar um endereço em que ninguém clicou. Confira se a página de confirmação da sua ferramenta pede o clique num botão.
- Entregabilidade. A confirmação é o primeiro e-mail que um leitor recebe de você. Envie-a de um domínio autenticado na sua ferramenta, ou ela cai no spam e a inscrição nunca se completa.
- Não confirmados se acumulam. Eles ainda não são assinantes. Decida na sua ferramenta se vai enviar um lembrete, e depois deixe-os em paz.
Confira se funciona
- Envie o formulário com um endereço seu. A página pede para você conferir a caixa de entrada.
- Abra a entrega em Webhooks no Ikiform. Ela mostra
succeededcom o204do relay. - Abra o assinante na sua ferramenta de e-mail. Ele está não confirmado, inativo ou pendente, dependendo da ferramenta.
- Abra o e-mail de confirmação e clique. O assinante fica ativo ou confirmado.
- Envie o mesmo endereço de novo no mesmo dia. A entrega mostra
200com "Confirmation already requested today", e nenhum segundo e-mail chega. - Inscreva um endereço que já está confirmado. Ele continua confirmado e não recebe um novo e-mail de confirmação.
Perguntas
Não. O Ikiform nunca envia e-mail para quem envia um formulário. Sua ferramenta de e-mail envia a confirmação, disparada pelo webhook do Ikiform por meio de um relay ou de uma ferramenta de automação.
Elas fazem trabalhos diferentes. A caixa registra que a pessoa concordou na sua página, com data e hora. O clique de confirmação prova que ela é dona do endereço. A maioria das listas mantém os dois.
O mais provável é que o relay o tenha criado como já confirmado: o create subscriber do Kit usa ativo por padrão, o MailerLite precisa da opção de double opt-in por API ligada, mais um status não confirmado para assinantes existentes, e o double_opt_override do beehiiv definido como off pula o e-mail. Confira o estado do assinante na ferramenta.
Sim. Aponte o webhook do Ikiform para a automação e use a ação dela para a sua ferramenta de e-mail. Confira se as opções da ação criam o assinante num estado não confirmado; você perde a proteção de uma vez por dia, a menos que adicione uma etapa de filtro.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.