I have this issue where I need a CPT to have several layout options and use templates. Originally, WP does not support templates for custom posts, however I know its possible to do it manually via Meta boxes custom data.

This is the snippet of code I have in my functions, which enables possibility to choose template and save it. It works fine - adds data to db and saves/updates the template. My issue is in the last part, where I try to redirect the theme to correct template and some-why it does not work.

 // --------Add actions
 add_action('add_meta_boxes', 'custom_template_add_custom_box');

 /* Do something with the data entered */
 add_action('save_post', 'custom_template_save_postdata');

 // --------Add functions
 /* Adds a box to the main column on the Post and Page edit screens */
 function custom_template_add_custom_box() {
     add_meta_box( 'custom-post-type-choice', 'Choose custom template', 'custom_template_inner_box', 'campaign', 'side' );

 /* Prints the box content */
 function custom_template_inner_box( $post ) {

     // Use nonce for verification
     wp_nonce_field( plugin_basename(__FILE__), 'custom_template_noncename' );

     if ( 0 != count( get_page_templates() ) ) {
         $page_template = get_post_meta($post->ID, '_wp_page_template', TRUE); ?>
     <p><strong><?php _e('Template') ?></strong></p>
     <label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label>
     <select name="page_template" id="page_template">
         <option value='default'><?php _e('Default Template'); ?></option>
         <?php page_template_dropdown($page_template); ?>
 <?php }

 /* When the post is saved, saves our custom data */
 function custom_template_save_postdata( $post_id ) {

     // verify this came from the our screen and with proper authorization,
     // because save_post can be triggered at other times

     if ( !isset( $_POST['custom_template_noncename'] ) || !wp_verify_nonce( $_POST['custom_template_noncename'], plugin_basename(__FILE__) ) )
         return $post_id;

     // verify if this is an auto save routine. 
     // If it is our form has not been submitted, so we dont want to do anything
     if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
         return $post_id;

     // Check permissions
     if ( 'page' == $_POST['post_type'] ) {
         if ( !current_user_can( 'edit_page', $post_id ) )
             return $post_id;
     else {
         if ( !current_user_can( 'edit_post', $post_id ) )
             return $post_id;

     // OK, we're authenticated: we need to find and save the data

     $page_template = $_POST['page_template'];

     if ( !empty($page_template) && 'campaign' == get_post_type($post_id) ) {
         $page_templates = get_page_templates();
         if ( 'default' != $page_template && !in_array($page_template, $page_templates) ) {
             if ( $wp_error )
                 return new WP_Error('invalid_page_template', __('The page template is invalid.'));
                 return 0;
         update_post_meta($post_id, '_wp_page_template',  $page_template);

 /* Custom template redirection hook */

 function custom_template_redirect() {
     global $post;

     if ( is_single() && 'campaign' == get_post_type($post) ) {
         $page_template = get_page_template();
 add_action("template_redirect", 'custom_template_redirect');

So how can I 'use' the selected template for that page?

1 Answer 1


I'd recommend using the template_include filter as opposed to template_redirect, as using this hook means that you don't redirect the user but rather just present them with the template that is requierd.

add_filter('template_include', 'my_custom_template_redirect', 99);
function my_custom_template_redirect($template){

    global $post;
    if(is_single() && 'campaign' == get_post_type($post)){
        $page_template = get_page_template();
        $new_template = locate_template( array( 'subfolder/' . $page_template . '.php' ) );
        $template = ($new_template !== '') ? $new_template : $template;

    return $template;

Ovbiously I'm making the assumption that your $page_template variable doesn't have .php on the end, but you can ammend that as required.

I'd recommend you have a read of the documentation related to this hook, and the locate_template function -


In my original answer I forgot to include global $post;. I've now amended the answer to include this line.

  • Weird. Seems like good code, and used exactly as codex suggested, however now I get error "undefined variable: post" .. thoughts? Commented Jan 23, 2015 at 14:15
  • Add global $post to the top of the function. I'll update the answer momentarily.
    – David Gard
    Commented Jan 23, 2015 at 14:55
  • Out of interest, do you have debugging enabled via wp-config.php? I didn't think you'd be noticied of an undefined variable by default.
    – David Gard
    Commented Jan 23, 2015 at 14:55
  • Well, this does not work, as well my file-name is not template name and its located in sub-folder, so applying name of template to php would not even make sense. I declare template within the php file: /* Template Name: name-of-template */ Anyway, this code gives me white page for any page ;/ Commented Jan 26, 2015 at 8:38
  • The white page error should now be corrected, but you are correct that if you place the template in a subfolder that it will not be found. However, could you not simply add the name of the subfolder to the template string? So locate_template( array( 'subfolder/' . $page_template . '.php' ) ), obviously replacing subfolder with the correct folder name. Personally I would recommend putting templates directly into the theme folder though - it's just easier.
    – David Gard
    Commented Jan 26, 2015 at 9:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.