Create an Articles-Only Feed
WordPress makes it easy to publish content in any number of categories, with any number of tags, and with any type of custom post format. So for example, in addition to full articles, you could also offer screencasts, links, side posts, tweets, and all sorts of other peripheral content. Complementary material may work great for visitors surfing around your site, but including all of that extra stuff in your RSS feed dilutes the potency of your main articles. The idea here is that your visitors will subscribe to the more focused content.
In this post, we create a custom, “articles-only” feed for visitors who want to subscribe to the main content only, without all the side stuff. The technique is actually pretty flexible, and works great to create just about any type of custom WordPress feed content. It’s pretty easy to do, requiring a whopping two steps to make it happen..
Step 1: Create the custom page template
Go to your theme directory and create a new PHP file named
article-feed.php. Then add the following code (don’t worry it’s actually not that bad):
<?php /* Template Name: Article Feed */ $numposts = 10; // number of posts in feed $posts = query_posts('showposts='.$numposts.'&cat=3'); $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>
This is basically just a typical WordPress feed template, but with some extra query action to make it do what we want. In the first few lines of code, we specify how many posts to display, which categories to include, and whether to display full posts or excerpts:
$numposts = 10; // number of posts in feed $posts = query_posts('showposts='.$numposts.'&cat=3'); $more = 1;
Using this default code, the custom feed will show 10 posts from category 3. And with
$more set to
1, the full article will be included in the feed. This is where you customize your new feed to include whatever you want. So for example, if we post articles in three different categories, say with IDs of
3, we would modify our code to look like this:
$numposts = 10; // number of posts in feed $posts = query_posts('showposts='.$numposts.'&cat=1,2,3'); $more = 1;
query_posts function is quite flexible and provides all of the parameters needed to set up just about any customized feed content. You can exclude/include categories, display specific types of posts, change the number of posts displayed, and so much more. For a full list of options, check out query_posts at the WordPress Codex.
Step 2: Create the custom Page in the WP Admin
Once you have the custom Page Template uploaded to your server, log into the WordPress Admin and visit the “Add New Page” screen (Pages > Add New). Create a new page named “Articles-Only Feed” (or whatever), and select the newly added “articles” page template from the drop-down menu:
While you’re there in the Admin creating this new custom-feed page, take a moment to be mindful of the feed URL and title, which may be set to whatever works best:
Once everything is ready, finish it up by publishing the page to your site. Then check that your new feed is working by visiting the URL of the new page you just created in the WP Admin. Here at DigWP.com, our articles-only feed is available at
Wrap-up + additional resources
In addition to the easy-breezy two-step custom-feed tutorial in this post, here are some additional resources that are sort of related to this general topic:
Why bother copying code instead of simply including native feed template?
Also there is nifty
add_feed()function for creating custom feeds, extra page is not typically needed.
Yes, that sounds like another good way of doing it. I find that a custom page template provides more flexibility, but whatever works best. Plus it works great and is simple to explain, so I thought I would share. Thanks for the tips!
There’s also a great plugin called More Types that adds custom post types. It creates a new menu item that we’ve found really useful, especially in conjunction with its sister plugin More Fields (bet you can guess what that does). You still need to build a custom page template as above, but this really helps with the user experience.
Or, probably the simplest way, append a
/feed/(if you have pretty permalinks enabled) or
?cat-3&feed=rss2(if default permalinks are enabled) to the end of the article category URL and let WP do all the heavy lifting for you.
That way is good to handle feeds because you can turn to query_posts parameters.
Thanks for share.
I keep getting “XML Parsing Error: XML or text declaration not at start of entity”.
There are two line breaks being inserted before the
<?xmldeclaration. Any idea why?
Nevermind. I found the issue. There were extra spaces in my functions.php file that were appearing before the content header.
Tried for hours to find where to change the Twenty Eleven comment heading (reply-title) “Leave a Reply” in both the code, the css and the database, with no luck. Just want it to say “Comment or Question?”. Saw one suggestion using a filter, but for an earlier theme.
My kingdom for a solution!
Thanks, I appreciated the helpful post! I followed your simple instructions and in only a few minutes had it working!
But am I correct that this will only work with Pages, and not Posts? This is cool, but it won’t work for many of us who’ve been using Posts for our articles. Any solution for Posts, rather than republish all back articles as Pages? Thanks, Matth
Just to clarify, the custom feed built in the article generates a feed that contains posts from whatever category or categories, tags, or any other set of posts possible via
query_postsor similar. That said, I would look into custom post types to set up a custom feed template that may be used for a specific post. It should be do-able, but I haven’t tried it yet.
Got it now, thanks. I misunderstood. The creation of the Page in the example above is just for the feed URL. That seems pretty obvious now. :0