表示中の記事と同一カテゴリーの人気記事をカンタンに出力する方法

この記事は17分くらいで読めます!

WEB運営をしている方なら誰しも気にするであろうサイト内の回遊率。

検索エンジンやリンクから辿ってきたユーザーさんが、いかにブログ内の他の記事に興味を持ってくれるかが鍵になりますよね。

大多数の方はサイドバーや記事下に関連記事人気記事ランキングなどを設置している事と思いますが、多数のカテゴリーを持つブログなどでは表示中の記事内容と全然関係ない記事のランキングが出てきてしまったりすると思います。

WordPressの人気無料テーマ「Simplicity2」ではカテゴリーに関連付いた人気記事出力がデフォルトで搭載されているのですが(宣伝)、僕が現在利用中のテーマ「SANGO」では総合・全期間のランキングしか表示することができませんでした……。

この記事を執筆時点で大して記事数があるわけじゃないので別に構わないのですが、将来的なことを考えて何とか実装したいなーと思っていた折、ドンピシャな記事を発見しました。

参考 記事クリック率が劇的に上がる!SANGOの関連記事カスタマイズマサオカブログ
MEMO
「SANGO」以外のテーマでも、ちょっとした編集で使えるようになりますよ!詳しくは後述します。

これこそまさに求めていたもの、ありがたく使わせて頂きました!

しかし、そのままコピペだと設置するウィジェットの位置によってはトップページに表示されたりして、少しおかしな挙動をしてしまいます。この記事ではそれを解消しつつ、カテゴリーアーカイブページでも表示できるように調整しました。

投稿ページとカテゴリーアーカイブページの時だけ表示する

基本的な実装方法はリンク先サイト様にて解説されていますので、それを元に少し手を加えていきます。

元のコードは以下の通り。

php
<h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php the_category(', ') ?>」</br>同じカテゴリの人気記事</h4>
<?php $cat = get_the_category(); ?>
<?php $cat_id = isset( $cat[0] ) ? $cat[0]->term_id : ''; ?>
<?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
<?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 1,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' ); ?>
<?php wpp_get_mostpopular( $args ); ?>
<?php endif; ?>

phpの条件分岐を追加する

WordPressに搭載されている非常に便利な条件分岐を使います。

条件分岐について詳しくは日本語版Codexをご覧下さい。

参考 条件分岐タグWordPress Codex 日本語版

投稿ページは、is_single()で、カテゴリーアーカイブページはis_category()で判別してあげます。

これを追加したのが下の形

php
<?php if ( is_single() || is_category() ) ://投稿ページとカテゴリーページのみ表示 ?>
<h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php the_category(', ') ?>」</br>同じカテゴリの人気記事</h4>
<?php $cat = get_the_category(); ?>
<?php $cat_id = isset( $cat[0] ) ? $cat[0]->term_id : ''; ?>
<?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
<?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 1,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' ); ?>
<?php wpp_get_mostpopular( $args ); ?>
<?php endif; ?>
<?php endif;//投稿ページとカテゴリーページのみ表示 ?>

先頭の行と最終行にコードが増えましたね!これは何をしているかというと、先頭で”もし投稿ページもしくはカテゴリーアーカイブだったらこのプログラムを実行しなさいよ”という命令を出し、最終行で”実行するのはここまでですよ”と指定しています。

さて、たったこれだけで投稿ページとカテゴリーアーカイブ以外ではランキングが出力されなくなりました!めでたしめでたし!

……というわけにもいかず、まだカテゴリーページで不安定な動作をします。

というのも、例えばカテゴリーが階層になっていると(子カテゴリーなどがついている状態だと)現状のコードではカテゴリー名やらを正しく取得できないので、正確なランキングが表示できないのです。

下の図は、「WEB」カテゴリーアーカイブを表示した時のランキングです。下層の「WordPressプラグイン」カテゴリーが取得されてしまいました。

カテゴリーアーカイブのページ名を取得する

正しく取得できない原因は、コード内で使用している関数get_the_categoryが現在の投稿が属するカテゴリーを取得するための関数だからです。

参考 テンプレートタグ/get the categoryWordPress Codex 日本語版

ですので、またまた条件分岐でカテゴリーアーカイブで取得できる関数を適用してあげましょう。

カテゴリーアーカイブではget_categoryで情報を取得できるのですが、今回は下層のカテゴリーもまとめてランキングしたいので、コードが少し冗長になってしまいます。プログラム簡略化のために、代わりにsingle_cat_titleを使ってカテゴリー名を直接取得してしまいます!

参考 テンプレートタグ/get categoryWordPress Codex 日本語版 参考 テンプレートタグ/single cat titleWordPress Codex 日本語版
php
<?php $cat = single_cat_title('',false);//アーカイブページのカテゴリー名を取得 ?>
<?php $cat_id = get_cat_ID($cat);//取得したカテゴリーのIDを取得 ?>

下層のカテゴリーも含めてランキング表示するために

先ほど取得した情報を元に、下の階層がある場合はそちらも拾いにいきましょう!

php
<?php $cats = get_term_children($cat_id, 'category');//子カテゴリのIDを配列として取得 ?>
<?php
 if ( !empty( $cats ) ) {//配列が空でなければ(子カテゴリーが存在していれば)
 foreach ($cats as $key => $value) {//配列をforeachループでカンマ区切りして変数へ追加
 $cat_id .= ',' . $value;
 }
 }
?>

これで、最下層の場合はそのカテゴリーの、親カテゴリーであれば子カテゴリーまですべてのIDを取得することができました。

このIDパラメータをWordPress Popular Postsに渡してあげれば、意図したランキング表示の完成です!

php
<?php if ( is_category() ) ://カテゴリーページでの表示 ?>
<?php $cat = single_cat_title('',false);//アーカイブページのカテゴリー名を取得 ?>
<?php $cat_id = get_cat_ID($cat);//取得したカテゴリーのIDを取得 ?>
<?php $cats = get_term_children($cat_id, 'category');//子カテゴリのIDを配列として取得 ?>
<h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php echo $cat; ?>」</br>同じカテゴリの人気記事</h4>
<?php
 if ( !empty( $cats ) ) {//配列が空でなければ(子カテゴリーが存在していれば)
 foreach ($cats as $key => $value) {//配列をforeachループでカンマ区切りして変数へ
 $cat_id .= ',' . $value;
 }
 }
?>
<?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
<?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 0,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' ); ?>
<?php wpp_get_mostpopular( $args ); ?>
<?php endif; ?>
<?php endif;//is_category ?>

投稿ページとカテゴリーアーカイブで挙動を分ける

カテゴリーアーカイブページでのコードが完成しましたので、最初のコードを投稿ページのみの条件にして、くっつけてしまいましょう!

php
<?php if ( is_single() ) ://投稿ページのみ表示 ?>
<h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php the_category(', ') ?>」</br>同じカテゴリの人気記事</h4>
<?php $cat = get_the_category(); ?>
<?php $cat_id = isset( $cat[0] ) ? $cat[0]->term_id : ''; ?>
<?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
<?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 1,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' ); ?>
<?php wpp_get_mostpopular( $args ); ?>
<?php endif; ?>
<?php elseif ( is_category() ) ://カテゴリーページでの表示 ?>
<?php $cat = single_cat_title('',false);//アーカイブページのカテゴリー名を取得 ?>
<?php $cat_id = get_cat_ID($cat);//取得したカテゴリーのIDを取得 ?>
<?php $cats = get_term_children($cat_id, 'category');//子カテゴリのIDを配列として取得 ?>
<h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php echo $cat; ?>」</br>同じカテゴリの人気記事</h4>
<?php
 if ( !empty( $cats ) ) {//配列が空でなければ(子カテゴリーが存在していれば)
 foreach ($cats as $key => $value) {//配列をforeachループでカンマ区切りして変数へ
 $cat_id .= ',' . $value;
 }
 }
?>
<?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
<?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 0,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' ); ?>
<?php wpp_get_mostpopular( $args ); ?>
<?php endif; ?>
<?php endif; ?>

これでバッチリ、しっかりと動いてくれるようになりました!

しかし、コードがめちゃくちゃ長い!!

それもそのはず、最初の数行以外はまったく同じ処理をする記述が2回もあるんですもの。

これだと見てくれが非常によろしくないので、重複する部分はまとめて書くように形を変えてあげましょう。

プログラムコードを整形

重複しているのは、カテゴリーIDを取得して変数に入れる部分以外全て!

まとめると、下のような形になります。

php
<?php if ( is_single() || is_category() ) ://投稿ページとカテゴリーページのみ表示 ?>
 <h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php echo $cat_name; ?>」</br>同じカテゴリの人気記事</h4>
 <?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
 <?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 0,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' );
 ?>
 <?php wpp_get_mostpopular( $args ); ?>
 <?php endif; ?>
<?php endif; ?>
MEMO
ピンク色のハイライト部分、オリジナルではカテゴリーアーカイブへのリンク付きでしたが、このソースコードではリンクは含まれません。リンクを付けたい場合は少し改変が必要です。

ここまでで共通の処理ができますので、あとはこれに渡してあげる情報を取得する部分をくっつけてあげるとこうなります。

php
<?php
 if ( is_single() ) {//投稿ページでの挙動
 $cat = get_the_category();//現在のページのカテゴリー情報を取得
 $cat_name = isset( $cat[0] ) ? $cat[0]->cat_name : '';//取得したカテゴリー情報からカテゴリー名を抽出
 $cat_id = isset( $cat[0] ) ? $cat[0]->term_id : '';//取得したカテゴリー情報からIDを抽出
 } else if ( is_category() ) {//カテゴリーページでの挙動
 $cat_name = single_cat_title('',false);//現在のカテゴリー名を取得
 $cat_id = get_cat_ID($cat_name);//カテゴリー名からIDを取得
 $cats = get_term_children($cat_id, 'category');//現カテゴリーに含まれる子カテゴリのIDを配列として取得
 if ( !empty( $cats ) ) {//配列が空でなければ(子カテゴリーが存在していれば)
 foreach ($cats as $key => $value) {//配列をforeachループでカンマ区切りして変数へ追加
 $cat_id .= ',' . $value;
 }
 }
 }
?>
<?php if ( is_single() || is_category() ) ://投稿ページとカテゴリーページのみ表示 ?>
 <h4 class="widgettitle dfont"><i class="fa fa-line-chart"></i> 「<?php echo $cat_name; ?>」</br>同じカテゴリの人気記事</h4>
 <?php if ( function_exists( 'wpp_get_mostpopular' ) ) : ?>
 <?php $args = array( 
 'limit' => 5,//表示数
 'range' => 'all',//集計する期間(weekly,monthly,all)
 'order_by' => 'views',//閲覧数で集計、comments(コメント数で集計)、avg(1日の平均で集計))
 'thumbnail_width' => 81,
 'thumbnail_height' => 81,
 'cat' => $cat_id,
 'wpp_start' => '<ul class="my-widget show_num">',
 'wpp_end' => '</ul>',
 'stats_views' => 0,//閲覧数表示(1 or 0)
 'stats_comments' => 0,//コメント数表示(1 or 0)
 'post_html' => '<li><a href="{url}"> <figure class="my-widget__img">{thumb_img}</figure><div class="my-widget__text">{text_title} <span class="dfont views"> {stats}</span></div></a></li>' );
 ?>
 <?php wpp_get_mostpopular( $args ); ?>
 <?php endif; ?>
<?php endif; ?>

……まだ少し長いような気もしますが、一応はこれで完成となります。

MEMO
紫色のハイライト部分が出力されるHTMLになります。SANGO以外のテーマの方は、ここをご使用のテーマに合わせて書き換えれば流用可能ですので、ぜひお試しください!

このソースコードをPHPコードウィジェットにコピペして保存すると、いい感じにランキングを作ってくれるはずです!

さいごに

このウィジェットをユーザーさんの目に留まりやすい位置に配置しておけば、自然と興味を惹かれるテーマの記事に誘導することができるかもしれませんね♪

回遊率が上がればGoogleからも役に立つページと認識してもらえるし、SEO対策にも有利かも?

ちょっとしたカスタマイズでブログの動線を強化してみましょう!

2 Comments

トマト

こんにちは。いつも素敵な情報をありがとうございます。
先ほど設定してみました。記事内には、コードが沢山ありますが、
こちらは、一番最後に書かれたコードのみをコピペすれば
動くという事でよろしいでしょうか?

SANGOにて先ほど実装してみましたが、
記事ぺージ開くとサイドバーに
カテゴリ名がちゃんと取得できて、
表示されているのですが、
肝心の記事そのものが取得できていない様です。

データが溜まっていないのかと思い、
シークレットウィンドウにて
何回か同カテゴリ内の記事をスマホ端末から
アクセスしてみましたが、

特に変化なしの状態でした。

サイドバーには以下の2つが表示されております。

・アイコン「カテゴリ名」
・同じカテゴリの人気記事

この記事に書いてある意外のプラグインなどが
必要という事でしょうか?

考えられる原因が分からず、
ご教示頂けたら幸いですm(_ _)m

返信する
トマト

先ほどコメントしたものです。
WordpressPopularPostsのプラグインを
入れて有効化した後の話だったんですね!

今色々試行錯誤して、表示を確認しました。
先ほどの疑問は解消されました。

お手数掛けて申し訳ございません。
回答は大丈夫です。

ありがとうございました。m(_ _)m

返信する

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です