複数のWordPressサイトを運営しているのですが、そのサイトの人気記事を別のサイトでも一覧表示したいと思いました。PVデータはKoko Analyticsで集計していたので、それを活用した記事推薦システムとして、おすすめ記事リストを表示するプラグイン開発を作りました。
これらの課題を解決するため、二つのプラグインからなるシステムを開発しました。「参照元サイト」でデータを提供し、「表示側サイト」がそれを取得して表示する仕組みです。
1. システム設計の概要
システム全体は「提供側」と「利用側」の二つのプラグインで構成されています。
- 提供側プラグイン(Remote Posts Provider)は、WordPress投稿とKoko AnalyticsのPV数などをJSON形式で提供するURLを用意します。
- 利用側プラグイン(Remote Posts Consumer)は、提供側からJSONデータを定期的に取得してサイト内データベースに保存し、ショートコードでおすすめ記事リストを表示します。
データの流れとしては、次のようになります。
- 提供側サイトがWordPressの記事情報とKoko AnalyticsのPV数を組み合わせる
- 利用側サイトが1日1回、提供側のAPIからJSONデータを取得する
- 取得したデータを利用側のデータベースに保存する
- 利用側サイトでは、PV数と適度なランダム性を組み合わせてランキングを計算し、ショートコードを使って記事リストを表示する
2. プラグインの使い方
完成したプラグインの基本的な使い方を紹介します。
2.1. 提供側(Provider)の設定
- プラグインをアップロードして有効化
- 管理画面 > 設定 > Remote Posts Provider へ移動
- 自動生成されたシークレットキーを確認
- 必要に応じて設定を調整(取得日数、キャッシュ時間など)
2.2. 利用側(Consumer)の設定とショートコードの利用
- プラグインをアップロードして有効化
- 管理画面 > 設定 > Remote Posts Consumer へ移動
- 提供側のAPIエンドポイントURLを入力 例:
https://example.com/wp-json/remote-posts/v1/list - 提供側で確認したシークレットキーを入力
- 「Fetch Posts Now」ボタンをクリックして同期テスト
設定が完了したら、投稿や固定ページに以下のようなショートコードを配置します。
[remote_recommend_list posts="8" cats="news, tech" show_views="true" recent_days="90" weight_views="1.2" randomness="0.15"]
Code language: JSON / JSON with Comments (json)
主なパラメータは以下のとおりです。
posts: 表示する投稿数(1-50、デフォルト: 10)cats: フィルターするカテゴリ(カンマ区切り)show_views: PV数を表示するかどうか(true/false)recent_days: 過去何日分のデータを対象とするか(デフォルト: 90)weight_views: PV数の重み付け係数(高いほど人気記事優先)randomness: ランダム要素(0.0-1.0、高いほど表示が多様化)
これらのパラメータを調整することで、様々な表示パターンが実現できます。
3. データ交換フォーマット
Provider側はJSON形式でデータを提供します。URLへのレスポンスとして、記事情報の配列を返します。
{
"id": 123,
"title": "記事のタイトル",
"eyecatch_svg": "<svg>...</svg>",
"url": "https://example.com/sample-post/",
"categories": ["tech", "news"],
"views": 42,
"updated_at": "2025-10-15T10:30:45Z"
}Code language: JSON / JSON with Comments (json)
毎回アクセスすると負荷がかかるので、Consumer側では、取得したデータを対応した独自のデータベーステーブルに保存します。
CREATE TABLE {prefix}_remote_posts_cache (
source_post_id BIGINT UNSIGNED PRIMARY KEY,
title TEXT NOT NULL,
eyecatch_svg LONGTEXT,
url TEXT NOT NULL,
views INT UNSIGNED DEFAULT 0,
categories LONGTEXT,
updated_at DATETIME DEFAULT NULL,
fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_views (views),
KEY idx_updated_at (updated_at)
);Code language: PHP (php)
Consumer側ではこのデータベースからデータを取得し、PV数とランダム性を組み合わせたランキングアルゴリズムを適用して、おすすめ記事リストを生成します。
各フィールドの説明:
source_post_id: 元サイトの投稿ID(主キー)title: 記事タイトルeyecatch_svg: アイキャッチ画像のSVGコード(ある場合のみ)url: 記事のURLviews: PV数(閲覧数)categories: カテゴリslugの配列(JSON文字列として保存)updated_at: 記事の最終更新日時fetched_at: データを取得した日時- インデックス: PV数と更新日時にインデックスを設定して検索を高速化
3.1. HMAC認証によるセキュリティ対策
インターネット上でサイトのデータをやり取りするので、セキュリティは重要な課題です。
今回は、サイトからの正しいアクセスだけにデータを提供するように、「シークレットキー」を導入しました。
HMAC-SHA256という認証方式で、「Hash-based Message Authentication Code(ハッシュベースのメッセージ認証コード)」の略です。具体的には、リクエスト時に現在のタイムスタンプと、そのタイムスタンプを秘密鍵で暗号化した署名を送信します。受け取った側は同じ秘密鍵を使って署名を検証し、改ざんされていないことを確認します。
そのほか、不正アクセスやデータの漏洩を防止するため、以下の対策もしました。
- タイムスタンプの有効期限チェック(±10分以内のリクエストのみ有効)
- レート制限(5分間に20リクエストまで)
- IPアドレス制限(特定のIPからのアクセスのみ許可する設定が可能)
- User-Agent検証(特定のクライアント識別情報を確認)
- HTTPS通信の推奨(暗号化された通信の利用)
3.2. ランキングアルゴリズムの工夫
おすすめ記事リストの表示には、単純なPV順だけでなく、適度なランダム性を導入することで多様性を持たせています。毎回同じ人気記事ばかりが表示されるのを避け、より多様な記事が読者の目に触れる機会を作るためです。
具体的なアルゴリズムは以下のとおりです。
- 各記事のPV数を正規化(0〜1の範囲に変換)
- 重み付け係数を適用(PVの影響度を調整)
- ランダム要素を追加(設定範囲内でランダムに変動)
- 最終スコアを計算して記事をソート
数式で表すと次のようになります。
normalized_views = views / max(views)
random_factor = uniform(1-randomness, 1+randomness)
score = (normalized_views ^ weight_views) * random_factor
4. プラグイン実装のポイント
プラグイン開発における主要なポイントをいくつか紹介します。
4.1. モジュラー設計によるコード管理
最初は一つのファイルにすべての機能を実装していましたが、コードが肥大化して管理が難しくなりました。そこで、機能ごとにクラスを分割し、それぞれの役割を明確にしました。
提供側(Provider)プラグインでは:
- 管理画面クラス:設定画面のUIを担当
- API処理クラス:REST APIエンドポイントを提供
- ユーティリティクラス:共通機能を集約
chiilabo-remote-posts-provider/
├── chiilabo-remote-posts-provider.php # メインプラグインファイル
├── includes/ # クラスファイル
│ ├── class-crpp-admin.php # 管理画面クラス
│ ├── class-crpp-api.php # API処理クラス
│ └── class-crpp-utils.php # ユーティリティクラス
├── assets/
│ ├── css/
│ │ └── admin.css # 管理画面用スタイル
│ └── js/
│ └── admin.js # 管理画面用スクリプト
└── index.php # セキュリティ対策用Code language: PHP (php)
利用側(Consumer)プラグインでは:
- 管理画面クラス:設定画面のUIを担当
- 同期処理クラス:外部APIからのデータ取得を実行
- 表示処理クラス:ショートコード出力を担当
- ユーティリティクラス:データベース操作などを実装
chiilabo-remote-posts-consumer/
├── chiilabo-remote-posts-consumer.php # メインプラグインファイル
├── includes/ # クラスファイル
│ ├── class-crpc-admin.php # 管理画面クラス
│ ├── class-crpc-sync.php # 同期処理クラス
│ ├── class-crpc-display.php # 表示処理クラス
│ └── class-crpc-utils.php # ユーティリティクラス
├── assets/
│ ├── css/
│ │ ├── admin.css # 管理画面用スタイル
│ │ └── frontend.css # フロントエンド用スタイル
│ └── js/
│ └── admin.js # 管理画面用スクリプト
└── index.php # セキュリティ対策用Code language: PHP (php)
4.2. エラーハンドリングと復旧機能
実運用を考慮し、エラー発生時の対応も重視しました。例えば、API通信が失敗した場合には以前に取得したデータを使用する「フォールバック機能」を実装しています。
また、メモリ使用量を監視し、大量のデータを処理する場合でもサーバーに負荷をかけないよう配慮しました。具体的には、データ取得時にメモリ使用量が一定値を超えた場合、処理を中断して部分的な同期を完了させる機能を追加しています。
4.3. パフォーマンス最適化
ユーザー体験を向上させるため、以下のようなパフォーマンス最適化も行いました。
- API応答とショートコード出力のキャッシュ
- 軽量なデータ取得(必要最小限のデータのみを取得)
- ページネーションによる大量データの分割処理
- 条件付きスクリプト読み込み(必要な場合のみCSSやJSを読み込む)
これらの工夫により、サーバー負荷を抑えながらスムーズな動作を実現しています。
5. まとめ
複数のWordPressサイトを運営する際の「別サイトの人気記事を紹介したい」という課題に対して、オリジナルプラグインを開発しました。サイト間でのデータ共有という目的を達成しながら、セキュリティ、パフォーマンス、エラーハンドリングなどの実用的な側面も考慮しています。
また、単純なPV順ではなく適度なランダム性を加えることで、多様な記事が読者の目に触れる機会を作り出す工夫も行いました。
モジュラー設計の採用により、今後の拡張や改善も容易になっています。このプラグインが、WordPress運営者の方々のサイト間連携の一助となれば幸いです。