DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Easy Custom Feeds in WordPress

Posted by on

Now that we have seen how to setup Tumblr-style posts, it would be nice to be able to segregate the Tumblr-posts category from the main feed into its own, separate feed. This would enable readers to subscribe exclusively to the Tumblr-posts feed and maybe display it in their sidebar or something. While we’re at it, it would also be cool to be able to provide readers with a full menu of feed choices, including the following:

  • Everything feed: includes both the main posts and the Tumblr posts
  • Articles-only feed: includes only the main articles and no Tumblr stuff
  • Tumblr-only feed: includes only the Tumblr-style posts

Let’s look at an overview of the process..

Update! Check out more feed customizing tricks & tips: Customizing WordPress Feeds, Create an Articles-Only Feed, and What is My WordPress Feed URL?.

Overview of this tutorial

To accomplish our goals, we’ll perform the following steps:

  1. Create two custom-Page templates
  2. Create two Pages, one for the articles and one for the Tumblr-posts
  3. Assign the custom templates to their respective Pages
  4. Make sure the feeds validate and clean up theme tags

That’s the plan, now let’s dig in..

Step 1: create a couple custom-page templates

Our two custom Page-templates will contain all of the code needed to generate our two custom feeds. These two custom templates are almost identical. For the articles-only feed, we will exclude the tumblelog category from the loop, and for the tumblr-only feed, we will include only the tumblelog category.

Let’s do the articles-only Page template first. In your theme, create a new Page-template file called “articles.php” and insert the following code:

<?php 
/* 
Template Name: Articles
*/
$numposts = 10; // number of posts in feed
$posts = query_posts('showposts='.$numposts.'&cat=-1'); // replace the number 1 with the ID of your tumblelog category
$more = 1;

header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
?>

<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	<?php do_action('rss2_ns'); ?>
>
<channel>
	<title><?php bloginfo_rss('name'); wp_title_rss(); ?> - Article Feed</title>
	<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
	<link><?php bloginfo_rss('url') ?></link>
	<description><?php bloginfo_rss("description") ?></description>
	<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
	<?php the_generator( 'rss2' ); ?>
	<language><?php echo get_option('rss_language'); ?></language>
	<sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
	<sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>
	<?php do_action('rss2_head'); ?>
	<?php while( have_posts()) : the_post(); ?>

	<item>
		<title><?php the_title_rss(); ?></title>
		<link><?php the_permalink_rss(); ?></link>
		<comments><?php comments_link(); ?></comments>
		<pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
		<dc:creator><?php the_author(); ?></dc:creator>
<?php the_category_rss(); ?>
		<guid isPermaLink="false"><?php the_guid(); ?></guid>
<?php if (get_option('rss_use_excerpt')) : ?>

		<description><![CDATA[<?php the_excerpt_rss() ?>]]></description>
<?php else : ?>

		<description><![CDATA[<?php the_excerpt_rss() ?>]]></description>
	<?php if ( strlen( $post->post_content ) > 0 ) : ?>

		<content:encoded><![CDATA[<?php the_content() ?>]]></content:encoded>
	<?php else : ?>

		<content:encoded><![CDATA[<?php the_excerpt_rss() ?>]]></content:encoded>
	<?php endif; ?>
<?php endif; ?>

		<wfw:commentRss><?php echo get_post_comments_feed_link(); ?></wfw:commentRss>
		<slash:comments><?php echo get_comments_number(); ?></slash:comments>
<?php rss_enclosure(); ?>
<?php do_action('rss2_item'); ?>

	</item>
	<?php endwhile; ?>

</channel>
</rss>

Alternately, you may download the two required page-template files here.

Once you have that code in place, edit the $numposts variable according to the number of articles that you would like to display in the articles-only feed. Then edit the $posts variable according to the ID of your tumblelog category. See the comments in the code for details.

That’s it for your articles-only feed. Now, for your tumblr-only feed, create another new Page-template file called “tumblelog.php” and insert the exact same chunk of code as before. The first change that we need to make for this second template is to remove the hyphen ( - ) from the $numposts variable like so:

$posts = query_posts('showposts='.$numposts.'&cat=1');

This tells WordPress to include only your tumblelog category in your tumblr-only feed. For your articles-only feed, the presence of the hyphen (negative sign, whatever) tells WordPress to exclude your tumblelog category. Simple, but effective.

The second (and final) change that we need to make for the tumblr-only template is to give it a new template name in the first line:

Template Name: Tumblelog

This will enable WordPress to distinguish between the two custom templates in the next step.

Step 2: create two Pages in the WordPress Admin

With your two custom Page-templates uploaded to your server, login to your Admin area and create two new Pages:

  • Create a Page called “Articles” and assign it the “Articles” template
  • Create a Page called “Tumblelog” and assign it the “Tumblelog” template

At this point, your two new custom feeds are fully functional, appearing at the following URLs:

  • http://domain.tld/articles/ — articles-only feed
  • http://domain.tld/tumblelog/ — tumblr-only feed

Once you have some posts in your tumblr-only category, you will see that they are excluded from the articles-only feed and appear by themselves in the tumblr-only feed. Of course, your main posts feed, located at http://domain.tld/feed/ will contain all of your posts, enabling you to offer the following feeds to your readers:

  • “Everything” feed — that would include both the main posts and the Tumblr posts
  • “Articles-only” feed — that would include only the main articles and no Tumblr stuff
  • “Tumblr-only” feed — that would include only the Tumblr-style posts

Final step: validation and theme clean-up

Now that everything is working, you should take the time to double-check the validity of your new feeds. This will ensure that subscribers receive the correct content in the proper format. Rest assured, I have already validated the XML produced from the custom page-template, but double-checking is always a good idea in case there are any unintended side-effects from plugins, scripts and whatnot.

One of our favorite validation services is available at: http://feedvalidator.org/ — go there and enter the URLs of your new feeds.

Here at DiW, we recently used this exact method to establish an articles-only feed for use at Planet WordPress. You can verify that it validates quite nicely.

Finally, after setting up your custom feeds, you should go into your theme and add some nice “subscribe” links for your readers. Also want to remind you that your new feeds are in fact Pages, such that you may want to remove them from any automatic Page-listings generated by the wp_list_pages or wp_page_menu template tags. For example, you can easily exclude your two feed Pages as follows:

wp_list_pages('exclude=123,456');

Where “123” and “456” are the IDs of your Articles and Tumblelog Pages.

Wrapping it up

With the technique described in this article, you now have an easy, sure-fire way of creating custom feeds in WordPress. The code for the feed markup is highly versatile, and may be customized to suit virtually any custom-feed configuration.

7 Responses

  1. Karl Oakes September 14, 2009

    Thanks Jeff, never played around with rss feed formats and I will need this sort of category control on a current project.

  2. What I think is extra-super-cool, is this technique can be used to create a custom feed for just about anything on your site, simply by adjusting the query_posts function at the top.

  3. Greg McAusland September 18, 2009

    Super awesome technique dude.

    Literally 2 days ago I was toying with the concept of building a custom RSS feed for a specific page parent in wordpress, with basically no idea how to do it.

    I swear you guys read my mind before writing tutorials these last few weeks

  4. Antoine October 5, 2009

    I really like this method, thanks for your tutorial.

    I’m trying to display in my custom feed an excerpt with a “Read more” link and 1 image on each post. This RSS feed will be used in MailChimp to send a daily post alert e-mails to our subscribers.

    Would you have an idea of help to do this?

    Thanks

    • The loop that is integrated within the custom feed template works just like any other WordPress loop. So you can include the_excerpt or any other tags and/or markup to get things working as needed.

  5. I want to create an audio only feed, for a WordPress site that I run (4thandelm.com). Do I follow the same steps, I don’t necessarily want/need the Tumblr posts.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry