Support » Developing with WordPress » How To Hide CPT Post IDs From Their Archive?

  • Resolved bward

    (@bward)


    I am trying to hide two custom post type Post IDs from their own archive only. I still want them to appear in feeds, search and on the homepage, etc.

    I currently use this code for other functions and was trying to modify it with no luck. I cannot find anything on this, only how to hide posts. I know I am missing something here. Thanks so much in advance!

    // Hide Posts Pages from RSS feeds
    function exclude_single_posts($query) {
    	  if (($query->is_home() || $query->is_archive() || $query->is_feed() || $query->is_search()) && $query->is_main_query()) {
    		  $query->set('post__not_in', array(52428,52432,52426,52436,52434,52430,52845,52424,52438,13363,45989,54116,38540));
    	  }
    }
    add_action('pre_get_posts', 'exclude_single_posts');
    • This topic was modified 4 months, 3 weeks ago by  bward.
Viewing 11 replies - 1 through 11 (of 11 total)
  • Moderator bcworkz

    (@bcworkz)

    It’s all in how you construct the conditional. Something along the lines of

    if (! is_admin() && $query->is_main_query() && $query->is_archive()) {
      if ('CPT_1' == $query->get('post_type') || 'CPT_2' == $query->get('post_type')) {

    Change CPT_! and CPT_2 to your actual post types of course.

    If that doesn’t get it, dump out $query->query_vars and identify something else unique you can use as a conditional.

    I may not have explained that very well or I am not following your reply.

    We have a CPT of “example”. In the CPT archive for “example” we would like to hide CPT “example” post-id 100. Only in the CPT “example” archive.

    Thanks so much.

    Moderator bcworkz

    (@bcworkz)

    I guess you didn’t follow my response since your simplified example conforms to my initial understanding. I gave you incomplete code, expecting you to follow my reasoning. That wasn’t a very good strategy on my part. Complete code for your simplified example. To capture other CPT archives you can either use OR logic in the second conditional, or you can replicate the entire code again, substituting the new CPT and exclusion IDs.

    // Exclude certain "example" CPT posts from archive lists
    function exclude_selected_posts($query) {
      if (! is_admin() && $query->is_main_query() && $query->is_archive()) {
        if ('example' == $query->get('post_type')) {
          $query->set('post__not_in', array( 100, 123, 456 ));
        }
      }
    }
    add_action('pre_get_posts', 'exclude_selected_posts');

    As you can see, I expanded your exclusion ID 100 to exclude a couple more posts.

    Thanks for the follow-up bc. Hey, I am no coder, but I have not done too bad over the years trying to figure it all out! hah

    Thanks for spelling it all out. It helps me understand it a bit better, but that did not seem to work.

    I tried changing is_archive to is_post_type_archive as well, I saw that mentioned in the codex for CPT, but it was a no go.

    My CPT archive page is found at https://domain.com/example/archive. I am not sure what is missing at this point. I would kick the server, but it’s in the cloud!

    Moderator bcworkz

    (@bcworkz)

    Darn! That was going to be my next suggestion 🙂

    is_post_type_archive() is probably a better choice, but either should work.

    I double checked the code on my site and it works as expected both ways. For your site, be sure any caches that are active are flushed. Flush your browser cache as well.

    If that doesn’t help, the equivalent of kicking servers in WP is deactivating all plugins, and copying the test code to twentynineteen’s functions.php and switching to that theme. The code ought to work now. Switch back to your normal theme, then reactivate plugins, one at a time, testing after each. When the code again fails to work, the last activated module is at fault.

    You are the man!

    I was getting ready to take the next steps this morning. Then thought, the code I originally posted on is also in my functions file and that may be causing the issue. Sure enough, I commented it out and inserted your code and it works like a champ!

    I do need the original code as well. I am thinking I need to add your new code with an elseif statement somewhere?

    Moderator bcworkz

    (@bcworkz)

    Something like that. Please post the code you still need that you commented out as a test, as well as the working version of my code. I don’t dare try to meld logic without seeing what we’re working with.

    The code I commented out was:

    This one keeps the posts in array out of sight unless the user has the link, which is what I was after here.

    // Hide Posts Pages from RSS feeds
    function exclude_single_posts($query) {
    	  if (($query->is_home() || $query->is_archive() || $query->is_feed() || $query->is_search()) && $query->is_main_query()) {
    		  $query->set('post__not_in', array(1000,1002,1003));
    	  }
    }
    add_action('pre_get_posts', 'exclude_single_posts');

    When I have both the code above and your code below active, that is where I ran into trouble. So I commented out the code above. It is probably the way the $query statements are being called in this setup. I have not used those much.

    FYI, your code works great stand alone. Here it is.

    // Exclude certain "example" CPT posts from archive lists
    function exclude_selected_posts($query) {
      if (! is_admin() && $query->is_main_query() && $query->is_archive()) {
        if ('example' == $query->get('post_type')) {
          $query->set('post__not_in', array( 100, 123, 456 ));
        }
      }
    }
    add_action('pre_get_posts', 'exclude_selected_posts');

    It would be fantastic to be able to use both of these without issue though.

    Thanks again for the help bc!

    • This reply was modified 4 months, 2 weeks ago by  bward.
    Moderator bcworkz

    (@bcworkz)

    Thanks, after some cut and paste surgery, we end up with

    function exclude_selected_posts($query) {
      if (! is_admin() && $query->is_main_query()) {
        //Exclude certain posts from most lists
        if ( $query->is_home() || $query->is_archive() || $query->is_feed() || $query->is_search()) {
          $query->set('post__not_in', array(1000,1002,1003));
        }
        // Exclude certain "example" CPT posts from archive lists
        if ( $query->is_archive() && 'example' == $query->get('post_type')) {
          $query->set('post__not_in', array( 100, 123, 456 ));
        }
      }
    }
    add_action('pre_get_posts', 'exclude_selected_posts');

    Replace both code snippets with this one. The second $query->set() supersedes the first for “example” CPT archives only. If any of IDs 1000,1002,1003 are “example” posts, include these in the second $query->set() as well.

    BC, we have a winner!

    I did some testing and it looks like it is doing the job. You are fantastic, I really appreciate all of the help on this one.

    I struggled to try and obtain this for hours and hours, tried a few more times another day. It was a mess. I got it to “work,” but it hid the post in the admin panel as well.

    So I really appreciate your help here. Could not have done it without you sir!

    Moderator bcworkz

    (@bcworkz)

    You’re welcome! You are clearly pleased, that makes me happy 🙂

    Probably the key thing you had missed is using ! is_admin() to avoid influencing backend screens. That and is_main_query() are pretty much de rigueur for these sort of things.

Viewing 11 replies - 1 through 11 (of 11 total)
  • You must be logged in to reply to this topic.