In the home page, I have a custom loop for displaying different post type content. I have this loop on my index.php

$loop = new WP_Query(
    'post_type' => array('photo', 'video', 'web'), 
    'paged' => get_query_var('paged') ? get_query_var('paged') : 1,
    'posts_per_page' => -1


Now it displays correctly but I want to include the title from what post type it belongs so that I can link to right page.

for example if I have these items in my home page (as a result of the above loop):

  1. Item 1 - video
  2. Item 2 - photo
  3. Item 3 - web

Where the links are the page I created that displays those custom post type and the title is the title of the post type (ie video. photo, web).

I have tried this to put inside my loop but it doesn't work.

<?php while ( $loop->have_posts() ) : $loop->the_post(); ?>
        if ( is_singular( 'photo' ) ) :
           echo "<a href='/photo'>photo</a>";

        elseif ( is_singular( 'video' ) ) :
            echo "<a href='/video'>video</a>";

        elseif ( is_singular( 'web' ) ) :
            echo "<a href='/web'>web</a>";
    <?php get_template_part( 'content', 'grid'); ?>
<?php endwhile; ?>
  • do you really want to just link to /photo, /video or /web ? OR to the actual post permalink with the post title as anchor? as it seems you are asking about post title but then linking to post type.
    – majick
    Mar 11, 2016 at 4:24
  • It also seems like you might be confusing 'post type' with 'post'. Post types don't really have a title as such.. although they do have a label which gives them the name you see in the admin area.
    – Tim Malone
    Mar 11, 2016 at 4:27
  • @majick - I actually want two links. One will be the actual permalink and two, the link to a page where the custom post type are served. Actually, there are no problems with the links. I can just simply echo the links in my ifs. The problem is how it can detect weather it's a video or photo. Mar 11, 2016 at 4:54

2 Answers 2


You are doing it wrong on many levels here:

  • You should not be using a custom query in place of the main query. Rather use pre_get_posts to alter the main query accordingly. Go back to the main loop and add the following in your functions file or in a custom plugin

    add_action( 'pre_get_posts', function ( $q )
        if (    $q->is_home()
             && $q->is_main_query()
        ) {
            $q->set( 'post_type',      ['photo', 'video', 'web'] );
            $q->set( 'posts_per_page', -1                        );
  • is_singular() is the wrong check here. is_singular() checks if you are on a singular post page, so it will always return false on any page that is not a singular post page.

    What you need is get_post_type() to get the post type the post belongs to and test against that

    if ( 'photo' === get_post_type() ) :
       echo "<a href='/photo'>photo</a>";
    elseif ( 'video' === get_post_type() ) :
        echo "<a href='/video'>video</a>";
    elseif ( 'web' === get_post_type() ) :
        echo "<a href='/web'>web</a>";
  • Lastly, if you want to link to the archive pages of those post types, you should be using get_post_type_archive(). Something like the following would work

    <a href="<?php echo get_post_type_archive_link( 'Photo' ); ?>">Photo</a>

    instead of echo "<a href='/photo'>photo</a>"


From comments, I have done an extensive answer on why not to use custom queries in place of the main query. Feel free to check it out here. It should answer quite a few questions for you

  • that get_post_type and get_post_type_archive saved me tons. Don't even need to create a page now. Though I have created a template called archive-photo.php and copied the template from my template. Just want to point out though that pre_get_posts I have one before. I can't remember why but I removed it and changed it to what I have now. BTW, I also tried that one you suggested but I had an error on the line with 4q. Can you please tell me why this is the right thing to do? Why I should not be using using custom query in place if the main query. Everything is working with me now. Mar 11, 2016 at 5:14
  • Man, that actually worked! Everything now works as you suggested. I swear I had that pre_get_posts before but I'm not sure why I removed it. I think because before I had that page navigation to be displayed so that infinite scroll would work. But I'm not using infinite scroll now. Maybe that's why. But anyway, it worked, so thanks a lot! Mar 11, 2016 at 5:24

Calling the_post() populates the $post object variable, so you can use this to make things easier by getting information directly from the $post object (and also the post type object):

<?php $post_object = array();

while ( $loop->have_posts() ) : $loop->the_post(); 

global $post; $post_type = $post->post_type; // just for clarity

// link to post permalink with post title anchor
echo "<a href='".get_permalink($post->ID)."'>".$post->post_title."</a>";

// to be efficient, only get the post type object if we have not already
if (!isset($post_object[$post_type])) {$post_object[$post_type] = get_post_type_object($post_type);}

// link to post type archive, with post type name as anchor (plural)
echo " (<a href='".get_post_type_archive_link($post_type)."'>".$post_object[$post_type]->labels->name."</a>)";

get_template_part( 'content', 'grid');

endwhile; ?>

This should cover all post types now rather than having to add conditions if you ever add more.

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.