概要説明
WP Super Cache などのページキャッシュが効いていると、PHP で数える閲覧数は増えません。見に来た人のブラウザから Ajax で数える functions.php と JavaScript のコード、管理画面の一覧に閲覧数を出して並べかえる方法。公開中の投稿だけ数える守り方も、作業環境で確かめた結果つきで。
WP Super Cache などのページキャッシュを使うと、2 回目からは保存しておいた HTML をそのまま返すので、PHP の処理が動かず、閲覧数を数えられません。そこで、見に来た人のブラウザから Ajax で数えるようにします。
キャッシュするページに閲覧数を出すと、その数字もキャッシュされるので、すぐには増えて見えません。数は正しく数えられていて、キャッシュが作り直されたときに出る数字が変わります。
~ 目次 ~
Ajax で数える JavaScript を足す
/**
* 記事のページで、閲覧数を 1 増やす(ページキャッシュが効いていても、見に来た人のブラウザから毎回送る)
*/
document.addEventListener( 'DOMContentLoaded', function () {
if ( ! window.myPv || ! myPv.postId ) {
return;
}
fetch( myPv.ajaxUrl, {
method: 'POST',
body: new URLSearchParams( { action: 'my_pv_count', post_id: myPv.postId } ),
credentials: 'same-origin',
} );
} );
テーマのフォルダの中の js フォルダ(例:wp-content/themes/テーマ名/js/pv-count.js)に置きます。jQuery は使っていません。
JavaScript を読み込む処理と、数える処理
/**
* 記事のページに、閲覧数を数える JavaScript を読み込む(ログインしていない人だけ)
*/
add_action( 'wp_enqueue_scripts', function () {
if ( is_user_logged_in() || ! is_singular( 'post' ) ) {
return;
}
$file = get_template_directory() . '/js/pv-count.js';
wp_enqueue_script( 'my-pv-count', get_template_directory_uri() . '/js/pv-count.js', array(), (string) filemtime( $file ), true );
wp_localize_script( 'my-pv-count', 'myPv', array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'postId' => get_queried_object_id(),
) );
} );
/**
* Ajax で呼ばれて、閲覧数を 1 増やす(公開中の投稿のときだけ)
*/
function my_pv_count() {
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
if ( ! $post_id || 'post' !== get_post_type( $post_id ) || 'publish' !== get_post_status( $post_id ) ) {
wp_die( '', '', array( 'response' => 400 ) );
}
$count = (int) get_post_meta( $post_id, 'page_view_cnt', true );
update_post_meta( $post_id, 'page_view_cnt', $count + 1 );
wp_die( (string) ( $count + 1 ) );
}
add_action( 'wp_ajax_nopriv_my_pv_count', 'my_pv_count' ); // ログインしていない人から
/**
* 閲覧数を取り出す
*/
function my_get_pv( $post_id ) {
return (int) get_post_meta( $post_id, 'page_view_cnt', true );
}
| 書き方 | 役目 |
|---|---|
| is_user_logged_in() のときは読み込まない | 自分や運営者が見た分を数えない |
| filemtime をファイルの版にする | JavaScript を直したときだけ読み込み直させる(前の time() だと毎回読み込み直していた) |
| wp_localize_script で記事の ID を渡す | テンプレートに隠した div を書き足さなくてよい |
| absint と公開中の投稿かの確かめ | 下書きや固定ページ、ない ID の数は増やさない(400 を返す) |
閲覧数を取り出して表示する
上のコードの my_get_pv() で、記事の閲覧数を取り出せます。
<?php echo esc_html( number_format( my_get_pv( get_the_ID() ) ) ); ?>
好きな場所に閲覧数を出せます。数字は 3 けたごとにカンマを入れています。
テンプレートに書き足すものはない
前はこの記事で、記事の ID を入れた隠した div をテンプレートに置いていました。今は wp_localize_script で JavaScript に ID を渡すので、テンプレートには何も書き足しません。
確かめた結果
このサイトの作業環境(WordPress 7.1)で試しました。
| 試したこと | 結果 |
|---|---|
| 公開中の投稿の ID で 2 回送る | 閲覧数が 1 → 2 と増えた |
| 固定ページの ID・ない ID・数字でないもの | 400 で、数は増えなかった |
| ログインしていない状態で記事を開く | 記事の ID(myPv.postId)が渡り、JavaScript がファイルの更新日時の版で読み込まれた |
試しに増やした閲覧数は、元に戻しました。
管理画面の投稿の一覧に閲覧数を出す
/**
* 管理画面の投稿の一覧に、閲覧数の列を足す
*/
add_filter( 'manage_posts_columns', function ( $columns ) {
$columns['page_view_cnt'] = 'PV';
return $columns;
} );
add_action( 'manage_posts_custom_column', function ( $column_name, $post_id ) {
if ( 'page_view_cnt' === $column_name ) {
echo esc_html( number_format( my_get_pv( $post_id ) ) );
}
}, 10, 2 );
管理画面の一覧で、記事ごとの閲覧数が見られます。数えたぶんだけ、そのまま増えていきます。
管理画面に IP の制限をしているとき
# 管理画面に IP の制限をしていても、admin-ajax.php だけは誰でも使えるようにする(Apache 2.4 の書き方) <Files "admin-ajax.php"> Require all granted </Files>
Ajax は wp-admin/admin-ajax.php に送るので、管理画面に IP の制限をかけていると、見に来た人の分が数えられません。admin-ajax.php だけ制限を外しておきます(前は Apache 2.2 の「allow from all」でしたが、今の Apache 2.4 では「Require all granted」です)。
閲覧数の列で並べかえる
/**
* 閲覧数の列で並べかえられるようにする
*/
add_filter( 'manage_edit-post_sortable_columns', function ( $columns ) {
$columns['page_view_cnt'] = 'page_view_cnt';
return $columns;
} );
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() && $query->is_main_query() && 'page_view_cnt' === $query->get( 'orderby' ) ) {
$query->set( 'meta_key', 'page_view_cnt' );
$query->set( 'orderby', 'meta_value_num' );
}
} );


