For a custom 'Most popular posts' widget, I created a function that creates/updates a post meta to save the number of posts views and I included this function in the single.php template.

It works just fine till I installed WP Super Cache, the number of views stay unchanged.

How can I use this function with the WP Super Cache activated?

This is the function included in the single.php:

function save_views($postID){
  $metakey = 'postsViews';
  $views = get_post_meta($postID,$metakey,true);
  $count = (empty($views) ? 0 : $views);
  • could you brief how you invoke the save_views method in your functions.php file? Jul 5, 2017 at 9:17
  • 1. it is a bad idea to do statistics on the same server as the site. 2. obviously you can not do it this way if the server is not invoked. Jul 5, 2017 at 9:37
  • @MariaDanielDeepak I invoke it on the single.php template Jul 5, 2017 at 10:02
  • 1
    @Elidrissi simo Yeap, I got that. But on which hook? Jul 5, 2017 at 11:58
  • 1
    @MariaDanielDeepak I saw read ajax requests done on each page load (some social sharing plugin) bring down a site. granted you might be able to have it working for a long time until you start having good traffic, but that is exactly when you do not want to start restructuring your site :) Jul 6, 2017 at 4:25

1 Answer 1


When using WP Super Cache, the plugin generates static HTML files for your templates, which means that any PHP code you're running will only ever run when the cached page is generated or regenerated.

So if you need to trigger PHP code on every page load from behind a cache, you'll need to use AJAX.

So for your use case you'll need two functions added to your functions file. Firstly you'll need to add the Javascript that makes the AJAX request to the footer of all of your posts. This will do that:

function my_count_views_script() {
    if ( is_single() ) :
                url:     '<?php echo admin_url( 'admin-ajax.php' ); ?>',
                action:  'my_count_views',
                post_id: <?php the_ID(); ?>
add_action( 'wp_footer', 'my_count_views_script' );

This sends a request to the admin-ajax.php file with the post_id of the post being viewed and the action we want to perform with it.

To count this view, you need to tell admin-ajax.php what code to run when it received a request with the my_count_views action. You do this by hooking onto wp_ajax_my_count_views (to handle it for logged in users) and wp_ajax_nopriv_my_count_views for logged out users:

function my_count_views() {
    if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
        $post_id = intval( $_POST['post_id'] );
        $views = intval( get_post_meta( $post_id, 'postsViews', true ) ) ?: 0;
        $views += 1;

        update_post_meta( $post_id, 'postsViews', $views );

add_action( 'wp_ajax_my_count_views', 'my_count_views' );
add_action( 'wp_ajax_nopriv_my_count_views', 'my_count_views' );
  • 1
    I have suggested couple of edits to improve security and also to keep JS isolated from PHP for easier maintenance. Jul 5, 2017 at 11:57
  • You basically remove most of the advantages of using caching in the first place.... might as well just not use the caching at all Jul 5, 2017 at 12:46
  • 1
    How is that remotely true? Most of the advantages of using a cache removed? This doesn't remove any of the advantages, it's just a tiny script quietly pops off a request in the background, and doesn't interfere with the performance advantages of a cache at all. Jul 5, 2017 at 15:05
  • 1
    @JacobPeattie, each ajax request will do in this case two DB reads (options and post data) which assuming you do not have any complex widget or shortcode on the post page is exactly the number of requests that will be done when generating the HTML Assuming some complex HTML generation, you might end up with x10 performance improvement instead of x1000 you expect to get when using a cache, and I am being generous here as there is also the overhead of server handling of the request and booting wordpress, and who knows what kind of shenanigans other plugin do on startup. Jul 6, 2017 at 4:33
  • 1
    .... one of the things that ajax requests suck in, is that they run under admin context which means they load all that is required to handle admin request, so the minimum here is not to use the ajax end point, but instead define a json route and use it instead Jul 6, 2017 at 4:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.