2026年8月10日
2026年8月10日
WordPressからMailchimpのAPIへ直接登録してメルマガ購読を自動化する方法
WordPress の独自フォームから Mailchimp のオーディエンス(購読者リスト)へ登録するには、Mailchimp Marketing API の「メンバーの追加または更新」を、WordPress のサーバー側から呼ぶのが基本です。この記事では、APIキーとオーディエンスIDの準備、nonce・スパム対策・連続送信の制限を入れたフォーム処理、ダブルオプトインの扱い、よくあるエラーの読み方までを、そのまま応用できる形で説明します。
直接連携が向く場面と、プラグインで足りる場面
単に「サイトに登録フォームを置きたい」だけなら、Mailchimp for WordPress(MC4WP)のような定評のあるプラグインで十分です。フォームの作成、ダブルオプトイン、主要なフォームプラグインとの連携まで画面上で設定できます。
直接 API を呼ぶ実装が向いているのは、たとえば次のような場合です。
- 会員登録や購入など、既存の処理の流れの中で購読登録も行いたい
- 登録時にタグや独自項目(マージフィールド)を細かく付け分けたい
- 余計なスクリプトやスタイルを読み込まずに、テーマのデザインに合わせた最小限のフォームにしたい
この記事のコードは、子テーマの functions.php か wp-content/mu-plugins/ 内のファイルに置く前提です。まずステージング環境と、テスト用のオーディエンスで試してください。
準備:APIキー・データセンター・オーディエンスID
Mailchimp の管理画面のアカウント設定から API キーを発行します。API キーの末尾には -us21 のようなデータセンターの識別子が付いており、API の接続先ホストはこの識別子で決まります(https://us21.api.mailchimp.com/3.0/)。オーディエンスIDは、オーディエンスの設定画面で確認できます。画面のメニュー構成や名称は変更されることがあるため、見つからない場合は Mailchimp のヘルプで「API key」「audience ID」を検索してください(2026年10月現在)。無料プランで使える機能や制限も変わることがあるので、契約中のプランで必要な機能が使えるかもあわせて確認します。
API キーはアカウント全体を操作できる強い権限を持ちます。テーマのファイルやデータベースのオプションに平文で置かず、wp-config.php の定数か、Web からアクセスできない場所の環境変数に置きます。
<?php
// wp-config.php(値はダミー)
define( 'MYSITE_MAILCHIMP_API_KEY', 'your-api-key-us21' );
define( 'MYSITE_MAILCHIMP_LIST_ID', 'your-list-id' );
Mailchimpに登録する関数を作る
Marketing API では、メンバーを「メールアドレスを小文字にしたものの MD5 ハッシュ」で識別します。このハッシュを使って PUT /lists/{list_id}/members/{subscriber_hash} を呼ぶと、未登録なら追加、登録済みなら更新という動きになり、同じ人が二度送信してもエラーになりません。
<?php
/**
* Mailchimp のオーディエンスに追加(既存なら更新)する。
* 新規の人はダブルオプトインの確認待ち(pending)として登録する。
*/
function mysite_mailchimp_upsert( $email, $first_name = '', $tags = array() ) {
$api_key = MYSITE_MAILCHIMP_API_KEY;
$dc = substr( strrchr( $api_key, '-' ), 1 ); // 末尾のデータセンター識別子
$hash = md5( strtolower( $email ) );
$base = sprintf( 'https://%s.api.mailchimp.com/3.0/lists/%s/members/%s', $dc, MYSITE_MAILCHIMP_LIST_ID, $hash );
$headers = array(
'Authorization' => 'Basic ' . base64_encode( 'wp:' . $api_key ),
'Content-Type' => 'application/json',
);
$response = wp_remote_request( $base, array(
'method' => 'PUT',
'timeout' => 15,
'headers' => $headers,
'body' => wp_json_encode( array(
'email_address' => $email,
'status_if_new' => 'pending', // 新規はダブルオプトイン。既存の人の状態は変えない
'merge_fields' => array( 'FNAME' => $first_name ),
) ),
) );
$code = wp_remote_retrieve_response_code( $response );
if ( is_wp_error( $response ) || 200 !== $code ) {
$body = json_decode( wp_remote_retrieve_body( $response ), true );
return new WP_Error( 'mailchimp_error', isset( $body['title'] ) ? $body['title'] : 'request failed', array( 'status' => $code ) );
}
if ( $tags ) {
wp_remote_post( $base . '/tags', array(
'timeout' => 15,
'headers' => $headers,
'body' => wp_json_encode( array(
'tags' => array_map( function ( $t ) {
return array( 'name' => $t, 'status' => 'active' );
}, $tags ),
) ),
) );
}
return true;
}
ここで status ではなく status_if_new を使っているのが大事な点です。status_if_new は新規の人にだけ適用されるため、過去に配信停止した人がフォームから再送信しても、勝手に購読状態に戻すことはありません。配信停止の意思を尊重する意味でも、法令やガイドラインに沿う意味でも、この形が安全です。
pending で登録すると、Mailchimp から確認メールが送られ、本人がリンクを押した時点で購読が有効になります。第三者が他人のアドレスを勝手に登録するいたずらを防げるため、Web フォームからの登録ではダブルオプトインを基本にしてください。
認証ヘッダーのユーザー名部分(例では wp)は任意の文字列で構いません。Mailchimp は Basic 認証のパスワード部分に入った API キーで認証します。
フォームを受け取る処理:nonce・スパム対策・連続送信の制限
フォームの送信先には admin-post.php を使います。ログインしていない訪問者からの送信は admin_post_nopriv_{action}、ログイン中のユーザーからは admin_post_{action} のフックで受け取れます。
<?php
// フォーム(テンプレートやショートコードから出力)
function mysite_newsletter_form() {
ob_start(); ?>
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
<input type="hidden" name="action" value="mysite_subscribe">
<?php wp_nonce_field( 'mysite_subscribe', 'mysite_subscribe_nonce' ); ?>
<label>お名前 <input type="text" name="fname" maxlength="50"></label>
<label>メールアドレス <input type="email" name="email" required></label>
<p style="display:none"><label>空欄のまま <input type="text" name="website" tabindex="-1" autocomplete="off"></label></p>
<label><input type="checkbox" name="consent" value="1" required> プライバシーポリシーに同意してメールマガジンを受け取る</label>
<button type="submit">登録する</button>
</form>
<?php
return ob_get_clean();
}
add_shortcode( 'mysite_newsletter', 'mysite_newsletter_form' );
// 送信の受け取り
function mysite_handle_subscribe() {
$back = wp_get_referer() ? wp_get_referer() : home_url( '/' );
if ( ! isset( $_POST['mysite_subscribe_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['mysite_subscribe_nonce'] ) ), 'mysite_subscribe' ) ) {
wp_safe_redirect( add_query_arg( 'nl', 'error', $back ) );
exit;
}
// ボット対策:隠し項目に値が入っていたら登録しない
if ( ! empty( $_POST['website'] ) || empty( $_POST['consent'] ) ) {
wp_safe_redirect( add_query_arg( 'nl', 'error', $back ) );
exit;
}
// 同じ IP からの連続送信を 1 分に 3 回までに制限
$key = 'mysite_nl_' . md5( isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '' );
$count = (int) get_transient( $key );
if ( $count >= 3 ) {
wp_safe_redirect( add_query_arg( 'nl', 'wait', $back ) );
exit;
}
set_transient( $key, $count + 1, MINUTE_IN_SECONDS );
$email = sanitize_email( wp_unslash( isset( $_POST['email'] ) ? $_POST['email'] : '' ) );
$fname = sanitize_text_field( wp_unslash( isset( $_POST['fname'] ) ? $_POST['fname'] : '' ) );
if ( ! is_email( $email ) ) {
wp_safe_redirect( add_query_arg( 'nl', 'invalid', $back ) );
exit;
}
$result = mysite_mailchimp_upsert( $email, $fname, array( 'wp-form' ) );
wp_safe_redirect( add_query_arg( 'nl', is_wp_error( $result ) ? 'error' : 'pending', $back ) );
exit;
}
add_action( 'admin_post_nopriv_mysite_subscribe', 'mysite_handle_subscribe' );
add_action( 'admin_post_mysite_subscribe', 'mysite_handle_subscribe' );
リダイレクト先のURLには結果の種類(nl=pending など)だけを付け、メールアドレスのような個人情報は付けません。表示側では $_GET['nl'] を決まった値と照合し、「確認メールを送りました。メール内のリンクを押すと登録が完了します」のような案内を出します。
ページキャッシュを使っているサイトでは、フォームを含むページがキャッシュされると nonce が古くなり、一定時間後に送信が失敗することがあります。フォームのあるページをキャッシュ対象から外すか、nonce の有効期間内にキャッシュが更新される設定にしてください。
よくあるエラーの読み方
失敗時は、Mailchimp が返す JSON の title と detail に原因が書かれています。上の関数では title を WP_Error に入れているので、まずそれを確認します。
- 401 / API Key Invalid:キーの貼り間違いか、失効しています。データセンター識別子とホスト名が一致しているかも見ます。
- 404 / Resource Not Found:オーディエンスIDの誤りが多い原因です。別アカウントのIDを使っていないかも確認します。
- 400 / Invalid Resource:メールアドレスの形式やマージフィールドの値が不正です。
detailやerrorsにどの項目かが出ます。 - Forgotten Email Not Subscribed:Mailchimp 上で恒久的に削除(個人データの削除依頼などによる)されたアドレスは、API からは再登録できません。本人に Mailchimp の公式登録フォームから改めて登録してもらう必要があります。
- Member Exists:
POST /membersで追加しようとしたときの重複エラーです。この記事のようにPUTとstatus_if_newを使えば発生しません。
まとめ
- フォームを置くだけならプラグインで足りる。既存処理と組み合わせたい、タグを細かく付けたい場合に直接連携を選ぶ。
- API キーは wp-config.php の定数か環境変数に置き、データセンター識別子から接続先ホストを決める。
PUT /lists/{list_id}/members/{hash}とstatus_if_new: pendingで、重複エラーを避けつつダブルオプトインにし、配信停止した人を勝手に戻さない。- 受け取り処理には nonce、隠し項目によるボット対策、IP 単位の連続送信制限、同意チェックを入れる。
- エラーは返ってきた
titleとdetailで切り分け、個人情報は URL やログに残さない。