Creating Custom RSS Feeds in WordPress – The Right Way

There are a lot of tutorials floating around the internet that describe how to create a custom RSS feed in WordPress. Most of them have you creating a new page template, copying the code that WordPress uses to generate feeds into the page template, and adding to and modifying the code there.

In addition to all of the duplicated RSS code in the template, and the maintenance burden that creates, most of these tutorials exhibit poor coding practices, security vulnerabilities, and do not make use of core WordPress functionality. Having been frustrated with all of the bad tutorials out there, I decided to do something about it and write my own tutorial showing how to create a custom RSS feed in WordPress the right way.

If you just want to see the code, head over to this post’s example repository on GitHub. Otherwise, keep reading.

Starting Off

I’m going to build this functionality as a plugin. Most tutorials have you building this directly into your theme, but you should almost always be building things like this in a custom plugin so you can switch themes at any point without losing all of your custom functionality.

Create a new file custom-rss-feed-example.php in your plugins directory, and add the plugin header.

<?php
/**
 * Plugin Name: Custom RSS Feed Example
 * Plugin URI:  https://philipnewcomer.net/2016/08/creating-custom-feeds-wordpress-right-way/
 * Description: An example plugin to demonstrate the right way to implement a custom RSS feed in WordPress.
 * Version:     1.0
 * Author:      Philip Newcomer
 * Author URI:  https://philipnewcomer.net
 * License:     GPL-2.0+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 */

namespace PhilipNewcomer\CustomRSSFeedExample;

You will notice in this tutorial that I’m using PHP namespaces, which may be unfamiliar to you. Namespaces replace the need for prefixes in your function names, and they’re better than prefixes for a number of reasons. However, few WordPress developers are familiar with namespaces, even though they have been available since PHP 5.3. Part of the reason may be that WordPress Core still supports PHP 5.2, so it cannot use namespaces until it bumps its minimum supported PHP version to at least 5.3. However, most people (and web hosts) are now using a version of PHP that supports namespaces, so you should be fine to use them in your own code.

Register the New Feed

My example plugin will create a new feed identical to the default feed, but with the post’s featured image included. However, this fairly trivial example can be repurposed to do most anything you would need a custom feed for.

Now, let’s go ahead and register a new feed, by calling add_feed() on the init action hook.

/**
 * Registers our custom feed
 */
function register() {
   add_feed( 'rss2-with-featured-images', __NAMESPACE__ . '\generate_content' );
}
add_action( 'init', __NAMESPACE__ . '\register' );

The add_feed() function will register a new feed.

The first parameter is the name of the feed, which is also the URL endpoint at which the feed will be accessible. Since I used rss2-with-featured-images as the feed name, our new feed will be accessible at http://domain.com/feed/rss2-with-featured-images/.

The second parameter is the name of a function that will generate the markup for the new feed. We’ll look at that function in the next section.

Generate the Custom Feed Content

Now that our new feed is registered, we just need to write a function to generate the feed’s content. Rather than build a complete feed from scratch, we’ll utilize the existing WordPress RSS2 code to do the heavy lifting for us.

The code that WordPress uses to generate an RSS2 feed is located in feed-rss2.php in the WordPress includes directory (usually /wp-includes). While we could just copy the contents of that file into our plugin and modify it to suit, that would require that we maintain all of that code going forward. Instead, we’ll just include the file in our function from the WordPress includes directory.

/**
 * Generates the content of our custom feed
 */
function generate_content() {
   if ( file_exists( ABSPATH . WPINC . '/feed-rss2.php' ) ) {
      require( ABSPATH . WPINC . '/feed-rss2.php' );
   }
}

If you’re including a file from outside your plugin or theme, always check to be sure it exists first!

While we haven’t yet added featured images to the feed, believe it or not we now have a complete, fully-functional custom RSS feed in addition to our regular feed. That was much cleaner than copying the entire feed-rss2.php file into your plugin or theme just to create a new feed, wasn’t it?

Go ahead and activate the plugin and try it out. (We’ll add the featured images in the next section.) Note that after you activate the plugin, you will need to flush your site’s rewrite rules (by visiting the Settings > Permalinks page in the admin) to “activate” the new feed URL. You’ll only have to do this once after adding a new feed, or changing the name of a previously-registered feed.

Add Featured Images to the Custom Feed

Now that we have a separate, fully-functional RSS feed, let’s go ahead and add the featured images, being careful to only affect our custom feed. We can do that by adding a filter on the the_content_feed and the_excerpt_rss hooks immediately before we include the feed-rss2.php file, adding the featured image with a filter function, and then removing the hooks after the include. This will cause the filters to apply to feed-rss2.php code only when it’s included in our custom feed.

Modify the generate_content() function to add and remove the filters:

/**
 * Generates the content of our custom feed
 */
function generate_content() {

   add_filter( 'the_content_feed', __NAMESPACE__ . '\prepend_thumbnail' );
   add_filter( 'the_excerpt_rss',  __NAMESPACE__ . '\prepend_thumbnail' );

   if ( file_exists( ABSPATH . WPINC . '/feed-rss2.php' ) ) {
      require( ABSPATH . WPINC . '/feed-rss2.php' );
   }

   remove_filter( 'the_content_feed', __NAMESPACE__ . '\prepend_thumbnail' );
   remove_filter( 'the_excerpt_rss',  __NAMESPACE__ . '\prepend_thumbnail' );
}

Adding the filter immediately before the include (and removing it after) will allow the filter to apply only to the code between the add_filter() and remove_filter() calls.

Removing the filter after the include probably isn’t strictly necessary in this example, but it’s always good to be in the habit of cleaning up after yourself. In other contexts, not removing a filter when you’re done with it can introduce difficult-to-find bugs.

We’re using both the the_content_feed and the_excerpt_rss hooks so that no matter whether we have chosen (at Settings > Reading) to display the full content, or only the excerpt in the feed, the featured image will be included. There is a different filter for the excerpt and full content, and by using both, we’ll have covered both scenarios.

Finally, we need to create the function referenced in our add_filter() and remove_filter() calls above, which will actually add the featured image to the content:

/**
 * Prepends the post's featured image to the feed content
 *
 * @param string $content The feed content.
 *
 * @return string The filtered content.
 */
function prepend_thumbnail( $content ) {

   if ( ! has_post_thumbnail() ) {
      return $content;
   }

   $thumbnail_html = sprintf( "<p>%s</p>\n",
      get_the_post_thumbnail()
   );

   return $thumbnail_html . $content;
}

We are returning early if the current post does not have a featured image. If there is a featured image, we grab the image tag using the get_the_post_thumbnail() function, wrap it in a set of paragraph tags, add a newline character to keep the markup clean, and prepend it to the content.

Finishing Up

That’s it! Load up your custom feed URL again (making sure the plugin is activated, and that you’ve refreshed your permalinks if you haven’t yet), and see your custom feed in action.

You might be wanting to do something other than add the featured image to a feed. If that’s the case, try to find a filter that will allow you to do what you want, and use that instead of the filters in this example.

The complete code from the post is available on GitHub. It’s actually a fully-functional plugin. Feel free to fork it and build something on your own.

One thought on “Creating Custom RSS Feeds in WordPress – The Right Way

Leave a Reply

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