I have the following code running in a plugin:


//Callback function
function thousand_pay($content)
    echo $content;

    if( !in_category( 'Stories') )

[Some HTML]


For some reason, on individual posts' pages the HTML gets printed multiple times:

Bug where HTML is printed multiple times

Can anyone think of why this would be? I read here that I might have to add to the conditional to check is_singular() and is_main_query(), so it would look like if(!in_category('Stories') || !is_singular() || !is_main_query(), but that just seems to stop the HTML getting printed at all on a post page. Any ideas?


It is normal for content to be accessed multiple times. For example SEO plugins need to do this to access it and generate meta data from.

Also it is a filter hook. Filters should never echo anything to the page, they are meant to modify passed value and return it.

If you do want to do something at that point, but only within the loop then in_the_loop() is condition you need.

  • Thanks! What kind of hook would I want to use to add something? – Ed King May 5 '16 at 10:21
  • You can use this to add something, you just need to modify the passed value and return it instead of just echoing things. – Rarst May 5 '16 at 10:22

I was having the same issue. My the_content filter was being called multiple times and this was slowing down page load as my the_content filter was calling an external API. So in my case, the API was being queried multiple times for the same data.

I tried using in_the_loop(), is_singular() and is_main_query() but sometimes, depending on the theme, those failed to limit calls to my filter to one time.

So I added a constant to my filter and that seems to have fixed the issue.

Here's an example of how to limit your calls to the the_content filter to one time:

add_filter( 'the_content', 'se225721_the_content' );

function se225721_the_content( $content ) {

    if ( ! in_the_loop() ) {
        return $content;

    if ( ! is_singular() ) {
        return $content;

    if ( ! is_main_query() ) {
        return $content;

    $content = ucwords( $content );

    remove_filter( 'the_content', 'se225721_the_content' );

    return $content;

Hope that helps!


  • I suppose this works. You could also remove the filter when the function is called. – Nathan Johnson Feb 17 '17 at 19:32
  • 1
    You're right! That is simpler. I updated the code to use the remove_filter() option instead of defining a constant. – Eric Feb 23 '17 at 15:38

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.