テーマをCocoonに変更しました!
プラグイン

WordPressで別サイトの記事を自動ブログカード表示する自作プラグイン

FavoriteLoadingお気に入り登録
プラグイン

2つのブログを自動でつなぐ!タグで別サイトの記事をブログカード表示する自作プラグイン【WordPress】

ブログを2つ運営していると、「こっちの記事を読んだ人に、もう1つのブログの関連記事も読んでほしい」と思うことがあります。でも、記事を書くたびに手作業でリンクを貼るのは大変です。

そこで、記事のタグを使って、もう1つのブログから関連記事を自動で探し、ブログカードで表示する自作プラグインを作りました。今回は、その仕組みとソースコード、さらに最近行った改良点を紹介します。

このプラグインでできること

投稿ページの本文の最後に、「あわせて読みたい」という見出しと一緒に、もう1つのブログの記事がブログカードで最大3枚表示されます。

項目内容
表示場所投稿ページの本文の最後
探し方記事に付いているタグ名で、もう1つのブログを検索
表示形式Cocoonのブログカード(ショートコード)
最大表示数3枚まで
重複同じ記事は2回出さない
キャッシュ検索結果を保存して、毎回問い合わせない

例えば「那須川天心」というタグが付いた記事なら、もう1つのブログで「那須川天心」を検索して、見つかった記事をカードで紹介してくれます。記事を書く時はタグを付けるだけで、リンクを貼る作業は一切いりません。

仕組み

WordPressには、外部から記事を検索できる「REST API」という機能が最初から付いています。このプラグインはそれを利用しています。

順番処理
1表示中の記事のタグを順番に取り出す
2タグ名で、もう1つのブログのREST APIに検索をかける
3見つかった記事の1件目のURLを取り出す
4Cocoonの … にして本文の最後に追加
53枚になるか、タグが無くなったら終了

検索に使う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に書き換える
2UTF-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分キャッシュで、こちらの表示は遅くならない

複数のブログを運営している方は、サイト同士をつなぐ仕組みとしてぜひ試してみてください。

気になる中古パソコン

パソコン

Supported by Rakuten Web Service

コメント

タイトルとURLをコピーしました
PR

当サイトは、Amazon、楽天アソシエイト・他プログラムの参加者です。リンクを通じて商品を購入すると、紹介料を得る場合があります。

⚠ 免責事項

本記事は、筆者が実際に行った作業を記録したものです。サーバーの環境や設定によっては、同じ手順でも結果が異なる場合があります。

作業を行う際は、事前にバックアップを取ったうえで、ご自身の責任で実施してください。本記事の内容を参考にしたことによって生じたトラブルや損害について、当サイトは一切の責任を負いかねますので、あらかじめご了承ください。