Creating A Custom ‘Preview Post’ Page In WordPress

By Neal Grosskopf, Software Engineering Director

Published: October 29, 2014

I ran into a strange issue in a WordPress install that I had highly customized. Previewing posts didn’t work. The trouble stems from the fact that I put WordPress in a sub-folder called /wordpress/ AND that my home page wasn’t actually a WordPress page but my own static page. The other issue is my WordPress post listing page was displayed via AJAX.

The Site’s Configuration

In my wp-config.php file I had set the following for the site:

define('WP_HOME','/');
define('WP_SITEURL','/wordpress');

In my root htaccess file I had the following which pointed to my static home page:

DirectoryIndex home.php

Finally, in this file /wordpress/.htacces I reset the home page back to index.php for WordPress:

DirectoryIndex index.php

Previewing Posts Are Broken!

What ended up happening is the link WordPress used to preview posts went to here – http://www.example.com/?p=2429&preview=true. You may recall that the root page on my site is a static page called home.php so obviously this wasn’t working.
First, I created a new page in WordPress at /news-preview/ and forked the single.php template file. This would serve as my faux-preview post page.
After a Google search I attempted to use this in my root htaccess file but it resulted in an endless loop probably due to some internal WordPress code:

RewriteCond %{QUERY_STRING} p=(.*)&preview=true
RewriteRule (.*) /news-preview/?p=%1&preview=true [R=301,L]

A Solution

Finally I ran across a thread that described how to customize the URL WordPress uses for post preview links. The following code is added to the functions.php file:

add_filter( 'preview_post_link', 'the_preview_fix' );
function the_preview_fix() {
$preview_id = get_the_ID();
return "/news-preview/?custom_preview_id=$preview_id";
}

This code allows me to rewrite the preview post URL whenever WordPress uses it. I opted to point this to a page I controlled.
And then in my /news-preview/ file, I added the following code:

$id = (int)$_GET['custom_preview_id']; $query = new WP_Query(array( 'p' => $id,
'post_type' => 'any')
);
while ( $query->have_posts() ) : $query->the_post();