Formulário de inscrição em newsletter6 min de leitura
Envie as inscrições do seu próprio formulário de newsletter para o MailerLite
Conecte seu próprio formulário de inscrição ao MailerLite: um relay adiciona novos leitores como não confirmados para o double opt-in e nunca pede a um assinante que confirme duas vezes.
Envie seu próprio formulário ao Ikiform e aponte o webhook para um relay que chama a API do MailerLite. O relay procura o endereço primeiro: um leitor novo é criado como unconfirmed, o que faz o MailerLite enviar o e-mail de double opt-in quando a opção da API está ligada, e um assinante existente só ganha o novo grupo. É essa consulta que impede que um assinante confirmado seja convidado a confirmar de novo.
O que muda com o MailerLite
O endpoint de criar assinante do MailerLite é um upsert: um POST em /api/subscribers cria um novo assinante ou atualiza um existente, respondendo 201 ou 200. Ele não é destrutivo, então grupos e campos que você omite continuam como estavam. O porém é o status. Com a opção de conta Double opt-in for API and integrations ligada, o MailerLite envia uma confirmação por e-mail aos novos assinantes via API. Um assinante existente, ativo ou descadastrado, só recebe uma quando a chamada envia status: "unconfirmed".
A ajuda do MailerLite diz que assinantes existentes, ativos ou descadastrados, não recebem o e-mail de confirmação a menos que a chamada inclua "status": "unconfirmed". Então um relay que sempre envia unconfirmed transforma cada nova inscrição de um leitor fiel num novo pedido de confirmação. A solução é procurar o endereço antes de decidir o que enviar:
- O relay verifica o webhook do Ikiform.
- Ele pede ao MailerLite o assinante pelo e-mail.
- Não encontrado: ele o cria com status unconfirmed e o grupo da posição, e o MailerLite envia o e-mail de confirmação.
- Encontrado e ativo ou não confirmado: ele adiciona o grupo sem status, então nada muda na confirmação.
- Encontrado e descadastrado: ele não faz nada, para que uma inscrição nunca desfaça um descadastro sem ninguém perceber.
Configure o MailerLite
- No MailerLite, abra as configurações de inscrição e ligue Double opt-in for API and integrations. Edite ali o e-mail de confirmação; o MailerLite envia o mesmo para todo assinante adicionado pela API.
- Crie um grupo por posição, como "Website footer" e "Blog posts", e anote o id de cada grupo.
- Em Integrations, crie um token de API e guarde-o para o ambiente do relay.
O relay
Este é um servidor Express. Ele lê o corpo bruto como texto, porque a assinatura cobre exatamente os bytes que o Ikiform enviou, e interpretar o JSON antes os alteraria.
import express from "express";
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";
const API = "https://connect.mailerlite.com/api";
const GROUPS: Record<string, string> = {
footer: process.env.MAILERLITE_GROUP_FOOTER!,
post: process.env.MAILERLITE_GROUP_POST!,
};
function mailerlite(path: string, init: RequestInit = {}) {
return fetch(`${API}${path}`, {
...init,
headers: {
Authorization: `Bearer ${process.env.MAILERLITE_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json",
},
});
}
async function subscribe(email: string, name: string | undefined, source: string) {
const found = await mailerlite(`/subscribers/${encodeURIComponent(email)}`);
if (found.status !== 200 && found.status !== 404) return found;
const groups = [GROUPS[source] ?? process.env.MAILERLITE_GROUP_FOOTER!];
const fields = name ? { name } : {};
if (found.status === 404) {
return mailerlite("/subscribers", {
method: "POST",
body: JSON.stringify({ email, fields, groups, status: "unconfirmed" }),
});
}
const existing = await found.json();
if (existing.data.status === "unsubscribed") return new Response(null, { status: 208 });
return mailerlite("/subscribers", { method: "POST", body: JSON.stringify({ email, fields, groups }) });
}
const app = express();
app.post("/hooks/mailerlite", express.text({ type: "application/json", limit: "512kb" }), async (req, res) => {
let event;
try {
event = await verifyWebhook({ payload: req.body, headers: req.headers, secret: process.env.IKIFORM_WEBHOOK_SECRET! });
} catch (error) {
if (error instanceof WebhookVerificationError) return res.status(400).send(error.reason);
return res.status(500).end();
}
if (event.type !== "submission.created") return res.status(204).end();
const { email, first_name, consent, source } = event.data.fields;
if (consent !== true || typeof email !== "string") return res.status(200).send("Skipped");
const answer = await subscribe(
email,
typeof first_name === "string" ? first_name : undefined,
typeof source === "string" ? source : "footer",
);
if (answer.status === 208) return res.status(200).send("Unsubscribed earlier, left alone");
if (answer.status === 429) {
return res.status(503).set("retry-after", answer.headers.get("retry-after") ?? "60").send("MailerLite rate limit");
}
if (!answer.ok) return res.status(502).send(`MailerLite answered ${answer.status}: ${await answer.text()}`);
res.status(204).end();
});
app.listen(Number(process.env.PORT ?? 3000));- O MailerLite recebe o token como
Authorization: Bearer. A URL base éhttps://connect.mailerlite.com/api. GET /api/subscribers/{email}aceita um e-mail ou um id e responde404quando o assinante não existe.groupsrecebe ids de grupos que já existem. Um id errado é recusado com422, que o relay repassa como502com a mensagem do MailerLite.fields.nameé o campo padrão de primeiro nome do MailerLite. Campos personalizados precisam existir no MailerLite antes de você enviá-los.- O
208é um marcador interno para um leitor descadastrado. O Ikiform vê200e uma nota no log de entregas.
Faça o deploy em qualquer lugar que ofereça uma URL HTTPS pública na porta 443, adicione essa URL em Webhooks no Ikiform e coloque o segredo whsec_ em IKIFORM_WEBHOOK_SECRET. A documentação de webhooks cobre as novas tentativas e o payload, e seu próprio servidor tem a mesma configuração Express com um banco de dados.
Onde fica o registro de consentimento
A chamada de create do MailerLite aceita subscribed_at, ip_address, opted_in_at e optin_ip. Deixe os campos de IP de fora. O webhook do Ikiform nunca inclui o endereço IP do visitante nem o hash dele, então o relay não tem nada verdadeiro para enviar, e um valor inventado é pior que nenhum.
O registro da inscrição fica no Ikiform: o envio guarda consent: true com data e hora, origem, referrer e país. O registro da confirmação fica no MailerLite, que anota quando o leitor clicou no link. Com os dois, você consegue mostrar quando alguém marcou a caixa e quando provou que o endereço era seu. Exporte o lado do Ikiform como CSV em Submissions quando precisar.
Limites de taxa
O limite global da API do MailerLite é de 120 requisições por minuto. O relay faz duas por inscrição, então cabem cerca de 60 inscrições por minuto. Acima disso, o MailerLite responde 429, o relay responde 503 com Retry-After e o Ikiform tenta de novo mais tarde com a mesma entrega.
| O MailerLite responde | O relay responde | Ikiform |
|---|---|---|
201 ou 200 | 204 | Entrega bem-sucedida |
429 | 503 com Retry-After | Espera e tenta de novo |
401 | 502 | Tenta de novo. Corrija o token e use Retry now nas entregas com falha |
422 | 502 com os erros | Tenta de novo. Geralmente um id de grupo ou nome de campo errado |
Pegadinhas
- Não envie
status: "active". Ele marca a pessoa como inscrita, e a documentação do MailerLite não diz se uma confirmação ainda é enviada. Teste com o status que você envia. - Reinscrever é uma escolha. O MailerLite tem uma flag
resubscribepara quem se descadastrou. Só a envie quando o seu formulário disser isso, e quando o leitor souber que está voltando a se inscrever. - A chave importa. O MailerLite só envia e-mail de confirmação para inscrições via API quando Double opt-in for API and integrations está ligado.
- Um único e-mail de confirmação. O e-mail de double opt-in da API é compartilhado por todas as inscrições via API. Se você precisa de textos diferentes por posição, use formulários separados do MailerLite.
- Duplicados no Ikiform. O Ikiform guarda todo envio aceito, enquanto o MailerLite guarda um assinante por e-mail. Conte os assinantes no MailerLite, não no painel do Ikiform.
Confira se funciona
- Envie um teste pelo endpoint no Ikiform. A entrega mostra
204. - Inscreva-se com um endereço novo seu. O MailerLite mostra o assinante como não confirmado no grupo do rodapé, e o e-mail de confirmação chega.
- Confirme e depois inscreva-se de novo a partir de um post do blog. O assinante continua ativo, entra no segundo grupo e não recebe um novo e-mail de confirmação.
- Descadastre esse endereço no MailerLite e inscreva-se mais uma vez. O log de entregas mostra a nota de descadastrado, e o MailerLite continua mostrando o endereço como descadastrado.
Perguntas
Sim. Envie o formulário ao Ikiform e deixe um relay adicionar cada inscrição pela API do MailerLite com o grupo certo. O formulário fica no seu markup e o MailerLite continua enviando a newsletter.
Ou o Double opt-in for API and integrations está desligado nas configurações de inscrição do MailerLite, ou o relay criou o assinante como ativo. Mantenha a opção ligada, envie status unconfirmed e teste com um endereço seu.
Não com este relay. Ele procura o endereço primeiro e só envia unconfirmed para um assinante novo. Um assinante existente é adicionado ao novo grupo e nada mais muda.
Dê a cada posição um valor diferente no input oculto source do formulário e mapeie cada valor para um id de grupo do MailerLite no relay. Um assinante existente que se inscreve a partir de uma segunda posição entra nesse grupo também, e continua no primeiro.
Não. O Ikiform nunca envia e-mail para quem envia um formulário. O MailerLite envia a confirmação, cada newsletter e o link de descadastro.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.