I have a client who's site will be making heavy use of custom post types to configure their site. But I'm between a rock and a hard place for their requested home page.

In reality, the home page will be a stack of specific "pages" within WordPress. Basically, there will be pages for: Intro, Blog, About Us, Portfolio, and Contact Us. They'll all be stacked on top of one another so you can scroll from one page to another.

My first instinct was to just use a page (called Home) and embed a shortcode that accepts page slugs and outputs the proper order (i.e. [pageOrder]intro, blog, about-us, portfolio, contact-us[/pageOrder]). The page would use a custom page template to lay things out, control the loop, and add navigation to the left side of the page. But that all seems klunky.

My ideal solution would be to create a custom post type (called Stack) that allows the end user to position the pages with drag-drop and have the CPT take care of layout and navigation and such.

The problem with my ideal solution is settings. WordPress allows you to select a page for the default home page of the site. But it's tied to a post type of page, and I'm not sure where to hook in to modify that so that users could also select a Stack as the default home page.

So, where do I hook in to in order to add a CPT to the dropdown of available pages for the default home page?


Thanks to @toscho for the useful answer, but it felt a bit hackish to me, so I poked around a bit and figured out I could add a filter instead:

function wpa18013_add_pages_to_dropdown( $pages, $r ){
    if('page_on_front' == $r['name']){
        $args = array(
            'post_type' => 'stack'
        $stacks = get_posts($args);
        $pages = array_merge($pages, $stacks);

    return $pages;
add_filter( 'get_pages', 'wpa18013_add_pages_to_dropdown', 10, 2 );


After adding the above code I was, indeed, able to use a custom post type as the home page, but WordPress would redirect the permalinks because it wasn't a "page" post type. So http://localhost/test would redirect to http://localhost/test/stacks/home-stack, which wasn't what I wanted.

Adding this action, though, fixed that and queries my custom post type along with pages for the home page:

function enable_front_page_stacks( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'stack' );
add_action( 'pre_get_posts', 'enable_front_page_stacks' );
  • I played with such a filter too, but it has to be restricted to the front page query. And then I was beaten by some strange behavior/bugs: I got just 404s. Anyway +1. :)
    – fuxia
    May 24 '11 at 1:49
  • Good catch. The extra conditional inside the function (make sure post_type isn't already set and that page_id isn't 0) prevents all the 404s. I can now run queries for all of my custom posts, all of my posts, and all of my pages without any interference.
    – EAMann
    May 24 '11 at 4:39
  • @EAmann Thanks for the code! It works as it should, although it changes the title of the frontpage to Title of Post | Homepage name, can this be changed to just be the Homepage name, in someway?
    – INT
    Jul 11 '12 at 0:38
  • This doesn't work at all ... server warnings/errors: Missing argument 2 for wpa18013_add_pages_to_dropdown() and Undefined variable: r
    – Dameer
    Oct 22 '13 at 11:16
  • @EAMann I get errors on this. "Undefined index post_type" on the front page if the setting is set to "Your latest posts" and on other pages I get additional errors of "Undefined index: name"
    – christian
    May 20 '20 at 20:19

Maybe so? Refined version of my earlier solution.

add_filter( 'wp_dropdown_pages', 'add_cpt_to_front_page_dropdown', 10, 1 );

 * Adds CPTs to the list of available pages for a static front page.
 * @param  string $select Existing select list.
 * @return string
function add_cpt_to_front_page_dropdown( $select )
    if ( FALSE === strpos( $select, '<select name="page_on_front"' ) )
        return $select;

    $cpt_posts = get_posts(
            'post_type'      => 'YOUR_POST_TYPE'
        ,   'nopaging'       => TRUE
        ,   'numberposts'    => -1
        ,   'order'          => 'ASC'
        ,   'orderby'        => 'title'
        ,   'posts_per_page' => -1

    if ( ! $cpt_posts ) // no posts found.
        return $select;

    $current = get_option( 'page_on_front', 0 );

    $options = walk_page_dropdown_tree(
    ,   0
    ,    array(
            'depth'                 => 0
         ,  'child_of'              => 0
         ,  'selected'              => $current
         ,  'echo'                  => 0
         ,  'name'                  => 'page_on_front'
         ,  'id'                    => ''
         ,  'show_option_none'      => ''
         ,  'show_option_no_change' => ''
         ,  'option_none_value'     => ''

    return str_replace( '</select>', $options . '</select>', $select );
  • This is only to select the custom post type, but that doesn't make it display that custom post type as front page? or am I missing something? May 23 '11 at 18:23
  • @Hameedullah - Once you select it, WordPress updates an option that marks which page is supposed to be used for the front page. Then, when a user visits the front page, WordPress reads the same option back from the database.
    – EAMann
    May 23 '11 at 18:49
  • @Hameedullah Khan You are right. This worked before 3.1, now I’m redirected to the permalink of the post – and I get a 404. Strange. I wish I had time for this. :(
    – fuxia
    May 23 '11 at 20:06

Why not just create a front-page.php template file, that uses either a normal query/Loop, or (if a custom Theme option is set to display the CPT on the Front Page), outputs a custom query/Loop, based on the CPT?

The issue there is that you would have to create a separate Theme option to control the Front Page output, while at the same time instructing users to set Front Page to static page.

To make things easier, you could hook your Theme option into settings-reading, using the "Reading" option group in your call to register_setting via the Settings API, so that it displays with the existing Front-Page options.

  • I do like simple solutions and Chip I think your's is best. Wordpress allows for custom templates for the front page codex.wordpress.org/Template_Hierarchy#Home_Page_display and then one can do whatever one likes inside that.
    – anmari
    Oct 12 '11 at 10:12
  • This is the most maintainable and straightforward solution. The front-page.php is selected automatically because is part of the wordpress template hierarchy. No need to remember why this is happening (or need to mark it down for the next person).
    – Odys
    Nov 2 '14 at 14:25

I think something may have changed since EAMann wrote his update in 2011, and the wpa18013_add_pages_to_dropdown() function he supplies no longer works. As mentioned in a comment by Dameer, this function currently (December 2013) throws an error "Missing argument 2 for wpa18013_add_pages_to_dropdown()"

The solution, for me anyway, was to rewrite the function without that second parameter, or the check for its contents. The full block of code then becomes:

function add_unbox_tabs_to_dropdown( $pages ){
    $args = array(
        'post_type' => 'unbox_tabs'
    $items = get_posts($args);
    $pages = array_merge($pages, $items);

    return $pages;
add_filter( 'get_pages', 'add_unbox_tabs_to_dropdown' );

function enable_front_page_unbox_tabs( $query ){
    if('' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'])
        $query->query_vars['post_type'] = array( 'page', 'unbox_tabs' );
add_action( 'pre_get_posts', 'enable_front_page_unbox_tabs' );

Please note that in the above example, the custom post type I'm adding is "unbox_tabs" rather than "stack".


I'm using this technique to include a template from a plugin. So, @ChipBennett's solution doesn't apply.

To add the CPT's ( 'hierarchical' => 'false' ) from the plugin in the list of Static Pages, I modified @EAMann's solution as follows:

add_action( 'admin_head-options-reading.php', 'wpse_18013_modify_front_pages_dropdown' );
add_action( 'pre_get_posts', 'wpse_18013_enable_front_page_stacks' );

function wpse_18013_modify_front_pages_dropdown()
    // Filtering /wp-includes/post-templates.php#L780
    add_filter( 'get_pages', 'wpse_18013_add_cpt_to_pages_on_front' );

function wpse_18013_add_cpt_to_pages_on_front( $r )
    $args = array(
        'post_type' => 'stack'
    $stacks = get_posts( $args );
    $r = array_merge( $r, $stacks );

    return $r;

function wpse_18013_enable_front_page_stacks( $query )
    if( '' == $query->query_vars['post_type'] && 0 != $query->query_vars['page_id'] )
        $query->query_vars['post_type'] = array( 'page', 'stack' );

Core reference v3.4.2:
slight difference of line numbers in 3.5 RC3, but code remains the same

 * wp-admin/options-reading.php#L96
 * Happens inside a <li><label>-</label></li>
    wp_dropdown_pages( array( 
                'name' => 'page_on_front'
            ,   'echo' => 0
            ,   'show_option_none' => __( '&mdash; Select &mdash;' )
            ,   'option_none_value' => '0'
            ,   'selected' => get_option( 'page_on_front' ) 

  * wp-includes/post-template.php#L768
function wp_dropdown_pages($args = '') {
    $defaults = array( /* defaults array */ );    
    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );  
    $pages = get_pages( $r );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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