Change post category based on latest posts views

I have a custom field called post_views_count which stores the views of each post on my blog. I would like to use these views to decide which category the posts belong. Here is what I would like to happen:

  1. Put the latest 50 posts into groups of 10.
  2. Find which post in each group has the highest views and move them to the large category.
  3. Find the average of the remaining 9 posts in each group.
  4. Posts which are below the average of each group are moved to the small category and posts above the average are moved to the medium category.

This should result in 1 large post, 4 or 5 medium and 4 or 5 small posts per group. This process would run on a cron every hour to refresh the categories as well as running each time a new post is made. When a post leaves the latest 50 it just remains the category it was last assigned.

I’ve looked around for similar solutions and I’m not able to find much. Any help would be much appreciated.

1 Answer
1

I took the freedom to ignore step #1 and step #3, as they seem being part of your primary approach to achieve your goal and not being your goal itself. I believe you can achieve your goal in a simpler way.

function assign_last_posts_cat_by_views( $posts_number = 50, $delete_last_posts_transient = true ) {
    if ( true === $delete_last_posts_transient ) {
        delete_transient( 'last_posts' );
    }

    if ( ! $posts = get_transient( 'last_posts' ) ) {
        $args = array(
            'numberposts' => $posts_number
        );

        $posts = get_posts( $args ); // Gets your posts...

        set_transient( 'last_posts', $posts, 60*60*24 ); // Caches the result...
    }

    $post_views = array();

    foreach ( $posts as $post ) {
        $post_views[ $post->ID ] = get_post_meta( $post->ID, 'post_views_count', true ); // Gets each post views count...
    }

    arsort( $post_views, SORT_NUMERIC ); // Sorts views in desc order...

    $post_number = 0;

    foreach ( $post_views as $post_id => $views ) {
        if ( $post_number < 5 ) {
            $term_slug = 'large';

        } elseif ( $post_number < 30 ) {
            $term_slug = 'medium';

        } else {
            $term_slug = 'small';
        }

        $term = get_term_by( 'slug', $term_slug, 'category' ); // Gets term and caches it...

        wp_set_post_terms( $post_id, array( $term->term_id ), 'category' ); // Programatically assignes the category to the post...

        $post_number++;
    }
}

Now, as CRON job, to refresh the categories of your last posts every hour without running a new post query, you can do something like this…

add_action( 'hourly_process', 'assign_last_posts_cat_by_views', 10, 2 );
wp_schedule_event( time(), 'hourly', 'hourly_process', array( 50, false ) );

And to run the process when a post is saved…

add_action( 'save_post', 'assign_last_posts_cat_by_views' );

Leave a Comment