Some posts have a more "readable value" even though they are free to read. To highlight their increased reader value, I've managed to get together this piece of code.

"Problem" is, for some reason when navigation through the blog pages, the menu items gets the "Worth Reading" label as well - which is not the idea.

My question is this; am I doing this wrong or do I need to somehow include a "is_menu()" kind of conditional that I am not aware of?

add_filter('the_title', 'label_after_post_title', 10, 1);
function label_after_post_title($title){

  if (is_admin()) return $title;

    if (is_single() || is_category('worth-reading') || is_search()) return $title;

        $label = '';

        if (has_category('worth-reading')){

          $label = '<span class="worth-reading">Worth Reading</span>';
          $title = $title . '&nbsp;&nbsp;' . $label;
      return $title;

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 );
  • 1
    Hi Jacob, I tested your code with a small change (due to nr of arguments given). I changed add_filter( 'the_title', 'label_after_post_title', 10, 1 ); into add_filter( 'the_title', 'label_after_post_title', 10, 2 ); and I added one more condition to the argument to make sure the label did not show on posts pages (!is_singular('post')) and it seems to work just fine. Thank you! Jan 14 at 7:32
  • I just wanted to say thank you for your detailed answer. I learned something while fixing my problem. So, thanks! Jan 14 at 7:55

You may skip altering the title by checking if the post is a nav item using is_nav_menu_item Or you may just bail out by checking if the get_post_type != 'post'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.