ニュースレター登録フォーム

ニュースレター登録フォーム2 分で読めます

自作のニュースレターフォームの登録を beehiiv に送る

自作の登録フォームを beehiiv につなぎます。リレーがダブルオプトインをオンにし、設置場所を UTM ソースに、ページをリファラーにして各購読を作成します。

Preet SutharIkiform 創業者

自作のフォームを Ikiform に送信し、Webhook を beehiiv の購読作成エンドポイントを呼ぶリレーに向けます。beehiiv が確認メールを送るよう double_opt_override: "on" を送り、フォームの設置場所を utm_source に、ページを referring_site に渡し、登録が配信停止をひそかに取り消さないよう reactivate_existing は false のままにします。1 件の登録につき API の呼び出しは 1 回で、キーはリレーに置いたままです。

beehiiv で異なる点

beehiiv の API はパブリケーションを中心に構成されています。購読とは 1 つのパブリケーションに登録されたメールアドレスのことで、/v2/publications/{publicationId}/subscriptions への 1 回の POST で作成します。登録に関することはすべてその 1 回のリクエストで送ります。確認を求めるか、ウェルカムメールを送るか、読者がどこから来たか、カスタムフィールドです。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:FirstNamedouble_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 はリレーが追加します。
最初の 4 つは Ikiform のイベントから来ます。最後の 2 つは、リレーがすべての登録で決めている固定の選択です。

beehiiv を設定する

  1. beehiiv で Settings を開き、Workspace Settings の API で Create New API Key を選びます。beehiiv は二度と表示しないので、すぐにコピーしてください。
  2. 有料プランなら、キーをフォームの送信先となる 1 つのパブリケーションに限定します。パブリケーションに限定したキーはほかのパブリケーションでは 404 になるので、漏れたときの被害を抑えられます。
  3. パブリケーションの id を確認します。beehiiv の API がパスで使う、接頭辞付きの id です。API のパブリケーション一覧のエンドポイントが返します。
  4. 名を保存したいなら、First Name という名前のカスタムフィールドを作ります。beehiiv はまだ存在しないカスタムフィールドを破棄します。
  5. ダブルオプトインとウェルカムメールはパブリケーションの設定で用意します。リレーはリクエストごとにそれらをオンにし、内容は beehiiv にあります。
beehiiv の料金ページではすべてのプランに API アクセスが記載されており、安いプランほど API のレート制限が低くなっています。API でメールを送るための Send API は上位プランに限られますが、このリレーは購読を作成するだけなので不要です。

リレー

これは Netlify Function で、すでに Netlify にあるサイトに向いています。静的サイトの隣で、自分のドメイン上で、別のサービスなしに動きます。型のために @netlify/functions をインストールし、3 つの変数をサイトの環境設定に設定します。

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 のとき、リレーは beehiiv の RateLimit-Reset(Unix 時刻)を読み、Ikiform 向けの Retry-After の待ち時間に変換します。

関数の URL は https://your-site.com/hooks/beehiiv です。Ikiform の Webhooks に追加し、whsec_ のシークレットを IKIFORM_WEBHOOK_SECRET にコピーします。URL のルールは Webhook のドキュメントに、処理済みの配信を飛ばす方法は自前のサーバーにあります。

UTM の値を決める

beehiiv の UTM のフィールドは自由記述なので、値は一度決めたら一貫させてください。そうしないと、footer と Footer のようなほぼ重複した記録に分かれてしまいます。フォームの非表示の 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 秒の枠で測り、上限はプランによって異なります。1 件の登録が 1 リクエストです。

beehiiv のプラン1 分あたりのリクエスト数
Free30
Lite180
Pro500
Enterprise800、申請すればそれ以上

1 分あたり 30 件あれば、たいていのフッターのフォームには十分ですが、無料のパブリケーションでのローンチ記事なら超えることもあります。リレーの 503 で、Ikiform は登録を捨てずに待ってからリトライします。プラン名と上限は変わるので、自分のプランが載っていなければ beehiiv のレート制限のページを確認してください。

ハマりどころ

  • カスタムフィールドの名前は完全一致。 beehiiv はカスタムフィールドを名前で照合し、未知のものはエラーではなくレスポンスの警告付きで捨てます。打ち間違いがあると、名が知らないうちに欠けていきます。
  • referring_site は空のことがある。 ブラウザーがリファラーを送らなかった場合、meta.referrer は null になり、リレーはそのフィールドを省きます。
  • 既存の購読者。 beehiiv のドキュメントには、この呼び出しで購読が作成または更新されるとありますが、アクティブな購読者で何が変わるかは書かれていません。すべてのページにフォームを置く前に、自分の確認済みのアドレスでテストしてください。
  • キーはデフォルトでワークスペース全体が対象。 パブリケーションを限定していないキーは、ワークスペースのすべてのパブリケーションにアクセスできます。範囲を絞ってください。
  • 有料ティアは beehiiv の中で。 tier を省けば、登録者は有料購読なしで加わります。アップグレードは beehiiv 自身の決済で行われます。

動作を確認する

  1. Ikiform でエンドポイントの Send test を選びます。配信には 204 が表示され、beehiiv にはリクエストが届きません。
  2. 自分のアドレスでページから購読します。配信には 204 が表示されます。
  3. beehiiv では、購読者が pending として、設置場所を UTM ソース、記事をリファラーとして表示されます。
  4. ダブルオプトインのメールが届きます。確認すると、ウェルカムメールが続いて届きます。
  5. beehiiv でそのアドレスを配信停止にし、もう一度登録します。reactivate_existing が false なので、購読者は非アクティブのままです。

よくある質問

手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com