0

How would I display a list of users who have viewed the post you are viewing?

3
  • 1
    You’d have to first record the IDs of users that have viewed the post, but that only works if they’re logged in, then you’d have to query that post-meta from the DB and loop through the array of recorded IDs. Nov 26, 2020 at 17:00
  • I don't 'spose you'd like to start (and finish) me off would you?
    – Pete
    Nov 27, 2020 at 10:33
  • 1
    Sir! I do not believe this is “that kind of establishment”! 🤣 Jokes aside, I can help and cobble together a few snippets. Are you adding this to a theme or do you need to build a plugin? Nov 27, 2020 at 12:12

1 Answer 1

1

Here you go Pete, hope this is the "happy ending" you had in mind... LOL!

First thing we want to do is A) record the IDs of logged in users as post metadata and B) generate a template tag that we can use to display that data somewhere.

Second, we want to drop that template tag into either your single.php or a template-part that displays singular post content.

I've commented throughly throughout the code so you can see what I did and so that I don't have to break it up into chunks here. Just easier for you if you can see the whole block in one place.

The code below was written for inclusion in a theme's/child theme's functions.php file, but if you wanted to you could easily convert it to a plugin.

<?php
// First we run a function in the wp_head or wp_footer where we capture the ID of logged in users and save them to an array in postmeta.
function track_Petes_viewers() {
    //If the viewer isn't logged in, the rest is pointless, so we check this first.
    if( is_user_logged_in() ) :
        global $post;
        //Lets set a nonce.
        $viewers_nonce  = wp_create_nonce( 'viewers_nonce_' . $post->ID );
        //Get the current user's ID.
        $userID         = get_current_user_id();
        //Lets check if this post already has a list of viewers so we can add to it.
        $viewers        = get_post_meta( $post->ID, 'petes_viewers', true );  
        //If this post doesn't already have this meta, lets set up an empty array.
        if( empty( $viewers ) ) :
            $viewers = array();
        endif;
        //Now we add the current user's ID to the array.
        $viewers[]      = $userID;
        //We don't want users being recorded twice, we just need to know if they viewed it, not how may times
        //So we're going to run array_unique() to make sure each ID is only in there once.
        $viewers_list   = array_unique( $viewers );
        //We verify the nonce and if it works, we update_post_meta(), if not, we kill the process.
        if( !wp_verify_nonce( $viewers_nonce, 'viewers_nonce_' . $post->ID ) ) :
            die();
        else :
            //If the postmeta doesn't exist, update_post_meta will create it, so we don't need to also use add_post_meta
            update_post_meta( $post->ID, 'petes_viewers', $viewers_list );
        endif;
    endif;
}
//We're going to drop it in the wp_head, but you can change this to a different hook
add_action( 'wp_head', 'track_Petes_viewers' );

//Now we generate a template tag that we can drop into our single view of posts, wherever you like, to display a list of viewers
function display_Petes_viewers() {
    global $post;
    //Not sure what you're using this for, but let's ONLY show this on posts
    if( get_post_type( $post->ID ) == 'post' ) :
        //We get the post meta for viewers
        $viewers_list   = get_post_meta( $post->ID, 'petes_viewers', true );
        //If there is a record in the DB for this particular post, we'll cycle through the IDs and spit out names
        if( !empty( $viewers_list ) ) :
            //Let's wrap the whole thing in a <ul>
            echo '<ul id="petes_viewers">';
            foreach( $viewers_list as $viewer ) :
                //We user the ID numbers to get the User object
                $viewer_info    = get_userdata( (int)$viewer );
                //ADDED: Let's check if the user still exists.
                if( $viewer_info != false ) :
                    //We pull the display_name from the User object
                    //You can pull additional info using this pattern, like the email, the link to their profile, their first/lastname, etc.
                    $viewer_name    = $viewer_info->display_name;
                    //and now we echo out whatever data we pulled from the user object, format this however you like
                    echo '<li>' . $viewer_name . '</li>';
                endif; 
            endforeach;
            echo '</ul><!--#petes_viewers-->';
        endif;
    endif;
}
?>

You now have a function that is recording the IDs of logged in users as they view posts. You then also have a second function that checks to see if this metadata exists and if it does, it generates a bullet list of display names of the users that HAVE viewed that particular post.

To use this second function you simply drop the following code into whichever theme template you want, ie. single.php.

<?php display_Petes_viewers(); ?>

Now, there's a number of things that could be improved upon... ...like, are we displaying the list of people that viewed the post to the general public? Or are we only displaying it to other logged in users? Or are we only displaying it to administrators or editors?

Second, when I'm logged in and viewing a post for the first time, my display name won't show up (not the first time), do we want to get all fancy and add the current user to the list if they're not already on it?

But those are relatively simple modifications you could make.

Hope this helps and if it does please remember to accept the answer. :-)

14
  • Now, there's a number of things that could be improved upon... ...like, are we displaying the list of people that viewed the post to the general public? Or are we only displaying it to other logged in users? Or are we only displaying it to administrators or editors? - I think that's easy enough to wrap a conditional around the template tag?
    – Pete
    Nov 28, 2020 at 14:01
  • Great help and explanation of this function! I searched high and low and there was nothing like this anywhere.
    – Pete
    Nov 28, 2020 at 14:02
  • 1
    Maybe we should make this a plugin... but we’d have to also make it a widget, add some options like “display to public, logged in only, admins only” etc... maybe some toggled options to configure the display of the list... 🤔 Nov 28, 2020 at 14:10
  • 1
    At first the issue confused me... ...but you mean IF you delete a user after they've viewed a page then in the database the ID is still recorded in the meta data but it can't display their name because they don't exist anymore... ...I can fix that. Ok, I fixed it, the code in the answer is updated, we just check if the user still exists before we try to output their information. Nov 29, 2020 at 4:28
  • 1
    Yes. But you could also just remove that condition entirely and allow it to apply to all post types, be it post, page, custom, etc. Dec 4, 2020 at 11:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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