I am working on a webinar plugin that uses a custom post type to display the webinar pages. Those pages could be register, thank you, countdown, live etc. depending on the visitors registration status and the current webinar status.

The plugin uses the template_include action to render content based on the current post status and the visitors status (if they are registered or not).

The plugin lets users choose a custom page for one of those webinar pages, like a custom registration page or a custom thank you page. It shows the user a list of their WordPress pages and lets them choose one, then it saves the post_id in wp_post_meta.

In template_include I'm getting the $custom_page_id from wp_post_meta and if it is set, I redirect the visitor to that page in template_include using something like this:

$redirect_url = get_permalink($custom_page_id);

So the visitor accesses my custom post url:


And is then redirected to:


What I really want to do is render the entire contents of $custom_page_id without redirecting and ideally pass in some meta data like the original post ID.

Is there any way I can render the full contents of $custom_page_id (including theme header & footer) without having to redirect so the visitor stays on https://example.com/my-post-type/mypost but sees exactly the same content as if they had redirected?

  • if you want to display the content on another URL, it's better to make URL rewriting rather than having same content on 2 URL : wordpress.stackexchange.com/questions/352189/…
    – Kaperto
    Commented Nov 15, 2019 at 12:07
  • The problem is that it depends on the settings of the custom post, i.e. some posts might have the setting enabled and others won't and then the custom post they link to might be different so I'm not sure that's a good fit? Commented Nov 15, 2019 at 12:16
  • I am not sure to understand what you want to create. edit your question to give more details about what the CPT is and what users do with that object.
    – Kaperto
    Commented Nov 15, 2019 at 12:29
  • I've edited the question to give more detail, I hope that's clearer Commented Nov 15, 2019 at 12:44
  • Would it be possible to post all of your code so we can see where you are using template_include? I think I have a grasp on what you need but would like to see your code first.
    – Tom
    Commented Nov 19, 2019 at 12:40

2 Answers 2


This was a bit tricky to solve your problem. the template_include filter executed after the main query processed the current request. If you can filter the current request (query_vars) and update it accordingly then WordPress will display any post/page you wanted to... Simply filter the query_vars with the request filter. Check the following snippet. But doing this might have a bad effect on SEO.

add_filter( 'request', function( $query_vars ) {
    if( is_admin() ) return $query_vars;
    $_post = null;
    // find the queried post
    if( isset( $query_vars['post_type'], $query_vars['your-post-type'] ) && $query_vars['post_type'] == 'your-post-type' ) {
        // $query_vars['your-post-type'] will contains the post slug
        $_post = get_page_by_path( $query_vars['your-post-type'], OBJECT, $query_vars['post_type'] );
    } else if( isset( $query_vars['p'] ) ) {
        $_post = get_post( $query_vars['p'] );
        if( $_post != 'your-post-type' ) $_post = null;
    if( $_post ) { // post found
        // get the redirect to page id
        $custom_page_id = get_post_meta( $_post->ID, 'custom_page_id', true );
        $custom_page = get_post( $custom_page_id );
        if( $custom_page ) { // valid page/post found.
            // set the query vars to display the page/post
            $query_vars[$custom_page->post_type] = $custom_page->post_name;
            $query_vars['name'] = $custom_page->post_name;
            $query_vars['post_type'] = $custom_page->post_type;
    return $query_vars;
}, 10 );
  • 1
    This looks like what I need! Indeed the execution order was causing me problems. Commented Nov 25, 2019 at 11:36

The idea of template_include is to intercept the normal template procedure and replace the template with another one based on some conditions. What you are doing now is to redirect to another url which would, through the normal template procedure, produce the template you want.

You can get your desired outcome by simply let template_include do what it is meant for. Since I don't know exactly how you have stored stuff I can't give you precise code, but it would look like this:

add_filter ('template_include','wpse352621_custom_template',10);

function wpse352621_custom_template ($template) {
  if ('webinar' == get_post_type()) { // assuming this is the name of your cpt
    // now, with $custom_page_id, you must not retrieve the url, but the template.
    // you have asked the user which template he wants and stored it somewhere,
    // presumably as user data (*)
    $user_template = $current_user->user_template // assuming this is where you stored it
    // now, just to be sure check if that template exists, then assign it
    $template_path = path.to.plugin.or.theme.directory . $user_template;
    if (file_exists ($template_path)) $template = $template_path;
  return $template;

(*) That would be the case if every user of the site can choose a template of his liking at this point. If you mean the admin can choose, you could store it as metadata to the post. Or you could even have a separate table somewhere in your plugin relating $custom_page_id's to templates. That does not fundamentally change what you need to do.

  • Thanks! But wouldn't this simply render the current $post with a different template? I'd also need to replace the $post->ID with $custom_page_id Commented Nov 25, 2019 at 11:33
  • Yes, that's what it does. I assumed $custom_page_id is a proxy for a template that you want to use on posts that have it as a meta value.
    – cjbj
    Commented Nov 25, 2019 at 13: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.