Display custom content on posts page
Published: – Leave a comment
Whenever you set a page as posts page, it automatically lists all posts. But how to add custom content above or below this post list?
For the posts page, the theme uses either the home.php
or alternatively the index.php
to display its content. And usually, these files only contain a basic template with a posts loop:
<?php
/**
* The main template file.
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
*
* @link https://codex.wordpress.org/Template_Hierarchy
*/
get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<?php
if ( have_posts() ) :
/* Start the Loop */
while ( have_posts() ) :
the_post();
/*
* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'template-parts/content', get_post_format() );
endwhile;
the_posts_navigation();
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
</main><!-- #main -->
<?php rh_primary_bottom(); ?>
</div><!-- #primary -->
<?php
get_sidebar();
get_footer();
Code language: PHP (php)
So there is no output for the content of the actual posts page.
Get home content
To get data for this page, you need to gather it manually via get_post
and setup_postdata
. To get the loop working after that, you also need to make sure to rewind the posts afterwards:
$page_for_posts_id = get_option( 'page_for_posts' );
if ( $page_for_posts_id ) {
// if $post is not explicitly set, the home content won't be displayed
// if there are no blog posts
global $post;
$actual_post = $post;
$home_page = get_post( $page_for_posts_id );
$post = $home_page;
setup_postdata( $home_page );
the_content();
rewind_posts();
$post = $actual_post;
}
Code language: PHP (php)
Also, if there is no post available, the content of the home page wouldn’t be displayed if the global $post
variable is empty. Thus, we need to override this variable first and restore it after displaying the content of the home page.
Putting it together
The complete home.php
could then look like this:
<?php
/**
* The home template file.
*
* @link https://codex.wordpress.org/Template_Hierarchy
*/
get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<?php
$page_for_posts_id = get_option( 'page_for_posts' );
if ( $page_for_posts_id ) {
// if $post is not explicitly set, the home content won't be displayed
// if there are no blog posts
global $post;
$actual_post = $post;
$home_page = get_post( $page_for_posts_id );
$post = $home_page;
setup_postdata( $home_page );
the_content();
rewind_posts();
$post = $actual_post;
}
if ( have_posts() ) :
/* Start the Loop */
while ( have_posts() ) :
the_post();
/*
* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'template-parts/content', get_post_format() );
endwhile;
the_posts_navigation();
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
</main><!-- #main -->
<?php rh_primary_bottom(); ?>
</div><!-- #primary -->
<?php
get_sidebar();
get_footer();
Code language: PHP (php)
As you can see, here we add the content of the home page before the loop. But you are free to add the code below the loop if you want the content to show up there.