19

I'd like to use a custom post type archive as a site's front page, so that

 http://the_site.com/

is a custom post type archive displayed according to my archive-{post-type}.php file.

Ideally I would like to alter the query using is_front_page() in my functions.php file. I tried the following, with a page called "Home" as my front page:

 add_filter('pre_get_posts', 'my_get_posts');
 function my_get_posts($query){
     global $wp_the_query;
     if(is_front_page()&&$wp_the_query===$query){
        $query->set('post_type','album');
        $query->set('posts_per_page',-1);
     }
     return $query;
 }

but the front page is returning the content of "Home" and seems to be ignoring the custom query.

What am I doing wrong? Is there a better way, in general, of going about this?

1
  • is_front_page() will not work with pre_get_posts Aug 18, 2014 at 5:05

5 Answers 5

33

After you have set a static page as your home page you can add this to your functions.php and you are good to go. This will call the archive-POSTTYPE.php template correctly as well.

add_action("pre_get_posts", "custom_front_page");
function custom_front_page($wp_query){
    //Ensure this filter isn't applied to the admin area
    if(is_admin()) {
        return;
    }

    if($wp_query->get('page_id') == get_option('page_on_front')):

        $wp_query->set('post_type', 'CUSTOM POST TYPE NAME HERE');
        $wp_query->set('page_id', ''); //Empty

        //Set properties that describe the page to reflect that
        //we aren't really displaying a static page
        $wp_query->is_page = 0;
        $wp_query->is_singular = 0;
        $wp_query->is_post_type_archive = 1;
        $wp_query->is_archive = 1;

    endif;

}
6
  • This function needs if(is_admin()) return; at the very beginning, otherwise it messes with the admin area.
    – brasofilo
    Sep 11, 2013 at 0:01
  • 1
    While this worked for me, my primary and secondary menus disappeared as result.
    – super9
    Apr 19, 2015 at 17:44
  • It's almost correctly. This code is changing all wp_queries, so it should be if ( is_home() ) instead of if ($wp_query->get.....) Jun 10, 2015 at 4:59
  • I'm using the same but on my custom page template instead of frontpage, and it shows no results (as if no custom posts were added). Any thoughts?
    – trainoasis
    Jul 22, 2018 at 7:33
  • 1
    To support pagination: if ( $query->get('paged') ) { $paged = $query->get('paged'); } elseif ( $query->get('page') ) { $paged = $query->get('page'); } else { $paged = 1; } $query->set('paged', $paged); Sep 26, 2019 at 7:58
7

Re-name your CPT archive to home.php

Then use pre_get_posts to alter the home page query so only CPT's display

function wpsites_home_page_cpt_filter($query) {
if ( !is_admin() && $query->is_main_query() && is_home() ) {
$query->set('post_type', array( 'your-cpt' ) );
    }
  }

add_action('pre_get_posts','wpsites_home_page_cpt_filter');

Replace your-cpt with the name of your custom post type.

1
  • 2
    finally, a clear, workable explanation!
    – Jack
    Jun 13, 2015 at 15:56
1

Thanks for the answer ljaas—I was looking to solve this exact problem. In order to get the custom post type archive template to be called I had to add the following conditions:

$wp_query->is_post_type_archive = 1;
$wp_query->is_archive = 1;
2
  • 2
    Hi Eli, welcome to WPSE. "Answers" are meant to answer the initial question (stackexchange sites are not threaded discussion forums). This would be a much better fit for a comment. Jul 18, 2013 at 23:31
  • Thanks for the clarification Johannes. That is what I thought, though I could not figure out how to comment on the answer as there is no 'add comment' feature available. Is this a time-sensitive feature, or am I blind?
    – Eli
    Jul 20, 2013 at 20:09
1

This works better for me overriding both blog posts and static page in Settings > Reading > Front page displays:

<?php
/**
 * Set custom post type archive as front page.
 *
 * @since 1.0.0
 */
function ql_set_as_front_page( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    if ( ql_is_front_page( $query ) ) {
        $query->set( 'page_id', '' );
        $query->is_page = false;
        $query->is_singular = false;
        $query->set( 'post_type', 'MYCPT' );
        $query->is_archive = true;
        $query->is_post_type_archive = true;
    }
}
add_action( 'pre_get_posts', 'ql_set_as_front_page' );

/**
 * Taken from WP_Query::is_front_page and adapted to compare page_on_front with current page ID.
 * 
 * @since 1.0.0
 * 
 * @param object $query The main WP Query.
 */
function ql_is_front_page( $query ) {
    if ( 'posts' == get_option( 'show_on_front') && $query->is_home() )
        return true;
    elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $query->get('page_id') == get_option( 'page_on_front' ) )
        return true;
    else
        return false;
}

I'm using it in conjunction with a template override using the filters front_page_template and home_template to return a custom template.

0

For me it breaks the pagination : either you select the index or a static page as the home page, the pagination links shows up but when clicking on page 2 I get :

  • in case of index page (default) : the 404 page
  • in case of static page : the same results as page 1 : the "paged" argument is then interpreted to show the page type pagination, not the post type list pagination.

I think it needs some rewrite rules to catch the paged argument and pass it correctly.

Anyway, a custom template page should be the solution with some additional rewrite rules.

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.