뉴스레터 가입 폼4분 분량
직접 만든 뉴스레터 폼의 더블 옵트인
Ikiform은 확인 이메일을 보내지 않으므로 더블 옵트인은 이메일 도구에서 실행됩니다. 릴레이가 각 가입을 미확인으로 추가하고 도구가 링크를 보냅니다.
Ikiform은 가입한 사람에게 절대 이메일을 보내지 않으므로, 확인 이메일은 뉴스레터를 보내는 도구에서 나가야 합니다. 릴레이가 Ikiform의 서명된 웹훅을 받아 그 도구에 독자를 미확인으로 추가하면, 도구가 링크를 이메일로 보내고, 클릭해야만 구독자가 됩니다. 도구마다 켜는 방식이 다르며, 릴레이는 이미 구독 중인 사람에게 두 번째 확인을 보내면 안 됩니다.
이 경우가 다른 점
Ikiform은 폼을 작성한 사람에게 이메일을 보내지 않습니다. 알림 이메일은 나와 팀에게만 가므로 자동 응답, 확인 이메일, 더블 옵트인이 없습니다. 그런 이메일은 웹훅으로 트리거해 이메일 도구에서 보내세요. 서비스의 임베드를 쓰면 확인은 그 서비스 폼의 설정입니다. 내 폼을 쓰면 두 시스템이 관여하고, 확인은 목록을 관리하는 쪽에 속합니다. 할 일은 각 가입이 확인을 트리거하는 상태로 그 도구에 도달하게 하고, 그러면 안 될 때는 트리거하지 않게 하는 것입니다.
더블 옵트인은 이메일 도구 안의 상태 머신입니다. 독자는 미확인으로 시작하고, 호를 받을 수 없으며, 클릭해야만 구독자가 됩니다. Ikiform의 역할은 릴레이가 204로 응답하면 끝납니다.
- 독자가 동의 체크박스를 선택하고 폼을 제출하면 Ikiform으로 POST됩니다.
- Ikiform이 가입을 저장하고 릴레이로 서명된 웹훅을 보냅니다.
- 릴레이가 서명을 검증하고 독자를 이메일 도구에 미확인으로 추가합니다.
- 이메일 도구가 독자에게 확인 링크를 이메일로 보냅니다.
- 클릭하면 도구가 확인됨으로 표시하고 모든 호를 보냅니다.
- 클릭하지 않으면 미확인 상태로 남고 뉴스레터를 받지 않습니다.
도구별 설정
도구마다 미확인의 개념이 다르고, 새 API 구독자를 미확인으로 만드는 방법도 다릅니다. 잘못하면 구독자가 이메일 없이 이미 확인된 상태로 추가됩니다.
| 도구 | API 가입이 확인 이메일을 받는 방법 | 함정 |
|---|---|---|
| Kit | state: "inactive"로 구독자를 만든 뒤, 인센티브 이메일이 켜진 폼에 추가하세요. Kit의 대량 폼 문서에 따르면 이렇게 하면 인센티브 이메일이 발송됩니다. 단일 엔드포인트는 내 주소로 테스트하세요 | 구독자 생성의 기본값은 state: "active"이며, 그 엔드포인트로는 나중에 상태를 바꿀 수 없습니다 |
| MailerLite | 구독 설정에서 Double opt-in for API and integrations(API 및 연동용 더블 옵트인)를 켜세요. status: "unconfirmed"도 함께 보내세요. MailerLite는 기존 구독자에게 이메일을 보내기 전에 이 값이 필요합니다 | 이미 활성인 주소에 unconfirmed를 보내면 다시 확인을 요청합니다 |
| beehiiv | 구독 생성 시 double_opt_override: "on"을 보내거나, 퍼블리케이션 자체 설정을 쓰려면 "not_set"을 보내세요 | "off"는 이메일 없이 구독자를 바로 활성화합니다 |
의존하기 전에 각각 내 주소로 테스트하세요. 도구 설정은 바뀌고, 이메일 자체의 제목, 문구, 링크가 여는 페이지는 도구에서 설정합니다.
한 번만 확인을 요청하는 릴레이
단순한 릴레이는 웹훅이 도착할 때마다 확인을 요청합니다. 두 경우에 이는 잘못입니다. 1분에 세 번 제출한 독자는 이메일을 세 통 받고, 피해자의 주소를 가입시키는 봇은 시도할 때마다 그 사람의 받은편지함에 내 확인 이메일을 넣습니다. 이 Cloudflare Worker는 주소당 하루에 최대 한 번만 도구에 확인을 요청합니다.
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>" }]
}./tool의addUnconfirmed는 위 표의 도구 호출입니다. 본문은 Kit, MailerLite, beehiiv 페이지에서 복사하세요.- KV 키는 소문자로 바꾼 주소의 SHA-256이므로 저장소에 주소 자체는 남지 않습니다. 하루 뒤 만료됩니다.
- 키는 도구가 요청을 받아들인 뒤에만 기록됩니다. 도구가 실패하면 Ikiform이 재시도하고, 재시도는 막히지 않습니다.
- 반복에
200으로 응답하면 Ikiform에 전달이 성공했다고 알려 재시도하지 않게 하고, 본문이 전달 로그에 이유를 설명합니다. - Worker는 커스텀 도메인에서 실행됩니다. Ikiform은
workers.dev호스트 이름을 웹훅 URL로 거부합니다. 웹훅 문서에 모든 URL 규칙과 각 응답의 의미가 있고, 자체 서버에서 각 전달을 한 번만 저장하는 릴레이를 보여 줍니다.
폼이 안내해야 할 내용
"구독해 주셔서 감사합니다"를 본 독자가 뉴스레터 폴더에서 아무것도 찾지 못하면 실패했다고 생각합니다. 도착한 페이지에서 다음에 무슨 일이 일어나는지 알려 주세요.
- 성공 문구나 감사 페이지에 열어야 할 이메일이 있다고 적으세요. "거의 다 됐습니다. 보내 드린 이메일을 열어 주소를 확인해 주세요."
- 찾아야 할 발신자 이름을 알려 주고, 몇 분 안에 아무것도 오지 않으면 스팸함을 확인하라고 안내하세요.
- 이메일 도구에서 확인 링크가 여는 페이지를 내 "구독 완료" 페이지로 설정하면 여정이 내 사이트에서 끝납니다.
폼의 동의 체크박스와 확인 이메일은 하는 일이 다릅니다. 체크박스는 누군가 내 페이지에서 동의했다는 것을 기록합니다. 클릭은 그 주소가 동의한 사람의 것임을 증명합니다. 대부분의 목록은 둘 다 원합니다. 뉴스레터 폼 템플릿에 필수 체크박스가 있습니다.
주의할 점
- 기존 구독자. 이미 확인된 사람이 새 페이지에서 다시 가입합니다. 미확인으로 되돌리지 마세요. MailerLite 페이지에서 주소를 먼저 조회하는 릴레이를 보여 줍니다.
- 수신 거부한 사람. 가입이 항상 수신 거부를 되돌려도 된다는 허락은 아닙니다. beehiiv는
reactivate_existing: true를 보낼 때만 다시 활성화하고, MailerLite는resubscribe: true일 때만 재구독합니다. 폼이 그렇다고 명시할 때만 보내세요. - 링크 스캐너. 일부 회사 메일 필터는 확인을 위해 들어오는 메일의 링크를 엽니다. 도구가 단순히 페이지가 로드되면 확인한다면, 스캐너가 아무도 클릭하지 않은 주소를 확인할 수 있습니다. 도구의 확인 페이지가 버튼을 누르게 하는지 확인하세요.
- 전달률. 확인 이메일은 독자가 나에게서 받는 첫 이메일입니다. 도구에서 인증된 도메인으로 보내세요. 그러지 않으면 스팸함에 들어가 가입이 완료되지 않습니다.
- 미확인 인원이 쌓입니다. 아직 구독자가 아닙니다. 도구에서 리마인더를 보낼지 정하고, 그다음에는 그대로 두세요.
작동 확인하기
- 내 주소로 폼을 제출하세요. 페이지가 받은편지함을 확인하라고 알려 줍니다.
- Ikiform의 Webhooks에서 전달을 여세요. 릴레이의
204와 함께succeeded가 표시됩니다. - 이메일 도구에서 구독자를 여세요. 도구에 따라 unconfirmed, inactive, pending 상태입니다.
- 확인 이메일을 열고 클릭하세요. 구독자가 active나 confirmed가 됩니다.
- 하루 안에 같은 주소로 다시 제출하세요. 전달에 "Confirmation already requested today"와 함께
200이 표시되고 두 번째 이메일은 오지 않습니다. - 이미 확인된 주소로 가입하세요. 확인 상태가 유지되고 새 확인 이메일은 오지 않습니다.
질문
아니요. Ikiform은 폼을 제출한 사람에게 절대 이메일을 보내지 않습니다. 확인 이메일은 릴레이나 자동화 도구를 거친 Ikiform의 웹훅으로 트리거되어 이메일 도구가 보냅니다.
하는 일이 다릅니다. 체크박스는 그 사람이 내 페이지에서 동의했다는 것을 타임스탬프와 함께 기록합니다. 확인 클릭은 그 주소의 소유자임을 증명합니다. 대부분의 목록은 둘 다 유지합니다.
릴레이가 이미 확인된 상태로 만들었을 가능성이 큽니다. Kit의 구독자 생성 기본값은 active이고, MailerLite는 API 더블 옵트인 설정과 기존 구독자에 대한 unconfirmed 상태가 필요하며, beehiiv의 double_opt_override를 off로 하면 이메일을 건너뜁니다. 도구에서 구독자의 상태를 확인하세요.
네. Ikiform 웹훅을 자동화로 보내고 이메일 도구용 액션을 쓰세요. 액션의 옵션이 구독자를 미확인 상태로 만드는지 확인하세요. 필터 단계를 추가하지 않으면 하루 한 번 제한은 사라집니다.
막히는 단계가 있거나 내 상황에 맞는 가이드가 필요하다면 이메일을 보내세요: hello@ikiform.com.