2026年10月25日
2026年10月25日
WordPress で Web プッシュ通知を FCM(Firebase Cloud Messaging)で実装する方法|Service Worker・トークンの保存・HTTP v1 API での送信
WordPress で Web プッシュ通知を FCM(Firebase Cloud Messaging)で実装する流れは、ブラウザー側で通知の許可を取り、Service Worker を登録してトークンを受け取る → そのトークンを WordPress に保存する → サーバーから FCM の HTTP v1 API にトークン宛ての通知を送る、の 3 段階です。送信に使うレガシー API(サーバーキーを使う旧方式)はすでに停止しているため、新しく作るなら HTTP v1 API とサービスアカウントで実装します。
結論を先にまとめます。
- FCM の JavaScript SDK は HTTPS のページでだけ動きます。Service Worker のファイル名は
firebase-messaging-sw.jsで、ドメインのルートに置くことが公式に案内されています。 - トークンは利用者ごと・ブラウザーごとに発行され、変わることがあります。WordPress 側にトークンを保存する REST エンドポイントを用意します。
- 送信は
https://fcm.googleapis.com/v1/projects/プロジェクト ID/messages:sendに、サービスアカウントから得た OAuth 2.0 のアクセストークンを付けて POST します。 - 自分で実装するより、Web プッシュ対応のプラグインで済む要件も多いです。要件を先に確かめてから選びます。
FCM の Web プッシュの仕組み
Web プッシュは、ブラウザーの Push API と Service Worker を使って、サイトを開いていないときにも通知を表示する仕組みです。FCM はその上で、ブラウザーごとに異なるプッシュサービスの違いを吸収し、トークン 1 つで送れるようにしてくれます。
| 要素 | 役割 | 置き場所 |
|---|---|---|
| Firebase プロジェクトと Web アプリ設定 | API キー・プロジェクト ID などの設定値、VAPID 鍵 | Firebase コンソール |
| クライアント JavaScript | 許可を求め、トークンを取得し、前面表示中のメッセージを受け取る | WordPress のテーマまたはプラグインが出力 |
firebase-messaging-sw.js |
背景(ページを開いていない時)のメッセージ受信と通知表示 | ドメインのルート(例: https://example.com/firebase-messaging-sw.js) |
| トークン保存 API | ブラウザーから送られたトークンを保存・削除する | WordPress の REST API(自作) |
| 送信側 | HTTP v1 API に通知を POST する | WordPress の PHP、または別のサーバー |
公式ドキュメントでは、通知ペイロード(notification)はページが背面のときブラウザーが自動で表示し、データペイロード(data)だけのメッセージは Service Worker 側で showNotification() を自分で呼ぶ必要がある、と区別されています。
手順 1: Firebase プロジェクトを用意する
- Firebase コンソールでプロジェクトを作り、「ウェブアプリ」を追加します。表示される設定オブジェクト(
apiKey、projectId、messagingSenderId、appIdなど)を控えます。 - プロジェクトの設定 → Cloud Messaging → ウェブ構成 で、ウェブプッシュ証明書(VAPID 鍵ペア)を生成し、公開鍵を控えます。公式ドキュメントは、この鍵をクライアントの
getTokenに渡すよう案内しています。 - 送信側で使う サービスアカウント の鍵(JSON)を、プロジェクトの設定 → サービスアカウント から作ります。この JSON は秘密情報です。WordPress の公開ディレクトリには置かず、ドキュメントルートの外か、環境変数で渡します。
手順 2: Service Worker をドメインのルートに置く
公式ドキュメントは、firebase-messaging-sw.js という名前のファイルをドメインのルートに置くことを求めています。WordPress をサブディレクトリ(例: /wordpress/)に入れているサイトでも、ファイルはドキュメントルート直下に置きます。Service Worker の有効範囲(scope)はファイルの置き場所で決まるためです。
// /firebase-messaging-sw.js(compat 版はバンドル不要)
importScripts('https://www.gstatic.com/firebasejs/10.12.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.12.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: 'ここに apiKey',
projectId: 'ここに projectId',
messagingSenderId: 'ここに messagingSenderId',
appId: 'ここに appId'
});
const messaging = firebase.messaging();
// データだけのメッセージを受けたときは自分で表示する
messaging.onBackgroundMessage(function (payload) {
const d = payload.data || {};
self.registration.showNotification(d.title || 'お知らせ', {
body: d.body || '',
data: { url: d.url || '/' }
});
});
SDK の版番号は公式のリリースノートで最新を確認して置き換えてください。公式ドキュメントは、Service Worker 内でモジュール版 SDK を使うにはバンドルが必要で、compat 版ならその手間が無いと説明しています。
手順 3: ブラウザーで許可を取り、トークンを受け取る
テーマまたは自作プラグインから、ログインしていない閲覧者にも読み込まれるスクリプトを出力します。ボタンを押したときに許可を求める形にすると、ページを開いた瞬間に許可ダイアログが出る体験を避けられます。
<script type="module">
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js';
import { getMessaging, getToken, onMessage } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-messaging.js';
const app = initializeApp({ apiKey: '...', projectId: '...', messagingSenderId: '...', appId: '...' });
const messaging = getMessaging(app);
document.getElementById('push-subscribe').addEventListener('click', async () => {
const permission = await Notification.requestPermission();
if (permission !== 'granted') return;
const token = await getToken(messaging, { vapidKey: 'ここに VAPID 公開鍵' });
await fetch('/wp-json/mysite/v1/push-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token })
});
});
// ページを開いている間に届いたメッセージ
onMessage(messaging, (payload) => {
console.log('foreground message', payload);
});
</script>
公式ドキュメントは、Notification.requestPermission() の結果が granted のときだけトークンを取るよう案内しています。トークンは変わることがあるので、ページ読み込み時に再取得して保存済みのものと違えば更新する処理を入れます。
手順 4: WordPress にトークンを保存する REST API を作る
自作プラグイン(または子テーマの functions.php)で、トークンを受け取るエンドポイントを登録します。ここでは専用テーブルを作らず、オプションに配列で保存する最小の例です。購読者が数千を超えるなら専用テーブルにします。
add_action( 'rest_api_init', function () {
register_rest_route( 'mysite/v1', '/push-token', array(
'methods' => 'POST',
'permission_callback' => '__return_true', // 未ログインの閲覧者も登録できるようにする
'args' => array(
'token' => array( 'required' => true, 'type' => 'string' ),
),
'callback' => function ( WP_REST_Request $req ) {
$token = sanitize_text_field( $req->get_param( 'token' ) );
if ( strlen( $token ) < 50 || strlen( $token ) > 4096 ) {
return new WP_Error( 'invalid_token', 'invalid', array( 'status' => 400 ) );
}
$tokens = get_option( 'mysite_push_tokens', array() );
$tokens[ $token ] = time();
update_option( 'mysite_push_tokens', $tokens, false );
return array( 'ok' => true );
},
) );
} );
誰でも叩けるエンドポイントなので、トークンの形式チェックに加えて、同一 IP からの登録回数の制限や nonce の検証を足すと、無関係な文字列を大量に登録される事態を防げます。REST API 全体の扱いはWordPress の REST API へのアクセスを制限する方法も参照してください。
手順 5: HTTP v1 API で送信する
送信先は次の URL で、Authorization: Bearer アクセストークン を付けて POST します。アクセストークンはサービスアカウントの鍵から OAuth 2.0 で取得し、スコープは https://www.googleapis.com/auth/firebase.messaging です(公式リファレンス)。
POST https://fcm.googleapis.com/v1/projects/プロジェクト ID/messages:send
{
"message": {
"token": "送信先のトークン",
"notification": { "title": "新着記事", "body": "記事の題名" },
"webpush": {
"fcm_options": { "link": "https://example.com/wordpress/new-post/" }
}
}
}
公式ドキュメントは、通知をクリックしたときに開くページを webpush.fcm_options.link で指定でき、HTTPS の URL だけが使えると説明しています。
PHP からアクセストークンを得るには、Google の公式ライブラリ google/apiclient(Composer)でサービスアカウント認証を使うのが手堅い方法です。Firebase Admin SDK の公式対応言語は Node.js・Java・Python・Go・C# で、PHP は含まれていません(2026年11月現在)。PHP 向けには第三者のライブラリもありますが、採用するなら保守状況を確認してください。
// composer require google/apiclient
$client = new Google\Client();
$client->setAuthConfig( '/path/outside/webroot/service-account.json' );
$client->addScope( 'https://www.googleapis.com/auth/firebase.messaging' );
$token = $client->fetchAccessTokenWithAssertion()['access_token'];
$res = wp_remote_post(
'https://fcm.googleapis.com/v1/projects/' . $project_id . '/messages:send',
array(
'headers' => array( 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( array( 'message' => $message ) ),
'timeout' => 15,
)
);
投稿の公開時に送るなら transition_post_status フックで「公開になった瞬間」を捉え、WP-Cron で非同期に送ると、公開操作が遅くなりません。無効になったトークン(応答に UNREGISTERED 相当のエラーが返るもの)は保存先から削除します。
レガシー API について
Firebase の公式案内では、サーバーキーを使う旧方式(レガシー HTTP / XMPP API)は 2023 年 6 月に非推奨となり、2024 年 7 月に停止されています。古い記事やプラグインの手順で「サーバーキーを設定に貼る」とあるものは、そのままでは動きません。送信部分を HTTP v1 API(サービスアカウント認証)に置き換える必要があります。
プラグインで済ませる選択肢
要件が「新着記事を購読者に通知する」程度なら、Web プッシュ通知のプラグイン(OneSignal の WordPress プラグインなど、外部サービスと連携するもの)で実装せずに済みます。自作が向くのは、通知の内容や送信条件を細かく制御したい、購読者データを自社で持ちたい、外部サービスの利用規約や料金体系を避けたい、といった場合です。どちらの場合も、プッシュ通知を使うことと購読の解除方法をプライバシーポリシーに書きます。
WordPress の運用の観点
- Service Worker は強い権限を持つファイルです。ドメインのルートに置くため、WordPress のアップロード経由ではなく、FTP やデプロイで配置し、書き換えられていないかを更新のたびに確かめます。
- サービスアカウントの鍵は公開ディレクトリに置かない。
wp-content/uploads/に置いた鍵ファイルが外部から読める事故が起きます。wp-config.phpの扱いと同様に、ドキュメントルートの外か環境変数で渡します。 - キャッシュプラグインが JavaScript を結合すると、
type="module"のスクリプトが壊れることがあります。除外設定を入れます。 - 購読解除の導線を用意し、トークンの削除 API も作ります。ブラウザー側で通知を拒否に変えた利用者のトークンは送信時のエラーで判別できます。
よくある質問
WordPress をサブディレクトリに入れていますが firebase-messaging-sw.js はどこに置きますか
ドメインのルート(ドキュメントルート直下)です。/wordpress/firebase-messaging-sw.js に置くと、Service Worker の有効範囲が /wordpress/ 以下に限られます。公式ドキュメントもルートに置くことを案内しています。
HTTP でもプッシュ通知は動きますか
動きません。FCM の SDK は Service Worker を使うため、公式ドキュメントのとおり HTTPS で配信されるページでだけ動作します。開発時の localhost は例外です。
iPhone の Safari でも届きますか
Web プッシュの対応はブラウザーの Push API の実装に依存します。公式ドキュメントは対応ブラウザーの一覧を参照するよう案内しているので、対象の利用者が使うブラウザーで実機確認をしてください。ホーム画面に追加した Web アプリでの挙動など、条件がある環境もあります。
古いプラグインの「サーバーキー」の欄に何を入れればよいですか
その方式(レガシー API)はすでに停止しています。HTTP v1 API に対応した版へ更新するか、対応していないプラグインなら別の手段に移ります。
まとめ
- FCM の Web プッシュは「許可とトークン取得(ブラウザー)→ トークン保存(WordPress の REST API)→ HTTP v1 API で送信(サーバー)」の 3 段階です。
firebase-messaging-sw.jsはドメインのルートに置き、HTTPS で配信します。サービスアカウントの鍵は公開ディレクトリの外に置きます。- レガシー API は停止済みです。新規実装は HTTP v1 API とサービスアカウント認証で行い、要件が単純ならプラグインも選択肢です。
関連記事
参考: Firebase – Set up a JavaScript Firebase Cloud Messaging client app、Receive messages in a JavaScript client、FCM HTTP v1 API – projects.messages.send、Send messages with the Firebase Admin SDK
更新履歴: 2026-11-09 全面改訂(停止済みのレガシー API を前提にした手順を HTTP v1 API とサービスアカウント認証に置き換え、Service Worker の置き場所、WordPress 側のトークン保存 API、送信コード、運用上の注意を追加)。この記事はワードプレス博士(ライトセンド株式会社)が運営しています。