2つのブログを自動でつなぐ!タグで別サイトの記事をブログカード表示する自作プラグイン【WordPress】
ブログを2つ運営していると、「こっちの記事を読んだ人に、もう1つのブログの関連記事も読んでほしい」と思うことがあります。でも、記事を書くたびに手作業でリンクを貼るのは大変です。
そこで、記事のタグを使って、もう1つのブログから関連記事を自動で探し、ブログカードで表示する自作プラグインを作りました。今回は、その仕組みとソースコード、さらに最近行った改良点を紹介します。
このプラグインでできること
投稿ページの本文の最後に、「あわせて読みたい」という見出しと一緒に、もう1つのブログの記事がブログカードで最大3枚表示されます。
| 項目 | 内容 |
|---|---|
| 表示場所 | 投稿ページの本文の最後 |
| 探し方 | 記事に付いているタグ名で、もう1つのブログを検索 |
| 表示形式 | Cocoonのブログカード(ショートコード) |
| 最大表示数 | 3枚まで |
| 重複 | 同じ記事は2回出さない |
| キャッシュ | 検索結果を保存して、毎回問い合わせない |
例えば「那須川天心」というタグが付いた記事なら、もう1つのブログで「那須川天心」を検索して、見つかった記事をカードで紹介してくれます。記事を書く時はタグを付けるだけで、リンクを貼る作業は一切いりません。
仕組み
WordPressには、外部から記事を検索できる「REST API」という機能が最初から付いています。このプラグインはそれを利用しています。
| 順番 | 処理 |
|---|---|
| 1 | 表示中の記事のタグを順番に取り出す |
| 2 | タグ名で、もう1つのブログのREST APIに検索をかける |
| 3 | 見つかった記事の1件目のURLを取り出す |
| 4 | Cocoonの … にして本文の最後に追加 |
| 5 | 3枚になるか、タグが無くなったら終了 |
検索に使うURLはこんな形です。
https://example.com/wp-json/wp/v2/posts?search=タグ名&per_page=1ブラウザでこのURLを開くと、検索結果がJSON形式で表示されます。プラグインはこれを読み取っています。
ソースコード
ファイル名は cross-blog-card.php などにして、wp-content/plugins/ フォルダにアップロードします。
<?php
/*
Plugin Name: Cross-Blog Card with Cache (2サイト用・重複防止・最大3枚版)
Description: もう1つのブログから記事を探し、最大3枚まで重複なしでブログカードを表示します。失敗時も短時間キャッシュして連続アクセスを防ぎます。
*/
if ( !defined( 'ABSPATH' ) ) exit;
function cross_blog_card_display_single_target( $content ) {
// 投稿ページの本文の本表示の時だけ動かす(管理画面・RSS・本文以外の呼び出しでは動かない)
if ( is_admin() || is_feed() || !is_single() ) return $content;
if ( !in_the_loop() || !is_main_query() ) return $content;
$tags = get_the_tags();
if ( !$tags ) return $content;
$insert_html = '';
// 連携するブログのURL
$target_url = 'https://example.com/';
$displayed_urls = array(); // 表示したURLのメモ
$card_count = 0; // 表示したカードの枚数
$max_cards = 3; // 最大何枚まで表示するか
foreach ( $tags as $tag ) {
if ( $card_count >= $max_cards ) {
break;
}
$tag_name = $tag->name;
$cache_key = 'cross_blog_' . md5( $target_url . $tag_name );
$cached_url = get_transient( $cache_key );
if ( $cached_url === false ) {
$api_url = rtrim( $target_url, '/' ) . '/wp-json/wp/v2/posts?search=' . urlencode( $tag_name ) . '&per_page=1';
$response = wp_remote_get( $api_url, array( 'timeout' => 5 ) );
if ( !is_wp_error( $response ) && (int) wp_remote_retrieve_response_code( $response ) === 200 ) {
$posts = json_decode( wp_remote_retrieve_body( $response ) );
if ( !empty( $posts ) && !empty( $posts[0]->link ) ) {
//見つかった:12時間キャッシュ
$cached_url = $posts[0]->link;
set_transient( $cache_key, $cached_url, 12 * HOUR_IN_SECONDS );
} else {
//該当記事なし:12時間キャッシュ
$cached_url = 'not_found';
set_transient( $cache_key, $cached_url, 12 * HOUR_IN_SECONDS );
}
} else {
//接続失敗・エラー:10分キャッシュ(その間は問い合わせない)
$cached_url = 'error';
set_transient( $cache_key, $cached_url, 10 * MINUTE_IN_SECONDS );
}
}
if ( $cached_url === 'not_found' || $cached_url === 'error' ) {
continue;
}
if ( !in_array( $cached_url, $displayed_urls, true ) ) {
$insert_html .= '' . esc_url( $cached_url ) . '';
$displayed_urls[] = $cached_url;
$card_count++;
}
}
// ブログカードが1つでも追加されていれば、先頭に見出しを付ける
if ( $insert_html !== '' ) {
$insert_html = '<h3>あわせて読みたい</h3>' . $insert_html;
}
return $content . $insert_html;
}
add_filter( 'the_content', 'cross_blog_card_display_single_target' );設置方法
| 手順 | 作業 |
|---|---|
| 1 | 上のコードの $target_url を、連携したいブログのURLに書き換える |
| 2 | UTF-8(BOMなし)で保存して、wp-content/plugins/ にアップロード |
| 3 | 管理画面のプラグイン一覧で「有効化」 |
| 4 | タグ付きの記事を開いて、本文の最後にカードが出るか確認 |
カスタマイズできるところ
| 変えたいこと | 書き換える場所 |
|---|---|
| 連携するブログ | $target_url = ‘https://example.com/’; |
| 最大表示数 | $max_cards = 3; |
| 見出しの文字 | <h3>あわせて読みたい</h3> |
| キャッシュ時間 | 12 * HOUR_IN_SECONDS(12時間)、10 * MINUTE_IN_SECONDS(10分) |
今回の改良:相手のサイトが落ちていても遅くならないように
最初のバージョンでは、検索結果が「見つかった時」と「見つからなかった時」だけキャッシュしていました。ところが、相手のブログが落ちていたりエラーを返した時はキャッシュしていなかったので、その間は記事が表示されるたびに毎回相手に問い合わせに行ってしまいます。
1回の問い合わせで最大5秒待つので、相手サイトの調子が悪いと、こちらのブログまで表示が遅くなるという弱点がありました。
| 状況 | 改良前 | 改良後 |
|---|---|---|
| 記事が見つかった | 12時間キャッシュ | 12時間キャッシュ |
| 記事が見つからなかった | 12時間キャッシュ | 12時間キャッシュ |
| 接続失敗・エラー | キャッシュなし(毎回問い合わせ) | 10分キャッシュ |
あわせて、次の点も改良しました。
| 改良点 | 理由 |
|---|---|
| タイムアウトを5秒に明示 | 待ち時間の上限をはっきりさせるため |
| RSSフィードでは動かないように | RSSにカードのショートコードが混ざらないようにするため |
| 本文の本表示の時だけ動くように | 本文以外で the_content が呼ばれた時に、無駄な検索をしないため |
注意点
| 注意点 | 内容 |
|---|---|
| Cocoonのブログカードを使っている | はCocoonのショートコードなので、他のテーマでは表示されません |
| 相手のREST APIが有効であること | セキュリティ系プラグインでREST APIを止めていると検索できません |
| 検索結果の1件目を使う | タグ名が本文に含まれるだけの記事が選ばれることもあります |
| いつの間にか無効になっていることがある | サーバー移行などの後は、プラグイン一覧で有効になっているか確認を |
ちなみに私の場合、サーバー移行のあとこのプラグインがいつの間にか無効になっていて、しばらくカードが表示されていませんでした。移行後はプラグイン一覧の「停止中」を一度確認しておくのがおすすめです。
まとめ
- 記事にタグを付けるだけで、もう1つのブログの関連記事を自動でカード表示
- WordPress標準のREST APIを使うので、追加のプラグインは不要
- 検索結果はキャッシュして、相手サイトへの負担も表示速度も安心
- 相手サイトが落ちている時も10分キャッシュで、こちらの表示は遅くならない
複数のブログを運営している方は、サイト同士をつなぐ仕組みとしてぜひ試してみてください。






コメント