WordPress Front Page vs Home Page and getting post ID outside or after the loop in every possible way

I was recently working on a site that needed to display the featured image of every page in its sidebar.

On regular, static pages or posts, everything works as intended – you can use is_page(), is_single() and get_the_ID() and not worry about anything.

// This works well on static pages or posts,
// displaying the featured image
if ( is_page() || is_single() ) {
    if ( has_post_thumbnail( get_the_ID() ) ) {
        the_post_thumbnail( 'full' );
    }
}

However, on pages that contain the Loop (blog posts page, custom loop pages), things can get a bit complicated. I’ll walk you through a bunch of different solutions you can use to get the post/page ID, depending on the situation.

If you’ve manually set your posts page

You can set your posts page manually via Settings > Reading. If you’ve done that, you’ll find that get_the_ID() or is_page() aren’t working as expected. That means you’ll need to use a conditional tag to detect if you’re on the posts page and if so, use a different method to get the page ID.

One of the things that doesn’t really make sense with WordPress is the naming conventions for the conditional tags for detecting these pages: is_home() and is_front_page().

  • is_home() returns true if the current page is set to posts page;
  • is_front_page() returns true if the current page is set to front page.

So yeah, is_home() = blog posts page, which is what you’ll want to use to detect if the current page is displaying your blog posts.

if ( is_page() || is_single() ) {
    if ( has_post_thumbnail( get_the_ID() ) ) {
        the_post_thumbnail( 'full' );
    }
// This is called on the blog page you've set
} else if ( is_home() ) {
    // do stuff
}

Remember that these tags work only if you have set the pages in Settings > Reading. They do not work if you are displaying blog posts via a custom page template or loop without setting the relevant option – I’ll explain how to deal with these situations later.

Getting the posts page ID

Now that you’ve got the conditionals sorted out, there’s another problem: on posts page, get_the_ID() doesn’t work as intended – it appears to return the ID of the first or last post processed by the Loop, depending on whether it was called before or after the Loop.

Fortunately, there’s get_option() – this is a really useful function that can return anything WordPress has stored in the Options database table – that’s usually stuff from the Settings menu. You can use it to get the ID of the posts page:

// If the current page is a static page or post
if ( is_page() || is_single() ) {
    if ( has_post_thumbnail( get_the_ID() ) ) {
        the_post_thumbnail( 'full' );
    }

// If the current page is your posts page
} else if ( is_home() ) {
    // Get the ID of your posts page
    $id = get_option('page_for_posts');
    // Use the ID to get the post thumbnail or whatever
    if ( has_post_thumbnail( $id ) ) {
        echo get_the_post_thumbnail( $id, 'full' );
    }
}

This solution should work for most of the situations..

Custom template or loop

..however, if you are using a custom template or loop for displaying your posts (for example Thematic’s default Blog template) everything breaks down again: before the Loop, is_page() and get_the_ID() work fine, but after the loop the first function returns nothing and the second returns the ID of the last blog post..

There are two ways to solve this.

The first and simpler option: use global variables and save the post ID in your template before the Loop comes and breaks everything:

// This goes in your template file BEFORE the loop

// Declare global variables - these are accessible from anywhere
// $post is the current Post object variable in WordPress
global $post;
global $my_post_id;
// Save the post ID into the global variable
$my_post_id = $post->ID;

And use this code to get the ID of the post and do stuff with it:

// This can be used basically anywhere, but especially in your
// template after the Loop

// You're using the global variable declared before the Loop
global $my_post_id;
if ( has_post_thumbnail( $my_post_id ) ) {
    echo get_the_post_thumbnail( $my_post_id, 'full' );
}

The second option is way cooler and you can use it if you do not want to edit your template file – for example, inside functions.php or in a plugin. The main idea is the same – you declare a global variable and save the post ID into it before the loop begins – but you use an action to do this.

// Everything here goes into functions.php

function my_save_page_ID() {
    // Declare globals as before
    global $my_page_id;
    global $post;
    $my_page_id = $post->ID;
}

// This means your function my_get_page_ID() will be called when
// WordPress calls the function do_action('wp_head') - that's when
// your page's <head> is put together, way before the Loop
add_action('wp_head',  'my_save_page_ID');

So you can use this code anywhere:

// You're using the global variable you declared in functions.php
global $my_page_id;
if ( has_post_thumbnail( $my_page_id ) ) {
    echo get_the_post_thumbnail( $my_page_id, 'full' );
}

Simple as that.

So remember: is_home() returns true only on the blog page you’ve set via Settings > Reading, and to get your post or page ID after the Loop you’ll need to save it somewhere before the Loop begins.

And that’s all, folks!

4 thoughts on “WordPress Front Page vs Home Page and getting post ID outside or after the loop in every possible way

  1. Thanks so much for this article! However, as of WP 3.5.1 – neither of those last methods you posted seem to work. Any idea how to make them work with the latest wp?

    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>