Displaying WordPress Posts' JetPack Statistics Using stats_get_csv()


Here's a quick way to display how many times a WordPress post has been read.

For this, you will need:

  1. A blog running WordPress.
  2. The JetPack plugin installed.
  3. The ability to edit your themes.

Here's the snippet of code I'm using to add "This post has been read 12,345 times". I'll explain how it works in a bit more detail.

if( function_exists( 'stats_get_csv' ) ) {
     $stats_query = "page_stats_for_" . get_the_ID();

     if ( false === ( $special_query_results = get_transient( $stats_query ) ) ) {
       $stat_options = "post_id=".get_the_ID()."&days=-1";
       $post_stats = stats_get_csv( 'postviews', $stat_options );
       $special_query_results = $post_stats[0]["views"];
       set_transient( $stats_query, $special_query_results, 6 * HOUR_IN_SECONDS );
     }

     if (($special_query_results != null) && ($special_query_results > 100))
     {
       echo "This post has been read " . number_format($special_query_results) . " times.";
     }
}

Let's start from the inside out...

Get Your Stats

The call to stats_get_csv() is a wrapper for https://stats.wordpress.com/csv.php.

If you want to see the stats for the post with ID 123 you'd need to call:

https://stats.wordpress.com/csv.php? api_key=abcxyz& blog_uri=example.com& post_id=123& days=-1& table=postviews& format=txt

The days parameter can be set to whatever you like - so 7 for the last week. When set to -1, it will return data back to the beginning of time.

To call this in a PHP function, we use:

$post_stats = stats_get_csv( 'postviews', "post_id=123&days=-1" );

This brings back an array, so to access the number of views:

$views = $post_stats[0]["views"];

So, putting it all together, we get:

$stat_options = "post_id=".get_the_ID()."&days=-1";
$post_stats = stats_get_csv( 'postviews', $stat_options );
$views = $post_stats[0]["views"];

Caching

Once we've got the stats, it's sensible to cache them. WordPress recommends a minimum cache of 180 seconds. Given that each call can add around 3 seconds of latency, I think it's wise to cache for several hours.

We'll cache this with the Transients API - a lightweight way to store data semi-permanently.

To store some data for six hours, we use:

set_transient( 'reference_to_data', $data, 6 * HOUR_IN_SECONDS );

We're going to want to store a different result for every post:

set_transient( "page_stats_for_" . get_the_ID(), $views, 6 * HOUR_IN_SECONDS );

To get the data about a specific page, we call

get_transient( "page_stats_for_123" );

Put it all together, and you get:

if( function_exists( 'stats_get_csv' ) ) {
     $stats_query = "page_stats_for_" . get_the_ID();

     if ( false === ( $special_query_results = get_transient( $stats_query ) ) ) {
       $stat_options = "post_id=".get_the_ID()."&days=-1";
       $post_stats = stats_get_csv( 'postviews', $stat_options );
       $special_query_results = $post_stats[0]["views"];
       set_transient( $stats_query, $special_query_results, 6 * HOUR_IN_SECONDS );
     }

     if (($special_query_results != null) && ($special_query_results > 100))
     {
       echo "This post has been read " . number_format($special_query_results) . " times.";
     }
}

This snippet can be placed in your theme wherever you want a page view to appear.


Share this post on…

  • Mastodon
  • Facebook
  • LinkedIn
  • BlueSky
  • Threads
  • Reddit
  • HackerNews
  • Lobsters
  • WhatsApp
  • Telegram

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.

Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">