Sometimes you may need to create a fake page within WordPress, which doesn’t actually exist. You could make a real page, then add a shortcode into it for addition of dynamic content. But this could confuse the site owners, and it’s just generally a bit messy, particularly if the URL needs to change regularly.

Thankfully Jamie Holding came to the rescue with an incredibly useful little bit of code he posted six years ago. It’s quite old, so I’ve updated it to match modern WordPress coding conventions and dropped out a global variable in favour of a constant (to prevent it doing the same task twice when the filter reruns).

You can see Jamie’s original code here …


add_filter( 'the_posts', 'generate_fake_page', -10 );
 * Create a fake page called "fake"
 * $fake_slug can be modified to match whatever string is required
 * @param   object  $posts  Original posts object
 * @global  object  $wp     The main WordPress object
 * @global  object  $wp     The main WordPress query object
 * @return  object  $posts  Modified posts object
function generate_fake_page( $posts ) {
	global $wp, $wp_query;

	$url_slug = 'fake'; // URL slug of the fake page

	if ( ! defined( 'FAKE_PAGE' ) && ( strtolower( $wp->request ) == $url_slug ) ) {

		// stop interferring with other $posts arrays on this page (only works if the sidebar is rendered *after* the main page)
		define( 'FAKE_PAGE', true );

		// create a fake virtual page
		$post = new stdClass;
		$post->post_author    = 1;
		$post->post_name      = $url_slug;
		$post->guid           = home_url() . '/' . $url_slug;
		$post->post_title     = 'Some page name goes here';
		$post->post_content   = 'Stick some arbitrary text content in here';
		$post->ID             = -999;
		$post->post_type      = 'page';
		$post->post_status    = 'static';
		$post->comment_status = 'closed';
		$post->ping_status    = 'open';
		$post->comment_count  = 0;
		$post->post_date      = current_time( 'mysql' );
		$post->post_date_gmt  = current_time( 'mysql', 1 );
		$posts                = NULL;
		$posts[]              = $post;

		// make wpQuery believe this is a real page too
		$wp_query->is_page             = true;
		$wp_query->is_singular         = true;
		$wp_query->is_home             = false;
		$wp_query->is_archive          = false;
		$wp_query->is_category         = false;
		unset( $wp_query->query[ 'error' ] );
		$wp_query->query_vars[ 'error' ] = '';
		$wp_query->is_404 = false;

	return $posts;