Pippins Plugins
  • Email
  • Facebook
  • Feedburner
  • Github
  • Google
  • Twitter
  • Vimeo
  • Youtube
  • Rss
  • About
  • News
  • Join the Site
    • Member Benefits
    • Member Plugins
    • Email Notifications
  • Plugin Store
    • Affiliate Area
    • Checkout
  • Plugins
    • Plugin Portfolio
      • Plugin Portfolio – List View
    • Free
    • Premium
    • Member Plugins
    • Coding Standards
    • Get Plugin Support
  • Tutorials
    • Series
      • Plugin Development 101
      • Creating a User Follow System Plugin
      • Customizing Restrict Content Pro
      • Displaying Content with Easy Content Types
      • Writing Your First WordPress Plugins, Basic to Advanced
      • Working with Widgets
      • User Submitted Image Galleries
      • Plugin Thoughts
      • Integrating Stripe.com with WordPress
      • WordPress Rewrite API
    • Member Exclusive
      • Free Members
      • Subscriber Only
    • Difficulty
      • Beginner
      • Intermediate
      • Advanced
    • Action and Filter Hooks
    • Ajax
    • Custom Post Types
    • External APIs
    • Short Codes
    • Taxonomies
    • Video Tutorials
    • Widget Tutorials
    • WordPress Admin / Dashboard
    • Working with jQuery
    • WordPress Database
    • Writing Plugins
    • Tag Index
  • Reviews
  • Support Forum
  • Contact
    • Support the Site
    • Request Code Review
    • Plugin Support

Playing Nice with the “the_content” Filter

Posted on May 14, 2012 by Pippin in Action and Filter Hooks, Intermediate, Tutorials, Writing Plugins 45 Comments
Home» Tutorials » Action and Filter Hooks » Playing Nice with the “the_content” Filter
Tweet
Love It - 6

One of the very first things people tend to learn when writing plugins is how to attach custom HTML to the bottom of their WordPress posts using the filter called “the_content”. This is good, as it is an extremely useful filter, but rarely do tutorials really explain how to use this filter well, and how to avoid some potentially major problems when using it in your plugins. I’m going to walk you through the basics and also demonstrate some more advanced applications, and talk to you about problems that can be caused when using this filter.

The typical code that you will see intro plugin development tutorials show usually looks about like this:

1
2
3
4
5
6
function pippin_filter_content_sample($content) {
	$new_content = '<p>This is added to the bottom of all post and page content</p>';
	$content = $content . $new_content;
	return $content;
}
add_filter('the_content', 'pippin_filter_content_sample');

With this function active in your theme or plugin, any time the the_content() function is called, the text “This is added to the bottom of all post and page content” will be appended to the end.

There are a few minor and major issues with function. Let’s look at how we correct these.

Problem number 1: while there is nothing syntactically wrong with this function, we can improve it by cutting away some of the unnecessary code. There is really no reason for this line:

$content = $content . $new_content;

Instead of doing that, we should just attach our $new_content variable directly to the $content variable in the return statement, like so:

return $content . $new_content;

You could even go a little further and do just this:

return $content . '<p>This is added to the bottom of all post and page content</p>';

They will both result in the same thing, but I prefer the first of the two methods and it is just slightly easier to read, especially when you have much larger functions.

Problem number 2: the first problem was more of a good coding practice kind of problem, this second one is much more major. Have you ever seen a plugin, particularly social sharing plugins, that adds some form of content to posts and/or pages, and for some reason the content appears in weird places, such as sidebars or footers, and also on every single page, including archives? This is typically because the developer has not take the time to ensure that their extra content, be it social icons or something else, only gets added in the appropriate place. The most common place to append content is at the end of a post when viewing the single post.

To update our code and fix problem #2, we need to use some conditional tags. First let’s start with is_single().

1
2
3
4
5
6
7
8
function pippin_filter_content_sample($content) {
	if(is_single()) {
		$new_content = '<p>This is added to the bottom of all post content</p>';
		$content .= $new_content;	
	}	
	return $content;
}
add_filter('the_content', 'pippin_filter_content_sample');

By adding the is_single() conditional check, we ensure that out extra content only gets appended when we are on a single post page. But what if we want to add content to both single posts and pages? And perhaps custom post types? Then we need to use is_singular():

1
2
3
4
5
6
7
8
function pippin_filter_content_sample($content) {
	if(is_singular()) {
		$new_content = '<p>This is added to the bottom of all post and page content, as well as custom post types.</p>';
		$content .= $new_content;	
	}	
	return $content;
}
add_filter('the_content', 'pippin_filter_content_sample');

Looks pretty good right? Actually no, there is still a major problem with this code. The thing that you must understand and acknowledge is that the “the_content” filter may NOT only get applied when we call the_content(). Often times plugin and theme developers will use something like the following to help format their custom queries:

echo apply_filters('the_content', $custom_content_here);

Doing this will pass whatever content is stored in the $custom_content_here variable and perform all of the nice formatting that we expect with the the_content() function. This also means that our pippin_filter_content_sample() function will attach its custom content to this other text as well, and that’s not good.

In order to solve this problem, we can use one more conditional tag. The is_main_query() function was introduced in WordPress 3.3 and allows us to check whether we are currently inside of the main post query. The main post query can be thought of as the primary post loop that displays the main content for the post/page or archive. By using this tag, our filter will NOT get applied to any custom loops in sidebars, footers, or elsewhere, even if they use this:

apply_filters('the_content' . . .

Our final function, which should play well with everything, looks like this:

1
2
3
4
5
6
7
8
function pippin_filter_content_sample($content) {
	if( is_singular() && is_main_query() ) {
		$new_content = '<p>This is added to the bottom of all post and page content, as well as custom post types.</p>';
		$content .= $new_content;	
	}	
	return $content;
}
add_filter('the_content', 'pippin_filter_content_sample');

When building your own plugins and themes, do not forget to think about what other developer’s plugins and themes may be doing. You should always try to eliminate as many possible conflicts before they even happen, and making sure that you use these kind of filters correctly is a great place to start.

Tweet Follow @pippinsplugins
add_filter, the_content

45 comments on “Playing Nice with the “the_content” Filter”

  1. Justin Sainton says:
    May 14, 2012 at 11:30 pm

    It’s probably worth noting that the ‘the_content’ filter is NOT actually applied to get_the_content().

    Reply
    • Pippin says:
      May 15, 2012 at 10:07 am

      Ah yes, you’re right. Updating now.

  2. Paul says:
    May 15, 2012 at 10:17 am

    thanks Pippin!

    I’m guilty of doing_it_wrong ;) But from now on, I’ll use the improved code.
    how’s the baby?

    Reply
    • Pippin says:
      May 15, 2012 at 10:25 am

      Lots of people are. I’ve definitely done it wrong far more than I’d care to admit.

      The baby is doing well :)

  3. david says:
    May 15, 2012 at 6:40 pm

    I think, if you want to add something below the content, (for eg: social button). It should be added after wp_link_pages.?
    Because wp link pages already have filter to enable this.

    Reply
    • Pippin says:
      May 15, 2012 at 6:59 pm

      The wp_link_pages() function does not actually have a filter that you can use to attach additional content too, and even if it did, it actually would not be a good idea to use, as it is up to the theme to implement wp_link_pages() in the template files. Obviously yes, it is up to the theme to add the_content() as well, but that function is almost guaranteed to be included in every theme.

    • Justin Tadlock says:
      September 17, 2012 at 6:54 pm

      There’s a hook there. It was one of my contributions to the core code. Andrew Nacin has an awesome solution that uses it in his Simple Footnotes plugin where he checks if wp_link_pages() is used. It’s brilliant stuff.

    • Pippin says:
      September 17, 2012 at 10:19 pm

      Oh, thanks for the correction!

  4. Flick says:
    May 15, 2012 at 9:05 pm

    Thanks for this tutorial :) I was wondering if you could advise the best practise for say – if one built an options page with checkboxes so users could ‘tick’ boxes to show content after Single / Page/ other post types? Thanks!

    Reply
    • Pippin says:
      May 15, 2012 at 9:09 pm

      Are you looking for help on creating those checkboxes, or how to detect if they are enabled and then adding the appropriate content?

  5. Johan says:
    May 18, 2012 at 3:44 am

    Thanks for the excellent explanation on how this filter works. I have written a plugin that allows you to display the contents of a custom post type called content block in a widget and often get the complaint that social media buttons are displayed in the widget area.

    From now on I will point them to this post!

    Reply
    • Pippin says:
      May 18, 2012 at 10:10 am

      Social media plugins tend to be the largest culprit for sure.

  6. Mobile Repairing says:
    May 19, 2012 at 8:43 pm

    I use it withing my theme single.php file but this code is cleaner will definitely try it thanks for sharing

    Reply
  7. Jack says:
    September 24, 2012 at 3:14 am

    As a user, not a plugin developer, I’m trying do remove a filter from a plugin. I’m using Secondary Content Blocks and it adds extra content beneath each block. like social media icons etc. This means that with 3 extra content blocks, I also get three extra sets of social media icons. The writer of the plugin told me this: “You have to the remove the filter (remove_filter) that adds the extra content via the “the_content” filters before your secondary HTML functions.” but that’s were the help stops ;) .

    How should my code look like then in my templates?

    Reply
    • Pippin says:
      September 24, 2012 at 9:12 am

      You’re going to use something like this:

      1
      
      remove_filter( 'the_content', 'name_of_the_function_from_the_plugin' );

      You will have to find the appropriate function name to replace “name_of_the_function_from_the_plugin”.

  8. Michael Paryna says:
    October 24, 2012 at 12:01 pm

    Unfortunately the is_main_query function doesn’t work OK inside a custom loop:/

    Reply
    • Pippin says:
      October 24, 2012 at 2:57 pm

      Do you mean it doesn’t work to detect a custom loop? If so, that’s correct, it’s for the main query that is performed when the page is loaded, not any sub-queries that happen throughout the page.

    • Michael Paryna says:
      October 24, 2012 at 3:59 pm

      Yes, exactly. And unfortunately that’s why the pippin_filter_content_sample filter will be also applied inside a custom loop (unless your custom query overwrites $GLOBALS['wp_query'] for a moment)

    • Pippin says:
      October 24, 2012 at 8:45 pm

      Yes, you’re right, though it largely depends on how the query is setup actually. The snippet I gave could actually be improved even further to help mitigate affecting sub queries.

  9. Jack says:
    January 25, 2013 at 12:36 pm

    I’m having a problem filtering the content in my Sermon plugin. The content will repeat in the header, but only using certain themes with JetPack installed. None of the themes I’ve developed have this issue. Twenty Twelve does cause the issue if JetPack is active. Here’s an example using the Suffusion theme with JetPack: http://stlukeswatford.org/sermons/image/

    You can view the code to filter the content here on lines 961-972 : https://github.com/wpforchurch/sermon-manager-for-wordpress/blob/master/sermons.php

    Any ideas? I’d really appreciate any help you could offer.

    Reply
    • Pippin says:
      January 27, 2013 at 9:02 pm

      What’s the issue in the header exactly? Can you give me an example?

    • Jack says:
      January 28, 2013 at 9:42 pm

      Sorry, there was an example at the first url, but they understandably took it down. Here’s another one: http://demo.wpforchurch.com/plugins/sermons/rooted-in-love/

    • Pippin says:
      January 31, 2013 at 5:42 pm

      Whoa, that’s bizarre. Have you tried deactivating all of the social modules? I suspect getting rid of those will fix it.

  10. Diana says:
    February 5, 2013 at 2:56 pm

    Pippin your site helps me a lot, but his time I can’t figure out what is happening, I need to ask you:

    When using the filter the_content, the defaults themes (2010 and 2011) outputs only raw content in archive listings :( Even your example turns into raw text.

    I think there’s something to do with this themes excerpt functions but I can’t find a clue on how to bypass they filters/functions.

    Thanks for any help.

    Reply
    • Pippin says:
      February 5, 2013 at 4:12 pm

      What do you mean exactly by raw text? Can you give me an example of what you were hoping for and what you’re getting?

  11. Diana says:
    February 5, 2013 at 5:50 pm

    I want place some special content in posts, just like in your example, but some themes like 2010 and 2011 just strips HTML if the filter is intend to affect on archives pages too.

    If you try your example on archive pages, (not only single), those themes will strip out any HTML, e.g.
    if you set $new_content= 'Test'; in your example, 2010 and 2011 themes will remove he HTML tags :(

    The 2012 theme and some other don’t do this, but 2010 and 2011 does;

    Reply
    • Jack says:
      February 5, 2013 at 6:18 pm

      You’ll want to filter the_excerpt

  12. Diana says:
    February 7, 2013 at 9:35 am

    Thanks @Jack! That solved!

    I just added the the_excerpt as well and works ok now!. Thanks!

    Reply
  13. David says:
    February 23, 2013 at 2:20 am

    Hi Pippin,
    I have a question. I am using a plugin that inserts content at the of the post automatically. Now I am using your code to insert custom content & it works well. The problem is that the content inserted by the plugin appears before my custom content. I am trying to reverse this. I am trying to show my content first, followed by the content inserted by the plugin. I tried to use 10 for the priority in the add_filter line of my theme but it does not seem to fix it.

    So do you know how I can fix this? Any help is appreciated.

    Thanks.

    Reply
    • Pippin says:
      February 24, 2013 at 10:42 am

      Try setting the priority to “-1″.

    • David says:
      February 25, 2013 at 7:11 am

      Should I do this for my theme for the plugin? If I edit the source code of the plugin, I am afraid that it will break when the plugin upgrades. So should I do this for theme?

    • Pippin says:
      February 25, 2013 at 6:51 pm

      In your theme yes.

  14. Rohin says:
    March 7, 2013 at 4:13 am

    Hello Pipin..
    I am using:
    1. a social media plugin that appends it’s social buttons after the_content
    2. a metadata plugin that also appends it’s metadata after the content
    3. An author box plugin that also appends the author box after the_content
    Now I want that The 2nd plugin(metadata plugin) should put it’s data after the social plugin or after both 1st and 3rd plugins data.

    Looked in plugin’s files. all 3 of them are using filter and returning something like this:
    the_content . “plugin data”
    through the function they hook.
    Can you help me solving this one?
    It can be taken as prioritizing the filters or something like that.
    Thank you :)

    Reply
    • Pippin says:
      March 7, 2013 at 2:21 pm

      Do you want to disable the filters globally or just in certain contexts?

    • Rohin says:
      March 7, 2013 at 2:39 pm

      I Don’t want to disable them.
      Just asking what to do when 3 plugins are using the_content filter and I want to make sure which plugin puts it content after post content first.

    • Pippin says:
      March 8, 2013 at 4:31 pm

      Got it. Then you should be using the priority options for the filters. The higher the priority, the later the function will run. Make sense?

  15. Silki says:
    March 20, 2013 at 8:51 pm

    Hello Pippin,

    Nice post, thanks a lot.
    I just tried to take help of your code and was able to successfully implement it with the following piece of code.

    function belowcontent($content) {
    global $post;
    if( is_singular() && is_main_query() ) {
    $variable = get_post_meta($post->ID, 'metadata', true);
    if ($variable == 'ap')
    {
    $new_content = 'xxxxxxxxxxxxxxxxxxxxxxx';
    return $content . $new_content;
    }
    else
    {
    return $content;
    }
    }
    }
    add_filter('the_content', 'belowcontent');

    I am observing that the conditional tag is successfully operating on single post pages. However, on there is no data on the main page (http://loancalculators.in/articles/), where all the posts are chronologically listed.

    Appreciate any help in this regard.
    Thanks

    Reply
    • Silki says:
      March 20, 2013 at 9:03 pm

      Just wanted to add that I am using a theme, which is using custom page for the main page. I have shared the code of this page on Google Drive here at…
      https://docs.google.com/file/d/0B9VMYc0qEDtpUXZMcmxrRDhId00/edit?usp=sharing.

      Thanks for any help.

    • Pippin says:
      March 22, 2013 at 4:28 pm

      That’s because the archive pages uses the_excerpt() instead of the_content().

    • Silki says:
      March 22, 2013 at 10:39 pm

      Thanks for looking.
      Yes, I understand that archive pages are using the_excerpt(). But I do not know if the_excerpt() and the_content() are related.
      Could you help me how I can get the excerpt back on the archive pages.

      Sorry, I may be sounding too naive to ask such simple question.

      Silki

    • Pippin says:
      March 25, 2013 at 3:28 pm

      They are related but only the_content() uses the filter called “the_content”.

    • Silki says:
      March 25, 2013 at 8:06 pm

      So,
      How can I fix up the issue?

      Silki

    • Pippin says:
      March 26, 2013 at 10:02 pm

      Modify the theme template files and replace the_excerpt() with the_content().

  16. Eduardo Casanova says:
    May 6, 2013 at 2:47 am

    Pippin. could show me how to add

    Try setting the priority to “-1″.

    I have no idea how much to add is to give an example

    Reply
    • Pippin says:
      May 6, 2013 at 11:12 am

      Instead of this (for example):

      add_filter('the_content', 'pippin_filter_content_sample');

      add_filter('the_content', 'pippin_filter_content_sample', -1);

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

  • Login

Lost your password?

Please enter your username or e-mail address. You will receive a new password via e-mail.

  • Facebook Become a Fan Like

  • Twitter Subscribe on Twitter Follow

  • YouTube Follow my Videos Subscribe

  • RSS Feed Subscribe with RSS Subscribe

Easy Digital Downloads

Most Loved

  • Love It Pro for WordPress
  • Write a “Love It” Plugin with Ajax to Let Users Love Their Favorite Posts / Pages
  • Simple Notices Pro Plugin for WordPress
  • User Bookmarks for WordPress
  • Front End Registration and Login Forms Plugin

Similar Plugins and Posts

  • Plugin Development 101 – An Intro to Filters
  • Never Remove the Default the_content Filters in Themes
  • Introduction to the gettext Filter in WordPress
  • Let’s Talk Extensible Code
  • Adding Custom Fields to the Easy Digital Downloads Checkout

Latest Premium Content

  • Plugin Development 101 – Introduction to Adding Dashboard Menus
  • Plugin Development 101 – Intro to Loading Scripts and Styles
  • User Follow System – Part 5
  • Plugin Development 101 – Intro to Short Codes
  • Plugin Development 101 – Registering a Custom Post Type
  • Plugin Development 101 – Intro to Actions

Latest Tutorials

  • Submitting Your First Pull Request to a WordPress Plugin on Github (4)

    Github is an extremely popular tool for managing WordPress plugins, and one...

  • Plugin Development 101 – Introduction to Adding Dashboard Menus (1)

    Adding new menus, both top level and sub level, to the WordPress Dashboard is a really common task for plugins...

  • Plugin Development 101 – Intro to Loading Scripts and Styles (16)

    In this part of Plugin...

Enter your email to receive automated updates when new posts are published

Latest Tweets

  • @tnorthcutt Start here, I may send you to the forums
    May 23, 2013
  • Best site to order custom t-shirts in quantities less than 10. Go!
    May 23, 2013
  • @JS_Zao HA! I really like that idea @carter2422
    May 23, 2013

Topics

hook meta box Rémi Corson featured shortcodes campaign monitor add_options_page register_setting Sugar Event Calendar attachments add_shortcode wp_enqueue_script the_content image forms short codes Related posts login do_action authors mail chimp attachment plugin recent posts comments post types bbpress apply_filters short code taxonomies custom post type Ajax images gallery Stripe jquery taxonomy users widgets add_filter easy content types add_action widget restrict content pro easy digital downloads

Weekly Newsletter

Useful Links

  • Join the Site
  • Plugin Store
  • Affiliate Area
  • Tag Index
  • Support the Site
  • Suggest a Tutorial
  • Random Post
  • Contact

Monthly Archives

(c) 2013 Pippin's Plugins