Disable only the main feed?

It’s possible to make a site totally inaccessible via feeds (RSS, Atom, RDF) with a function like this:

function itsme_disable_feed() {
    wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
}
add_action('do_feed', 'itsme_disable_feed', 1);
add_action('do_feed_rdf', 'itsme_disable_feed', 1);
add_action('do_feed_rss', 'itsme_disable_feed', 1);
add_action('do_feed_rss2', 'itsme_disable_feed', 1);
add_action('do_feed_atom', 'itsme_disable_feed', 1);
add_action('do_feed_rss2_comments', 'itsme_disable_feed', 1);
add_action('do_feed_atom_comments', 'itsme_disable_feed', 1);

But that disables feeds for the entire site i.e. the main feed, feeds for categories, tags, comments, posts, pages, custom post types, etc.

Read More

How do I disable just the main feed and the main comments feed of the site? i.e. only make site.com/feed/ and site.com/comments/feed/ inaccessible.

Simply hiding feed using something like this (below) isn’t an option:

remove_action( 'wp_head', 'feed_links_extra', 3 );
remove_action( 'wp_head', 'feed_links', 2 );

Related posts

5 comments

  1. Very, very quick unscientific research suggests that there is only one query_var set for the main feed. Other feeds such as category, tag, author feeds have more than one query_var. Thus the following should kill the main feed but leave others intact.

    add_filter(
      'pre_get_posts', 
      function($qry) {
        if ($qry->is_feed()) {
          $fvars = array_filter($qry->query_vars);
          if (1 == count($fvars)) {
            wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
          }
        }
      },
      1
    );
    

    To remove the main comment feed, you need a small edit to check for the presence of $fvars['withcomments'].

    add_filter(
      'pre_get_posts', 
      function($qry) {
        if ($qry->is_feed() ) {
          $fvars = array_filter($qry->query_vars);
          if (1 == count($fvars) || isset($fvars['withcomments'])) {
            wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
          }
        }
      },
      1
    );
    

    Be warned: Barely tested. Possibly buggy. Caveat emptor. No refunds.

  2. This is a modded version of @s_ha_dum answer.

    I’m agree with him that when in main feed the only variable setted is 'feed' (for posts feed) and 'withcomments' for main comment feed, but instead of relying on current query object variables, and filter the many empty defaults using array_filter, I think that – probably – is more reliable looking at $wp->query_vars: an array that contain only the query variables effectively used to run the query:

    add_action('pre_get_posts', 'no_main_feeds', 1);
    
    function no_main_feeds( $q ) {
      if ( is_feed() || is_comment_feed() ) {
        $vars = $GLOBALS['wp']->query_vars;
        unset( $vars['feed'], $vars['withcomments'] );
        if ( empty($vars) ) wp_die( 'No feed available' );
      }
    }
    

    The check for is_comment_feed() is actually needless, because when in main comment feed is_feed() is true, but I think it makes code intentions more clear, probably is also more future proof, and finally it doesn’t hurt…

    Unlike other answers here it (should) works with any permalink structure and also if pretty permalinks are disabled at all.

  3. add_filter('request', 'itsme_disable_main_feeds');
    
    function itsme_disable_main_feeds($q)
    {
        $exit_msg   = 'No feed available. Please visit the <a href="%s">homepage</a>.';
        $exit_title = 'No Feed Available';
    
        if (    !empty($q['feed'])         && count($q) === 1
             || !empty($q['withcomments']) && count($q) === 2 ) {
    
            $exit_msg = sprintf($exit_msg, esc_url( home_url('/') ));
            wp_die( $exit_msg, $exit_title, array('response' => 404) );
        }
    
        return $q;
    }
    
  4. using rewrite rules you can disable a url pattern that match main feed.

    add_filter('rewrite_rules_array', 'rewrite_rules_array_feed_disable');
    function rewrite_rules_array_feed_disable($rules){
        unset($rules['feed/(feed|rdf|rss|rss2|atom)/?$']);
        unset($rules['(feed|rdf|rss|rss2|atom)/?$']);
        return $rules;
    }
    
  5. The hook callback needs to check if it’s a tag feed, or if it’s a category feed or may be if it’s a author feed. You can get a lot of information about the feed being produced if you add this two line in the callback. i.e function itsme_disable_feed(){ … }

    global $wp_query;
    die(print_r($wp_query->query_vars));
    

    You will notice that for a tag feed, or a category feed or a comment feed or even for an author feed there are certain parameters which contain values. Just do a check so that if those parameters have any value associated with it, you will do nothing. And if not, which means it’s a main feed, you will call die().

    Hope it helps.

Comments are closed.