WordPress でページキャッシュが効いていても閲覧数(PV)を数える:Ajax で数えて管理画面の一覧に出す

広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

概要説明

WP Super Cache などのページキャッシュが効いていると、PHP で数える閲覧数は増えません。見に来た人のブラウザから Ajax で数える functions.php と JavaScript のコード、管理画面の一覧に閲覧数を出して並べかえる方法。公開中の投稿だけ数える守り方も、作業環境で確かめた結果つきで。

WP Super Cache などのページキャッシュを使うと、2 回目からは保存しておいた HTML をそのまま返すので、PHP の処理が動かず、閲覧数を数えられません。そこで、見に来た人のブラウザから Ajax で数えるようにします。

キャッシュするページに閲覧数を出すと、その数字もキャッシュされるので、すぐには増えて見えません。数は正しく数えられていて、キャッシュが作り直されたときに出る数字が変わります。

pv-count.js
/**
 * 記事のページで、閲覧数を 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 を読み込む処理と、数える処理

functions.php
/**
 * 記事のページに、閲覧数を数える 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() で、記事の閲覧数を取り出せます。

テンプレート(single.php など)
<?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 がファイルの更新日時の版で読み込まれた

試しに増やした閲覧数は、元に戻しました。

管理画面の投稿の一覧に閲覧数を出す

functions.php
/**
 * 管理画面の投稿の一覧に、閲覧数の列を足す
 */
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 );
WordPress でページキャッシュが効いていても閲覧数(PV)を数える:Ajax で数えて管理画面の一覧に出す

管理画面の一覧で、記事ごとの閲覧数が見られます。数えたぶんだけ、そのまま増えていきます。

管理画面に IP の制限をしているとき

.htaccess(wp-admin の中)
# 管理画面に 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」です)。

閲覧数の列で並べかえる

functions.php
/**
 * 閲覧数の列で並べかえられるようにする
 */
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' );
	}
} );
WordPress でページキャッシュが効いていても閲覧数(PV)を数える:Ajax で数えて管理画面の一覧に出す

関連機能

  1. WordPress のショートコードの作り方:add_shortcode の基本と、広告・記事のリンクを出す例(echo で上に出る・下書きのタイトルが出る問題も直す)

  2. DBキャッシュ機能を実装 外部データなど任意の情報を一定期間キャッシュさせる

  3. 管理画面ヘッダーにログアウトを追加

サイドバー

よく使うカスタマイズ

最近の記事

Profile

PAGE TOP