Random WordPress Post of the Day

Increase user engagement by showcasing a unique post each day on your WordPress site. This PHP snippet ensures that visitors see a different post daily, refreshing at midnight. This approach is ideal for highlighting older content, increasing page views, and keeping your site dynamic without the need for additional plugins. This snippet is compatible with custom post types and the output can be customized to fit any theme or layout.

Originally the code took advantage of the PHP rand()/mt_rand() function not being random when seeded with the same data. I later added transient caching to make the code less resource intensive on the server, while leaving the original post selection method as a fallback incase the transient is cleared early.

				
					<?php
/**
 * Shortcode [potd] to display a random post that is different each day.
 */
add_shortcode( 'potd', 'post_of_the_day' );

/**
 * Get the post of the day
 *
 * @param array $atts (unused)
 *
 * @return string
 */
function post_of_the_day( $atts ) {

	$post_type = 'post'; // CHANGE FOR CUSTOM POST TYPE

	// Transient key changes daily per post type, based on local WP time
	$today_key = 'potd_' . $post_type . '_' . current_time( 'Y_m_d' );

	// Try to fetch cached post ID
	$post_id = get_transient( $today_key );

	// If no cached ID, pick a new random one
	if ( ! $post_id ) {
		$timestamp   = current_time( 'timestamp' );//Get seconds since epoch
		$seed        = floor( $timestamp / DAY_IN_SECONDS );//Convert seconds to days and round down to only show completed days
		$count_posts = (int) wp_count_posts( $post_type )->publish;//Count number of publihed posts of a given post type.

		if ( $count_posts === 0 ) {
			return '<div class="post-of-the-day">No posts found.</div>';
		}

		$count_posts = $count_posts - 1; //remove one since counting from zero
		mt_srand( $seed ); //Seed the random number generator with the days since epoch
		$offset = mt_rand( 0, $count_posts ); //Generate a seeded random number in the range of 0 to the number of posts minus 1

		// Run the query as normal
		$args  = array(
			'post_type'      => array( $post_type ), 
			'posts_per_page' => 1,
			'offset'         => $offset,
		);

		$query = new WP_Query( $args );

		if ( $query->have_posts() ) {
			$query->the_post();
			$post_id = get_the_ID();

			// Calculate seconds until local midnight
			$now      = current_time( 'timestamp' );
			$midnight = strtotime( 'tomorrow', $now );
			$expires  = $midnight - $now;

			// Save chosen post ID until midnight
			set_transient( $today_key, $post_id, $expires );
		}
		wp_reset_postdata();
	}

	// If we now have a valid post ID render it with a normal query
	if ( $post_id ) {
		$query = new WP_Query( array(
			'post_type'      => array( $post_type ),
			'posts_per_page' => 1,
			'p'              => $post_id, // query by post ID
		) );

		if ( $query->have_posts() ) {
			ob_start(); 
			while ( $query->have_posts() ) {
				$query->the_post();
				//now treat it like a regular query return and customize to your theme
				?>
				<div class="post-of-the-day">
					<?php echo esc_html( get_the_title() ); ?>
					<?php echo esc_html( get_the_excerpt() ); ?>
				</div>
				<?php
			}
			wp_reset_postdata();
			return ob_get_clean();
		}
	}

	return '<div class="post-of-the-day">No post available today.</div>';
}
				
			

If this code helped you, or you have any questions on implementation, don’t hesitate to reach out.