Post view count

Hi,

This forum managed to count the post view, how does this work ? Is there a repo or something ? Does this ofurm uses wordpress also ? Thanks :slight_smile:

Here it is: frontity/response-utils.ts at dev · frontity/frontity · GitHub

Its not documented but its there.

Awesome, thanks :+1:

I will take a look, but in the meantime I’ve tried this Find popular posts with the WordPress REST API | by Ben Zumdahl | Fiat Insight | Medium

It almost work, with a bit of modifications on wp side, I’m able to retrieve the post meta in the state, and add +1 to it when I use the url provided with Postman (/wp-json/base/views/postid) but it does not work when I use this link in Frontity, any idea ? thanks again

useEffect(() => {
  actions.source.fetch(`/base/views/${postId}`);
}, [])

Find a solution, might not be the best but it works

const viewHandler = {
    name: "viewHandler",
    priority: 1,
    pattern: "/base/views/:id/",
    func: async ({ state, link, params, libraries,type }) => {
      // first need convert object to int
      let id = parseInt(params.id);
      const post = await libraries.source.api.get({
        endpoint: `/base/views/${id}`,
        params: {
          page: id,
        },
      });

    },
  
};

export default viewHandler;

in my post.js

    actions.source.fetch(`/base/views`);

Could you explain in more detail how this solution works? I am unable to implement

Hi, Iv’e added this piece of code on a plugin ( can be done in functions.php also )

add_action( 'rest_api_init', function () {
  register_rest_route( 'base', '/views/(?P<id>\d+)', array(
    'methods' => 'GET',
    'callback' => 'post_view_counter_function',
  ));
});function post_view_counter_function( WP_REST_Request $request ) {
  $post_id = $request['id'];if ( FALSE === get_post_status( $post_id ) ) {
    return new WP_Error( 'error_no_post', 'Not a post id', array( 'status' => 404 ) );
  } else {
    $current_views = get_post_meta( $post_id, 'views', true );
    $views = $current_views + 1;
    update_post_meta( $post_id, 'views', $views );
    return $views;
  }
}
// Register post_view_count meta data on REST
$meta_args = array( 
    'type'                => 'number',
    'single'             => true,
    'show_in_rest' => true,
);
register_meta( 'post', 'views', $meta_args );

then everytime you hit this url with the id of the post on last it will add +1 on the new post meta “views” .
So to get it working you need to add this piece of code on Wp, then in frontity add the handler above and then in a useEffect inside your post file ( or wherever you want to count the views) add the actions.source.fetch from above . that means that everytime you load the post page the useEffect will trigger the handler with the post Id then the handler will send to Wp the corresponding ID, so Wp can add +1 to the correct post meta. I’ve found that this method is quit simple and does not require any authentification

Also i’ve set a “view monitor” on localstorage, to only send request on first views, and if the page has been seen localStorage knows it and won’t send another request. Because without it a request is send on every request, even on refresh

Thanks for your reply!
But I’m a newbie and unfortunately it still doesn’t work for me. Maybe I’m doing something wrong…

Do you have a repo or something ?

There are already a lot of files and structures in my project) I don’t even know how to place it in repo correctly.

But I will try to describe my actions step by step, please help if it’s not difficult for you!

First I add the code you sent to function.php of my website theme.

After I create a Handler with the code you wrote

and import it into index.js

After I go to my post.js and add actions

image

But as a result, state.source.data in /base/views/ is empty and error

image

Not sure why you want to do this manually. Maybe I am missing something. This data is already available in the WP api. Please check my comment from above. Basically any request to a postType endpoint will have the total entries in the response headers. Also frontity already have functions that will give you those values based on the headers. frontity/response-utils.ts at dev · frontity/frontity · GitHub

Sorry, but I don’t understand how to use it and I don’t know how to get the number of page views by users from this

Try to check the tsx documentation. Here is what it says

/**
 * Get the total number of items in an archive or taxonomy response from the
 * REST API. The number is extracted from the "X-WP-Total" header.
 *
 * Official WordPress docs:
 * https://developer.wordpress.org/rest-api/using-the-rest-api/pagination/.
 *
 * @param response - The response object obtained by using `fetch()` on a REST
 * API URL.
 * @param valueIfHeaderMissing - The default value if the header is missing.
 * Defaults to 0.
 *
 * @returns The number of items in that archive/taxonomy.
 */

You can also see how they are using it in the actual handlers coming with wp-source. frontity/postTypeArchive.ts at dev · frontity/frontity · GitHub

Hopefully that helps.

It does not change anything, I still absolutely do not understand what to do with it all and how to use it. I understand that you are a professional and everything is clear to you, but I am self-taught and did a project according to the tutorial

hey @calore912, I am also self taught, it just takes some experience with Frontity.

I can take some time to make an example for you so you can better understand how it works. Do you need to know the total for pages or some other postType. Can you share the endpoint of the post type you are trying to find the total pages?

I am trying to count and display the number of views. First for a simple post, and then I think the mechanism will become clear to me and I will be able to display views for pages and other types of posts).

I will be very grateful if you can help me!

Hi, i’m also a self-taught, just practice and it will be clear :slight_smile:

SO for my solution I will start from the beginning:

The idea is to add a newpost meta in Wordpress so that frontity can tell Wordpress that this post has been seen, and in return on each post Wp will send the post meta and thus the view count.

Step 1 : Add the “views” post meta

add_action( 'rest_api_init', function () {
  register_rest_route( 'base', '/views/(?P<id>\d+)', array(
    'methods' => 'GET',
    'callback' => 'post_view_counter_function',
  ));
});function post_view_counter_function( WP_REST_Request $request ) {
  $post_id = $request['id'];if ( FALSE === get_post_status( $post_id ) ) {
    return new WP_Error( 'error_no_post', 'Not a post id', array( 'status' => 404 ) );
  } else {
    $current_views = get_post_meta( $post_id, 'views', true );
    $views = $current_views + 1;
    update_post_meta( $post_id, 'views', $views );
    return $views;
  }
}
// Register post_view_count meta data on REST
$meta_args = array( 
    'type'                => 'number',
    'single'             => true,
    'show_in_rest' => true,
);
register_meta( 'post', 'views', $meta_args );

This PHP code ( add it in functions.php or even better in a plugin) will add a new “view” field in the post meta and display it in the REST API

Step 2 : Add an handler so that Frontity knows where to tell Wp it has one more views

const viewHandler = {
    name: "viewHandler",
    priority: 1,
    pattern: "/base/views/:id/",
    func: async ({ state, link, params, libraries,type }) => {
      // first need convert object to int
      let id = parseInt(params.id);
      const post = await libraries.source.api.get({
        endpoint: `/base/views/${id}`,
        params: {
          page: id,
        },
      });

    },
  
};

export default viewHandler;

Now Frotntiy knows which URL to use when we will call this handler

Step 3 : tell Frontity to reach the URL in the handler so that Wp can +1 to the correct post meta “views”

  useEffect(() => {
 
      actions.source.fetch(`/base/views/${postId}`);
   
  }, [])

You need to extract the post ID in a variable, mine was “postId”
If you manage to get it working I can show you how I managed to keep track of which post has been seen to avoid adding +1 on reload or return on that post

If that works correctly you will see in your post data a new line under meta → views

example if I do console.log(postData) -which is a variable that contains every data of that specific post - somewhere in that variable i get this in the response :

postcount

Which means that I can do const postCount = state.source.post[id].meta.views, which will return 18 in that case

But this solutions works great for post count, @ni.bonev solutions might be better and I will be curious to see it

Thank you very much for your help! I used your solution in combination with local storage

Yeah the solution I suggested is just running out of the box. Wordpress returns a header with the postcount so you dont need your own endpoint and calculating it yourself.
Screenshot 2022-12-19 at 10.31.35

You can either grab that yourself or use the frontity function i shared above to make your life easier.