뉴스레터 가입 폼

뉴스레터 가입 폼4분 분량

내 뉴스레터 폼의 가입을 beehiiv로 보내기

내 가입 폼을 beehiiv에 연결합니다. 릴레이가 더블 옵트인을 켜고, 위치를 UTM source로, 페이지를 referrer로 해서 각 구독을 만듭니다.

Preet SutharIkiform 창업자

내 폼을 Ikiform으로 POST하고, beehiiv의 구독 생성 엔드포인트를 호출하는 릴레이로 웹훅을 보내세요. beehiiv가 확인 이메일을 보내도록 double_opt_override: "on"을 보내고, 폼의 위치는 utm_source로, 페이지는 referring_site로 넘기고, 가입이 수신 거부를 조용히 되돌리지 않도록 reactivate_existing은 false로 두세요. 가입마다 API 호출 한 번이며, 키는 릴레이에 둡니다.

beehiiv에서 다른 점

beehiiv의 API는 퍼블리케이션을 중심으로 구성됩니다. 구독은 한 퍼블리케이션을 구독한 이메일 주소이며, /v2/publications/{publicationId}/subscriptions로 POST 한 번이면 만들어집니다. 가입에 관한 모든 것이 그 요청 하나에 담깁니다. 확인할지, 환영 이메일을 보낼지, 독자가 어디서 왔는지, 커스텀 필드입니다. Kit처럼 별도의 태그나 폼 단계가 없습니다.

beehiiv는 유입도 UTM 용어로 보고합니다. 구독 레코드에는 utm_source, utm_medium, utm_campaign, referring_site가 있습니다. 폼의 필드를 여기에 매핑하면 beehiiv의 각 구독자에게 어느 위치와 어느 글에서 왔는지 표시됩니다.

릴레이가 Ikiform 제출을 beehiiv 구독으로 매핑하는 방식Ikiform 이벤트beehiiv 구독fields.email이메일fields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields: First Namedouble_opt_override: "on"reactivate_existing: false릴레이가 Ikiform 제출을 beehiiv 구독으로 매핑하는 방식Ikiform 이벤트beehiiv 구독fields.email이메일fields.sourceutm_sourcemeta.referrerreferring_sitefields.first_namecustom_fields:First Namedouble_opt_override:"on"reactivate_existing:false
  1. fields.email은 email이 됩니다.
  2. fields.source는 utm_source가 됩니다.
  3. meta.referrer는 referring_site가 됩니다.
  4. fields.first_name은 custom_fields: First Name이 됩니다.
  5. double_opt_override: "on"은 릴레이가 추가합니다.
  6. reactivate_existing: false는 릴레이가 추가합니다.
처음 네 개는 Ikiform 이벤트에서 옵니다. 마지막 두 개는 릴레이가 모든 가입에 대해 정하는 고정 값입니다.

beehiiv 설정하기

  1. beehiiv에서 Settings를 열고, Workspace Settings 아래의 API에서 Create New API Key를 고르세요. 바로 복사하세요. beehiiv는 다시 보여 주지 않습니다.
  2. 유료 플랜이라면 키를 폼이 연결되는 퍼블리케이션 하나로 제한하세요. 퍼블리케이션 범위의 키는 다른 퍼블리케이션에 대해 404를 받으므로, 유출되었을 때 피해가 제한됩니다.
  3. 퍼블리케이션 ID를 찾으세요. beehiiv API가 경로에 쓰는 접두사가 붙은 ID입니다. API의 퍼블리케이션 목록 엔드포인트가 반환합니다.
  4. 이름을 저장하고 싶다면 First Name이라는 커스텀 필드를 만드세요. beehiiv는 아직 존재하지 않는 커스텀 필드를 버립니다.
  5. 퍼블리케이션 설정에서 더블 옵트인 이메일과 환영 이메일을 설정하세요. 릴레이는 요청마다 이를 켜고, 내용은 beehiiv에 있습니다.
beehiiv 요금 페이지에는 모든 플랜에 API 접근이 있고, 저렴한 플랜일수록 API 레이트 리밋이 낮다고 나와 있습니다. API로 이메일을 보내는 Send API는 상위 플랜으로 제한되지만, 이 릴레이는 구독만 만들므로 필요 없습니다.

릴레이

이것은 Netlify Function이며, 이미 Netlify에 있는 사이트에 잘 맞습니다. 별도 서비스 없이 정적 사이트 옆, 내 도메인에서 실행됩니다. 타입을 위해 @netlify/functions를 설치하고, 사이트의 환경 설정에 변수 세 개를 설정하세요.

netlify/functions/beehiiv.mts
import type { Config } from "@netlify/functions";
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";

export default async (request: Request) => {
  const payload = await request.text();
  let event;
  try {
    event = await verifyWebhook({
      payload,
      headers: request.headers,
      secret: Netlify.env.get("IKIFORM_WEBHOOK_SECRET")!,
    });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
    throw error;
  }
  if (event.type !== "submission.created") return new Response(null, { status: 204 });

  const { email, first_name, consent, source } = event.data.fields;
  if (consent !== true || typeof email !== "string") return new Response("Skipped", { status: 200 });

  const publication = Netlify.env.get("BEEHIIV_PUBLICATION_ID");
  const answer = await fetch(`https://api.beehiiv.com/v2/publications/${publication}/subscriptions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${Netlify.env.get("BEEHIIV_API_KEY")}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      email,
      double_opt_override: "on",
      send_welcome_email: true,
      reactivate_existing: false,
      utm_source: typeof source === "string" ? source : "website",
      utm_medium: "signup_form",
      referring_site: event.data.meta.referrer ?? undefined,
      custom_fields: typeof first_name === "string" && first_name ? [{ name: "First Name", value: first_name }] : [],
    }),
  });

  if (answer.status === 429) {
    const reset = Number(answer.headers.get("ratelimit-reset"));
    const wait = reset ? Math.max(1, reset - Math.floor(Date.now() / 1000)) : 60;
    return new Response("beehiiv rate limit", { status: 503, headers: { "retry-after": String(wait) } });
  }
  if (!answer.ok) return new Response(`beehiiv answered ${answer.status}: ${await answer.text()}`, { status: 502 });
  return new Response(null, { status: 204 });
};

export const config: Config = {
  path: "/hooks/beehiiv",
};
  • double_opt_override: "on"은 퍼블리케이션 기본값과 관계없이 확인 이메일을 보냅니다. 퍼블리케이션 설정을 따르려면 "not_set"을 쓰고, 공개 폼에는 절대 "off"를 쓰지 마세요.
  • API에서 send_welcome_email의 기본값은 false입니다. 임베드 가입자가 받는 환영 이메일을 API 가입자도 받게 하려면 true로 설정하세요.
  • reactivate_existing: false도 기본값입니다. 나중에 누가 생각 없이 바꾸지 않도록 명시하세요. 수신 거부한 사람을 다시 활성화합니다.
  • beehiiv는 구독과 함께 200으로 응답하며, status는 beehiiv가 주소를 확인하는 동안 validating으로 시작해 독자가 확인할 때까지 pending입니다.
  • 429가 오면 릴레이가 Unix 시간인 beehiiv의 RateLimit-Reset을 읽어 Ikiform용 Retry-After 지연으로 바꿉니다.

함수의 URL은 https://your-site.com/hooks/beehiiv입니다. Ikiform의 Webhooks에 추가하고 whsec_ 시크릿을 IKIFORM_WEBHOOK_SECRET에 복사하세요. URL 규칙은 웹훅 문서에 있고, 자체 서버에서 이미 처리한 전달을 건너뛰는 방법을 보여 줍니다.

UTM 값 정하기

beehiiv의 UTM 필드는 자유 텍스트이므로 값을 한 번 정하고 일관되게 유지하세요. 그러지 않으면 footer와 Footer처럼 거의 같은 기록으로 갈라집니다. 폼의 hidden source 입력이 자연스러운 utm_source입니다. utm_medium은 고정해 두면 내 폼에서 온 가입을 beehiiv 호스팅 페이지나 가져오기와 구분할 수 있습니다.

위치source 입력utm_sourceutm_medium
사이트 푸터footerfootersignup_form
글의 끝postpostsignup_form
뉴스레터 페이지newsletter-pagenewsletter-pagesignup_form

폼이 있는 페이지로 링크하는 캠페인을 운영한다면, 릴레이에서 페이지 URL로부터 캠페인을 읽으세요. meta.referrer에는 브라우저가 보낸 경우 쿼리 문자열까지 포함한 페이지의 전체 URL이 담기므로, 릴레이가 그 안의 utm_campaign 파라미터를 요청에 복사할 수 있습니다.

플랜별 레이트 리밋

beehiiv는 API 키별로 고정된 60초 구간에서 한도를 측정하며, 한도는 플랜에 따라 다릅니다. 가입마다 요청 하나입니다.

beehiiv 플랜분당 요청 수
Free30
Lite180
Pro500
Enterprise800, 요청 시 상향 가능

분당 30건이면 대부분의 푸터 폼에 충분하지만, 무료 퍼블리케이션의 출시 글이 이를 넘을 수 있습니다. 릴레이의 503 덕분에 Ikiform은 가입을 버리지 않고 기다렸다가 재시도합니다. 플랜 이름과 한도는 바뀌므로, 내 플랜이 목록에 없다면 beehiiv의 레이트 리밋 페이지를 확인하세요.

주의할 점

  • 커스텀 필드 이름은 정확해야 합니다. beehiiv는 이름으로 커스텀 필드를 맞추고, 모르는 필드는 오류가 아니라 응답의 경고와 함께 버립니다. 오타가 있으면 이름이 조용히 사라집니다.
  • referring_site는 비어 있을 수 있습니다. 브라우저가 referrer를 보내지 않으면 meta.referrer는 null이고, 릴레이는 그 필드를 뺍니다.
  • 기존 구독자. beehiiv 문서에 따르면 이 호출은 구독을 만들거나 업데이트하지만, 활성 구독자에게 무엇이 바뀌는지는 나와 있지 않습니다. 폼을 모든 페이지에 두기 전에 확인된 내 주소로 테스트하세요.
  • 키는 기본적으로 워크스페이스 전체에 적용됩니다. 퍼블리케이션 제한이 없는 키는 워크스페이스의 모든 퍼블리케이션에 접근할 수 있습니다. 범위를 제한하세요.
  • 유료 등급은 beehiiv에 남습니다. 가입이 유료 구독 없이 이루어지도록 tier는 빼세요. 업그레이드는 beehiiv 자체 결제에서 이루어집니다.

작동 확인하기

  1. Ikiform의 엔드포인트에서 Send test를 누르세요. 전달에 204가 표시되고 beehiiv에는 요청이 가지 않습니다.
  2. 내 주소로 페이지에서 구독하세요. 전달에 204가 표시됩니다.
  3. beehiiv에서 구독자가 pending으로 나타나며, 위치는 UTM source로, 글은 referring site로 표시됩니다.
  4. 더블 옵트인 이메일이 도착합니다. 확인하면 환영 이메일이 이어집니다.
  5. beehiiv에서 그 주소를 수신 거부하고 다시 가입하세요. reactivate_existing이 false이므로 구독자는 비활성 상태로 남습니다.

질문

막히는 단계가 있거나 내 상황에 맞는 가이드가 필요하다면 이메일을 보내세요: hello@ikiform.com.