Quick answer: To show trending posts by real view count in Elementor, count views into a post-meta field with a small AJAX counter, then point an Elementor Posts widget at a custom query that orders by that field. Set the widget’s Query ID to popular_posts_filter and it sorts most-viewed first.
How it works
WordPress has no built-in view counter, so this adds a lightweight one: a tiny script pings admin-ajax.php once per visitor (tracked in the browser’s localStorage so refreshes do not inflate the count), and the server stores the running total in a post_views_count meta field. A query filter then tells any Elementor Posts widget to order by that field, and a shortcode lets you display the number anywhere.
The code
Add it as one PHP snippet. It gives you three things: the counter, the Elementor query filter (popular_posts_filter), and a [post_views_count] shortcode.
<?php
// 1. Count a view once per visitor, via a tiny AJAX ping in the footer.
function hmwp_enqueue_view_counter() {
if ( ! is_singular( 'post' ) ) {
return;
}
?>
<script type="text/javascript">
window.addEventListener("load", function () {
const postId = <?php echo (int) get_the_ID(); ?>;
const ajaxUrl = '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>';
if ( ! localStorage.getItem( 'post_viewed_' + postId ) ) {
fetch( ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: new URLSearchParams( { action: 'track_post_views', post_id: postId } )
} ).then( function ( r ) {
if ( r.ok ) {
localStorage.setItem( 'post_viewed_' + postId, 'true' );
}
} );
}
});
</script>
<?php
}
add_action( 'wp_footer', 'hmwp_enqueue_view_counter', 100 );
// 2. Store the incremented count in post meta.
function hmwp_track_post_views() {
if ( isset( $_POST['post_id'] ) ) {
$post_id = absint( $_POST['post_id'] );
$views = (int) get_post_meta( $post_id, 'post_views_count', true );
update_post_meta( $post_id, 'post_views_count', $views + 1 );
}
wp_die();
}
add_action( 'wp_ajax_track_post_views', 'hmwp_track_post_views' );
add_action( 'wp_ajax_nopriv_track_post_views', 'hmwp_track_post_views' );
// 3. An Elementor query filter that orders by the view count.
// Set the Posts widget's "Query ID" to: popular_posts_filter
function hmwp_popular_posts_query( $query ) {
$query->set( 'meta_key', 'post_views_count' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'DESC' );
}
add_action( 'elementor/query/popular_posts_filter', 'hmwp_popular_posts_query' );
// 4. A [post_views_count] shortcode to show the count anywhere.
function hmwp_post_views_shortcode() {
$views = (int) get_post_meta( get_the_ID(), 'post_views_count', true );
return number_format_i18n( $views );
}
add_shortcode( 'post_views_count', 'hmwp_post_views_shortcode' );
How to use it
- Add an Elementor Posts (or Loop Grid) widget.
- Under Query, set the Query ID to
popular_posts_filter. - Publish. The widget now lists posts by most-viewed.
Drop [post_views_count] into any post to show its view total.
Notes and how to undo
- Counts build up over time — a brand-new site shows low numbers until traffic accrues.
- Views are de-duplicated per browser via localStorage, so they approximate unique views rather than raw hits.
- To remove it, delete the snippet. The stored counts remain in the database harmlessly; the widget just needs its Query ID cleared.
