When I last looked at customizing feeds in WordPress, it was all to do with being able to offer a summary and full text feed simultaneously—making use of WordPress' flexible feed URL syntax and a .htaccess file. In this post I look at modifying the actual contents of the feed using a functions.php file (which may already exist as part of your current theme).
Just as WordPress provides a number of hooks for adding or removing actions in your theme header (see here), so to do the core files that generate your feeds. Editing the core files is however discouraged (it makes upgrading a pain), and although you can build your own replacement feed templates an easy alternative is adding a few lines to your theme's functions.php file.
As a perpetual PHP beginner I feel obliged to warn you that use of the following code is at your own risk.
If there are any PHP/ WordPress experts reading this who can improve on my code please make yourself known ;-)
Removing WP version info
Somewhere, a while back, I read a tip about not including the WordPress version you are running in your template header—potentially allowing hackers to identify you as a target if you haven't kept up-to-date. It's easy to remove if present. For example, in the K2 theme just delete the following line from header.php:
<meta name="generator" content="WordPress <?php bloginfo('version'); ?>" />
I recently released that version information was still being sent out in my feed. The feed XML contained a line like this:
<generator>http://wordpress.org/?v=2.x</generator>
Thanks to Peter Westwood's helpful post I used my theme's functions.php file to remove this with the following code:
//Remove WP version info
function hide_wp_vers() { return ''; }
add_filter('the_generator','hide_wp_vers');
So wherever the_generator function is called (such as in the feed templates in /wp-includes) it gets replaced with... nothing. Job done.
Adding a feed image
A feed image (e.g. your site logo or avatar) is an optional part of the RSS 2.0 spec and shows up in some feed readers along with the feed description. There are plenty of tutorials (search Google) that tell you how to add a feed image by editing core template files, and there are plugins that will add one for you. I had previously edited my core RSS 2.0 template, and lost the changes during upgrades more than once. To avoid this in future here's what's now in my functions.php file:
//Add a feed image
function feed_image() { echo "<image>\n\t\t<title>bioneural.net</title>\n\t\t<url>http://www.bioneural.net/images/kiwi-yellow-64px.png</url>\n\t\t<link>http://www.bioneural.net</link>\n\t\t<width>64</width>\n\t\t<height>64</height>\n\t\t<description>bioneural.net</description>\n\t</image>\n"; }
add_action('rss2_head', 'feed_image');
Having created my feed_image function I use add_action (Codex) to insert my function via the rss2_head hook (Codex).
Note that \n means new line, \t means tab, and \r (not shown) carriage return: these are just for the sake of formatting. They have no function other than making the feed XML—which you will likely never see—look more organized:
<image>
<title>bioneural.net</title>
<url>http://www.bioneural.net/images/kiwi-yellow-64px.png</url>
<link>http://www.bioneural.net</link>
<width>64</width>
<height>64</height>
<description>bioneural.net</description>
</image>
Here's how the above renders when viewed in Bloglines:

Tip: If you want to add a feed image but don't want to do it via a plugin or functions.php, you can use Feed Image Burner from FeedBurner.
Adding a content license
I've noticed a rise in my content appearing on splogs, usually in the form "[Some random name] wrote an interesting post today: here is an excerpt". This violates the Creative Commons licensing of my content, which requires correct attribution. In a similar vein I've noticed some of my images turning up on "all rights reserved" sites with no attribution. While some folk are no doubt just ignorant, the sploggers are simply morons who don't give a damn. I can't do much about the latter (although I'm giving AntiLeech a spin) but it did get me wondering what I can do to improve the visibility of my licensing terms for the benefit of those "unaware".
The Creative Commons Wiki links to an RSS 2.0 module for annotating feeds. While this may be machine-parsable I've yet to come across a feed reader that actually picks up on it. As well as incorporating this extension I wanted to add a human-readable annotation to each feed item. This one took a bit of figuring out:
//Add CC license to namespace, item, inline img link within description
function add_license_ns() { echo "\n\t" . 'xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"' . "\n"; }
add_action('rss2_ns', 'add_license_ns');
function add_license_item() { echo "\t" . '<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/2.5/</creativeCommons:license>' . "\n"; }
add_action('rss2_item', 'add_license_item');
function add_license_img($join) {
$join = _e('<p><a href="http://creativecommons.org/licenses/by-nc-sa/2.5/" rel="license" title="This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.5 License"><img src="http://www.bioneural.net/wp-content/themes/k2bn/styles/bioneural/cc.png" alt="CC" /></a> From <a href="http://www.bioneural.net/about/terms/">bioneural.net</a>:</p>') . the_content();
return $join;
}
add_filter('the_excerpt_rss','add_license_img');
The first function writes the required namespace declaration; add_action then adds this via the rss2_ns hook (Codex). The next function/ action pair writes the module to each feed item using rss2_item (Codex). The third part is the human-readable bit: writing the image, text, and links and concatenating these with the_content() (Codex) to replace the_excerpt_rss() (Codex). Note also the use of the rel-license microformat.
For this to work you must set your Reading Settings in WordPress to Summary, even though we will be displaying the full text (replacing the_excerpt_rss() with the_content()).
The XML will look like this (edited for clarity):
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
...
xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>
<channel>
...
<item>
<title>Web developer widgets</title>
...
<description><![CDATA[<p><a href="http://creativecommons.org/licenses/by-nc-sa/2.5/" rel="license" title="This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.5 License"><img src="http://www.bioneural.net/wp-content/themes/k2bn/styles/bioneural/cc.png" alt="CC" /></a> From <a href="http://www.bioneural.net/about/terms/">bioneural.net</a>:</p><p>Mac-based web developers...</p>]]></description>
...
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/2.5/</creativeCommons:license>
</item>
Rendered in a feed reader humans will see this:

The Creative Commons icon is hopefully recognisable and links to the correct license; the link to bioneural.net links to additional terms of use.
Tip: If you prefer not to have full text feeds containing HTML tags, you could use the_content_rss('', '', '', 250) (Codex) in place of the_content() to produce a 250 word text-only teaser.
Expanding the feed description
The text of the feed description is ordinarily the same text that appears as the tagline for your blog (set in General Settings). You might want to keep it short in your blog header, but perhaps send a more informative version out with your feed.
In K2 at least the description is only used in the head:
<meta name="description" content="<?php bloginfo('description'); ?>" />
and header:
<p class="description"><?php bloginfo('description'); ?></p>
One solution is therefore to replace the PHP call with short fixed text descriptions (e.g. "stuff worth sharing") in your theme template (header.php) and make the description/ tagline in WP General Settings longer, so it gets into your feed e.g.:
<description>bioneural.net is for stuff worth sharing: commentary by Bruce McKenzie. Major topics covered are gadgets, informatics, Internet, Mac, mobile, musings, New Zealand, photography, Project Koru, quicklinks, rant, rave, travel and Windows</description>
I was unable to successfully utilize rss2_head (Codex) in a way that avoided duplicate descriptions.
Tip: Another way to add a more detailed description to your feed only is to use Title/Description Burner from FeedBurner.
Adding a category image
I previously used the now neglected Category Image(s) plugin to send out a category icon with each feed item, replicating their use on my blog to readily identify Mac-related posts, etc. All I needed to do was replace the default item description with this:
<description><![CDATA[<?php c2c_the_category_image(); ?><br /><br /><?php the_excerpt_rss() ?>]]></description>
Sadly such a trick doesn't work with the Category Icons plugin I am now using, but I've been in touch with the plugin author and submitted this as a feature request.
Update 10.05.08: As of v1.9.8 Category Icons allows RSS feeds to display the category icons.









Simply adding an image link in the General Settings - Tagline will put desired image in RSS2 feeds.
Also, if you want a different "excerpt" or synopsis of a feed without people having to read the post. or the first few lines of your post is not suitable for an excerpt - write a different one in the "Excerpt" box ;)
Interesting idea D. Although this does trick the Feed Validator an img inside
<description>is not consistent with the RSS 2.0 spec, which specifies a required "Phrase or sentence describing the channel" and puts feed images inside a separate<image>channel sub-element. Furthermore, any URL entered as a tagline is rendered as text in the blog header.Correct. I've always put my "intro" into ecto's main editing area, with the main body of the post in the "Extended" editing area. When I post these two areas are automatically separated by
<!--more-->. But ecto also has a "Summary" editing area, which can contain a different version of the article known as the "excerpt". I've never used this, but if I did I imagine the contents would be used forthe_excerpt()in place of the post intro.So technically I guess I'm not using
the_excerpt()in my feeds or on my blog, but rather Summary in Reading Settings means "intro" and Full text means "intro + extended" using only thethe_content(). Confusing, huh?I wonder how many other folk using offline editors are doing this without realizing the bit of their post before
<!--more-->is part ofthe_content()and notthe_excerpt()? This would explain why I had to set Full text to get my hack to work.I've been using this for years - as I don't use the straplines/sub headers - RSS 2 Specs say "<image> is an optional sub-element of <channel>" - so is that within an element within the channel or does it really want a separate element?
Setting the excerpt can be far more descriptive in isolation - depends to a large degree on which news reader you use of course.
I just tried subscribing to your feed in Bloglines D.: the feed description is "<img src="http://david-hall.net/images/gravatar.png" />~ artist in nature ~" and, interestingly, your feed image does show.
However, viewing your XML source in NNW you have this nested in the <description> tag. The spec requires a feed image to be within an <image> tag and, if that is used, with 3 required sub-elements for url, title , and link. Check on Google for XML examples (e.g. here) to be convinced of the uniqueness of your approach ;-)
Yep, seen that. I checked it in most readers I could think of, when designing the Demeter rss.xsl files, and it seems to work :)
This Decription tag must be where WP puts the Tagline then, I suppose I could wrap it in more tags... The other required sub-elements can be as for the main feed.
Yes, WP properly inserts the tagline/ feed description via
<?php bloginfo("description") ?>in theme/header.php and<?php bloginfo_rss("description") ?>in wp-includes/feed-rss2.php.Adding more tags in Reading Settings won't make it any more valid D. since you still can't nest
<image>inside<description>; they should be on the same level inside<channel>.Hi Bruce,
to add category icons in the feeds, I tried this and it worked (I don't know if the code will appear correctly) :
function bm_caticons_excerpt_rss($content) {
$content = get_cat_icon('echo=false&link=false').''.$content;
return $content;
}
add_filter('the_excerpt_rss','bm_caticons_excerpt_rss');
Thanks Submarine. I tried this, disabling my above customizations, turning off the AntiLeech plugin in case it was interfering... but the best I could do was the following error on feed validation:
Deactivating/ reactivating had no effect.
Bruce, here is a link to a post I wrote about this error.