Adding Text after Post Title based on Category using IF Condition – But not for menu items

The the_title() filter is applied to the titles of posts and pages in menu items, so without any conditions any changes you make will also apply there.

It’s worth breaking down your conditions to see why your change is still applying to menus:

  • is_single() Are we viewing a single post? We may be, but nav menus are still typically displayed on single posts.
  • is_category() *Are we viewing a category archive?` Again, we may be, but nav menus are still typically displayed on single posts.
  • is_search() Are we viewing search results? Same again, this is still true for nav menu items.

So you need a condition to only apply a filter to post titles within the loop. The function you’re looking for is in_the_loop().

I would go as far as to say that you don’t want any of the other conditions you’ve used. Your goal is to display something next to the title of any posts in the loop that have the worth-reading category. As long as those conditions are met we don’t really need to check the others:

function label_after_post_title( $title, $post_id ) {
    if ( is_admin() ) {
        return $title;
    }

    if ( in_the_loop() && has_category( 'worth-reading', $post_id ) ) {
        return $title . '&nbsp;&nbsp;<span class="worth-reading">Worth Reading</span>';
    }

    return $title;
}
add_filter( 'the_title', 'label_after_post_title', 10, 2 );