Although WordPress has a *very* extensive plug-in collection, now and again things come up for which there are no suitable plug-ins available (yet). When I built PSDTUTS I thought it would be cool to have a way for users to submit links and to create a public link feed out of it. Today I'll show you how I hacked together a method using WordPress' comments.
Hack Together a User Contributed Link Feed with WordPress Comments
Jun 27th in Wordpress by Collis Ta'eedSo first of all if you're not sure what I mean by a User Contributed Link Feed, all you need to do is look in the sidebar of NETTUTS and you'll see our public link feed. You can subscribe via RSS or click to submit your own links. It's a neat little way to get more interactivity into the site, and to let readers leverage the traffic of the TUTS sites back to their own blogs and tutorials.
Rough Plan of Action
The first thing to do is come up with a plan of how it's all going to work. Here's our plan:
- First we'll create a special Post on our blog that will just have some short submission instructions
- Then we'll edit the comments.php file so that when this special Post comes up, it will display comments differently
- On those comments we'll change the regular comments form to be relabelled so that the fields fit a link submission
- Then we'll change the way comments display both on the post and in the comments RSS so that it makes sense
- Finally we'll make a bit of code to pull the latest 10 links and place them in the sidebar
Now the advantage of using the regular WordPress comments system is that there is already an approval and spam-catching workflow in place.
Step 1 - Create the Post
For my example today I'm going to be using the soon-to-launch AUDIOTUTS site that I've been spending the afternoon putting together. So we just make a regular Post with a title and some text, you can see me making mine in the screenshot:

And here it is on the AUDIOTUTS site:

Now it's important to find out what the Post ID is for our post. You can figure this out by editing the post you just created and looking at the URL for the edit post page. My edit post URL is "http://audiotuts.com/wp-admin/post.php?action=edit&post=3" so therefore the Post ID is 3!
Step 2 - Edit Comments.php
Next we're going to alter our comments.php file to look for the post with ID of 3 and to make that particular post's comments look different. Note that if you're interested to learn more about the comments.php file, we have a great tutorial here on NETTUTS called Unravelling the Secrets of Comments.php that is a great place to start.
So basically we're going to add a big if statement and if the Post ID is not 3 then we'll do our regular comments stuff, and if it is 3 then we'll change the way they are displayed AND how the form looks. Here's my comments.php file for AUDIOTUTS (note that I've commented out the regular comments stuff to make it clearer in regards to the link feed)
<? if ($post->ID != 3) {
// If the Post ID is *NOT* equal to 3 (our link feed post that we created earlier) then
// we execute the regular comments.php stuff in this space.
//
// I've deleted mine to make my code snippet a bit clearer
} else { ?>
<h2 style="margin-top:30px;">Previous User Submissions</h2>
<a href="#add" class="floated_link">Submit a Link</a>
<?php if ($comments) : ?>
<ol>
<?php foreach ($comments as $comment) : ?>
<?php if (get_comment_type() == "comment"){ ?>
<li id="comment-<?php comment_ID() ?>" >
<?php comment_author_link(); ?> <br />
<?php comment_text(); ?>
</li>
<?php } ?>
<?php endforeach; /* end for each comment */ ?>
</ol>
<?php endif; ?>
<div style="clear:both"></div>
<a name="add"></a>
<h2 style="margin-top:30px;">Submit a Link</h2>
<div class="formcontainer">
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">
<p><input type="text" name="author" id="author" value="" size="22" tabindex="1" />
<label for="author"><small>Link Title <?php if ($req) echo "(required)"; ?></small></label></p>
<input type="hidden" name="email" id="email" value="USER_LINK_SUBMISSION@AUDIOTUTS.com" size="22" tabindex="2" />
<p><input type="text" name="url" id="url" value="" size="22" tabindex="3" />
<label for="url"><small>Link URL</small></label></p>
<p><input type="text" name="comment" id="comment" value="" size="22" tabindex="3" />
<label for="url"><small>Link Description (Max 20 Words)</small></label></p>
<p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" class="button" />
<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" />
</p>
<?php do_action('comment_form', $post->ID); ?>
</form>
</div>
<div style="clear:both"></div>
<? } ?>
So let's analyse our code in two parts, first the form and then the comment display.
Step 3 - Altering the Comment Form
By default there are four form fields that WordPress uses to allow input of comments, they are:
- Author
- URL
- Comment
To receive a link submission we need three things:
- Link Title
- URL
- Link Description
So we'll map the four form fields to our three requirements like this:
- Author Field > Link Title
- URL > URL
- Comment > Link Description
And for the email field, we'll switch this to be a hidden form field and give it a value of "USER_LINK_SUBMISSION@AUDIOTUTS.COM", that will make the links a lot easier to spot when they are being approved in the comments approval.
So here's the form I'm using:
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">
<p><input type="text" name="author" id="author" value="" size="22" tabindex="1" />
<label for="author"><small>Link Title <?php if ($req) echo "(required)"; ?></small></label></p>
<input type="hidden" name="email" id="email" value="USER_LINK_SUBMISSION@AUDIOTUTS.com" size="22" tabindex="2" />
<p><input type="text" name="url" id="url" value="" size="22" tabindex="3" />
<label for="url"><small>Link URL</small></label></p>
<p><input type="text" name="comment" id="comment" value="" size="22" tabindex="3" />
<label for="url"><small>Link Description (Max 20 Words)</small></label></p>
<p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" class="button" />
<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" />
</p>
<?php do_action('comment_form', $post->ID); ?>
</form>
As you can see we have three <input type="text"> fields and one <input type="hidden"> for the email address. And though in the HTML these input fields still have their usual id's (author, url, comment), you can see in the text that the user sees they are labelled as link title, URL and link description. So that the form looks like this:

Step 4 - Displaying Previous Link Submissions
Next we'll format how the previous comments appear so that they also make use of our reusing the author, url and comment fields. Here's the code we'll use to display the links:
<?php if ($comments) : ?>
<ol>
<?php foreach ($comments as $comment) : ?>
<?php if (get_comment_type() == "comment"){ ?>
<li id="comment-<?php comment_ID() ?>" >
<?php comment_author_link(); ?> <br />
<?php comment_text(); ?>
</li>
<?php } ?>
<?php endforeach; /* end for each comment */ ?>
</ol>
<?php endif; ?>
So here's what we are doing
- First we check if there even are any comments
- If there are then we'll generate an ordered list <ol> of entries
- For each comment we publish an <li> element with:
- A linked author name - remember we've used these fields so that this will actually be the link title linked to the URL
- The comment text - or in other words our link description.
Step 5 - Updating the Comments RSS
Now the great thing about using comments is that, by default, there is an RSS feed for each WordPress post. The URL is simply the address for the post followed by '/feed'. So in our case it is: http://audiotuts.com/general/user-link-feed/feed/
The only problem is that by default the formatting of the comments RSS will create a feed that looks like this (in Safari):

So there are three problems:
- The title of the feed is "Comments On: User Link Feed"
- The link title says "By: ..."
- The link doesn't go to the URL, it goes back to AUDIOTUTS
So to solve these problems we have to edit the feed template. So we go into our WordPress install to /wp-includes/feed-rss2-comments.php, which is the template file for the comments RSS. Here's what the file has in it by default (in WordPress 2.5.1):
<?php
/**
* RSS2 Feed Template for displaying RSS2 Comments feed.
*
* @package WordPress
*/
header('Content-Type: text/xml;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:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><?php
if ( is_singular() )
printf(__('Comments on: %s'), get_the_title_rss());
elseif ( is_search() )
printf(__('Comments for %s searching on %s'), get_bloginfo_rss( 'name' ), attribute_escape($wp_query->query_vars['s']));
else
printf(__('Comments for %s'), get_bloginfo_rss( 'name' ) . get_wp_title_rss());
?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>
<description><?php bloginfo_rss("description") ?></description>
<pubDate><?php echo gmdate('r'); ?></pubDate>
<?php the_generator( 'rss2' ); ?>
<?php do_action('commentsrss2_head'); ?>
<?php
if ( have_comments() ) : while ( have_comments() ) : the_comment();
$comment_post = get_post($comment->comment_post_ID);
get_post_custom($comment_post->ID);
?>
<item>
<title><?php
if ( !is_singular() ) {
$title = get_the_title($comment_post->ID);
$title = apply_filters('the_title_rss', $title);
printf(__('Comment on %1$s by %2$s'), $title, get_comment_author_rss());
} else {
printf(__('By: %s'), get_comment_author_rss());
}
?></title>
<link><?php comment_link() ?></link>
<dc:creator><?php echo get_comment_author_rss() ?></dc:creator>
<pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_comment_time('Y-m-d H:i:s', true), false); ?></pubDate>
<guid isPermaLink="false"><?php comment_guid() ?></guid>
<?php if (!empty($comment_post->post_password) && $_COOKIE['wp-postpass'] != $comment_post->post_password) : ?>
<description><?php _e('Protected Comments: Please enter your password to view comments.'); ?></description>
<content:encoded><![CDATA[<?php echo get_the_password_form() ?></content:encoded>
<?php else : // post pass ?>
<description><?php comment_text_rss() ?></description>
<content:encoded><![CDATA[<?php comment_text() ?></content:encoded>
<?php endif; // post pass
do_action('commentrss2_item', $comment->comment_ID, $comment_post->ID);
?>
</item>
<?php endwhile; endif; ?>
</channel>
</rss>
Now we don't really need to know what most of that does, rather we'll just go through and change a few lines. The first line that we can fix is Line 18, which we change from this:
printf(__('Comments on: %s'), get_the_title_rss());
to this:
printf(__('%s'), get_the_title_rss());
Then we'll change Line 42 from this:
printf(__('By: %s'), get_comment_author_rss());
to this:
printf(__('%s'), get_comment_author_rss());
In both cases we are simply removing the extra words - "Comments on: " and "By: " - so that the feed makes more sense. So that was pretty easy. The next bit is a bit more complicated because we need to change where the URL is pointing. Now currently it points back to the post so that the user can follow comments on that post. Since this template controls *all* comment RSS feeds, we don't want to break that functionality so we need an if statement as follows:
<link><?php
if ($comment_post->ID != 3) {
comment_link();
} else {
echo $comment->comment_author_url;
}
?>
</link>
So here we are simply checking if the post has an ID of 3 (which in our example is the Post ID of the user link feed) and if it does then we publish the URL, and if not we do the regular comment_link() function. So the final RSS template looks like this:
<?php
/**
* RSS2 Feed Template for displaying RSS2 Comments feed.
*
* @package WordPress
*/
header('Content-Type: text/xml;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:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><?php
if ( is_singular() )
printf(__('%s'), get_the_title_rss());
elseif ( is_search() )
printf(__('Comments for %s searching on %s'), get_bloginfo_rss( 'name' ), attribute_escape($wp_query->query_vars['s']));
else
printf(__('Comments for %s'), get_bloginfo_rss( 'name' ) . get_wp_title_rss());
?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>
<description><?php bloginfo_rss("description") ?></description>
<pubDate><?php echo gmdate('r'); ?></pubDate>
<?php the_generator( 'rss2' ); ?>
<?php do_action('commentsrss2_head'); ?>
<?php
if ( have_comments() ) : while ( have_comments() ) : the_comment();
$comment_post = get_post($comment->comment_post_ID);
get_post_custom($comment_post->ID);
?>
<item>
<title><?php
if ( !is_singular() ) {
$title = get_the_title($comment_post->ID);
$title = apply_filters('the_title_rss', $title);
printf(__('Comment on %1$s by %2$s'), $title, get_comment_author_rss());
} else {
printf(__('%s'), get_comment_author_rss());
}
?>
</title>
<link><?php
if ($comment_post->ID != 3) {
comment_link();
} else {
echo $comment->comment_author_url;
}
?>
</link>
<dc:creator><?php echo get_comment_author_rss() ?></dc:creator>
<pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_comment_time('Y-m-d H:i:s', true), false); ?></pubDate>
<guid isPermaLink="false"><?php comment_guid() ?></guid>
<?php if (!empty($comment_post->post_password) && $_COOKIE['wp-postpass'] != $comment_post->post_password) : ?>
<description><?php _e('Protected Comments: Please enter your password to view comments.'); ?></description>
<content:encoded><
Step 6 - Displaying the Last 10 Items in the Sidebar
Next we need to display our most recent 10 items in the sidebar. Here's a little piece of code to do that:
<?php
$comment_array = array_reverse(get_approved_comments(3));
$count = 0;
?>
<ul class="linkfeed">
<? foreach($comment_array as $comment){ ?>
<? if ($count++ <= 10) { ?>
<li><?php comment_author_link(); ?> <br /><?php comment_text(); ?></li>
<? } ?>
<? } ?>
</ul>
So you can see here we are:
- Grabbing all approved comments from the post with Post ID = 3 as an array and reversing them so that we get the most recent first
- Then we create a <ul> element and for each comment in the array up to 10 we print out an <li> element with the link, title and description
And with a bit of styling here's how the result looks:
Finished!
So that's it! I also like to burn the feed via Feedburner so I can track how many people subscribe. So far it's been quite a useful feature, here at NETTUTS we have about 150 subscribers to the link feed, at PSDTUTS we have close to 500. So they are a good way of letting the community know about new links and they keep the site regularly updated.
I've recently contracted the fabulously talented Joshua Blount to build this into a WordPress plugin. Once it's all finished I'll make sure he releases it here as our first bit of NETTUTS open source :-)
Related Posts
Check out some more great tutorials and articles that you might like










User Comments
( ADD YOURS )Igor Quint June 27th
Great tutorial!! very helpful in my situation!
Andrei Constantin June 27th
Nice one. I was actually looking at wordpress site for a plugin like this.
To be honest never though about it. Thanks again nettuts
Callum Martin June 27th
AUDIOTUTS? where’d that come from?
MD June 27th
Thanks! it is really useful!
Josh Drake June 27th
Nice tutorial! I can’t wait for AudioTuts to come out too!
pickupjojo June 27th
Great tip, I think I’ll use it soon on my blog.
Ben Griffiths June 27th
First of all - nice sneaky way to introduce a new site! Second, thanks for the great tut. WordPress can be a real nightmare to work with, especially for complete custom content like this. Thanks for the great guide
K3v June 27th
Very usefull tutorial, thanks!
Lamin Barrow June 27th
I am not a huge PHP fan but i will keep this in mind just in-case i start playing agian with wordpress i have on my local machine. Thanks for the tut.
Danny June 27th
This is such a great way to keep a community together
Taylor Satula June 27th
Why does nettuts look so bad audiotuts vetortuts and psdtuts all look good
Taylor Satula June 27th
ya but then you get link spam with this if you have a large user base
Chris June 27th
I love you guys!
Jeff Finley June 27th
Awesome, I’m going to implement this into the new GoMediazine theme now. Should be live next week.
chris rock June 28th
Wouldn’t it have been easier to make a page, put it on private and simply link to that page? Just for the submission part.
flisterz June 28th
Awesome! The hidden email field is brilliant. Going to use this for my project. Thanks a lot!
James June 28th
Gawd! Not another Eden.cc site! Don’t you people ever get tired! Your making the rest of the internet look bad!
Anyway… Thanks for the tut Collis!
Dan June 28th
Seriously thanks for this, this is a great tut. Probably my favorite so far, and extremely useful.
Thanks.
Shane June 28th
Interesting tutorial - thanks for posting.
Wordpress is a fantastic free blogging tool, but you put it quite right when you say ‘hack together’ - when you want to do something out of the ordinary, it does feel like you’re hacking stuff.
Asmaa June 29th
Thanks so much collis for sharing this little but practicle tip i have been searching for a way to implement this on my blog . Your tutorials Rock REally!!
Asmaa June 29th
One Question! how to disable Gravatar for the post? it seems is i am logged in and have gravatar my own link shows up instead !
Braden Keith June 30th
This is very soon going to come in handy with the redesign of my site coming up. Thanks, bookmark now.
Joefrey Mahusay June 30th
This is very helpful to us Wordpress developer. Thanks Collis!
Tom July 1st
One of the best Wordpress hacks ever seen. Well done, I’ll definitely use this trick on my future projects.
Bárbara July 1st
Great, great, great!!! Thanks!
Taylor Satula July 1st
Someone should make a plugin from this tut. That would make me smile
Xenostar July 2nd
When I’m logged in to my account at my site, this doesn’t work because it uses my address and url that I have registered to my account rather than from the form that was filled out. Any ideas?
Sam P. July 2nd
Sweet tut, can’t see where i’d use it myself yet… add it to the coming soon list
Jeff Finley July 3rd
I’ve been trying to get this to work on my site, but I’m still stuck on Step 1. It’s frustrating.
You didn’t explain where in comments.php to put the new code: ID != 3) { Do I put it at the very top of the page? No matter where I put it I got an error “Parse error: syntax error, unexpected ‘<’
I’m not really experienced with PHP, but it seems like those if and else statements aren’t working for me. I need some help!
Wim July 7th
Great tutorial!
Thanks
Dave August 10th
I am also Stuck like Jeff Finley. Where do you put the code?
ziggy101 August 18th
This is an interesting concept, but seems it’s lacking as a tutorial, especially the editing of the comments.php. This wouldn’t be a big issue, but it seems the author(s) here don’t reply to comments/questions.
James August 21st
Gonna use this on my site… I’m surprised there isn’t a plugin which does the same job.
Matt August 22nd
Great post. I was looking for something like this for a while now. I am going to have to use this on my redesign.
Thanks!
Ian August 24th
@ Jeff Finley and Dave
I’ve just had a go at this and you need to add the if statement “ID != 3) { ?>” code (Note: in addition to what’s stated in the tutorial the code needs a trailing “?>”) directly after the “” message in the comments.php file.
Also you need to begin the else clause (added right at the very bottom of your existing comments.php file) with a “<?php” so it would read:
<h2 style=”margi….
Hope this helps.
Dave August 25th
@ Ian Thanks alot I believe I got it to work now.
liz August 25th
@Xenostar (and any others who have issues with the URL being overwritten if you’re logged in):
Had this same problem too and here’s the fix:
- Open wp-comments-post.php in your root wordpress install directory
- Go to line 42, find this chunk of code:
$user = wp_get_current_user();
if ( $user->ID ) {
$comment_author = $wpdb->escape($user->display_name);
$comment_author_email = $wpdb->escape($user->user_email);
$comment_author_url = $wpdb->escape($user->user_url);
- Now, replace it with this chunk:
$user = wp_get_current_user();
if ( $user->ID ) {
if ($comment_post_ID !=3) {
$comment_author = $wpdb->escape($user->display_name);
$comment_author_email = $wpdb->escape($user->user_email);
$comment_author_url = $wpdb->escape($user->user_url);
}
As in the original tutorial, make sure you replace the “3″ with whatever POST ID your submission page is.
Hope this helps.
styletime September 1st
still cant get it working @Ian can u help me@styl.eti.me? ;(
Windows Themes September 5th
Useful tutorial. Thanks
Cory September 17th
Fantastic concept. I think the tutorial is a bit vague at times, so I had to play around a bit to get it to work. However, I did get it working.
My problem now is that I’m unable to moderate the submitted links even though I’ve checked the appropriate setting to moderate all comments. Any ideas to get the moderation up and running?
Thanks!
Jeremy Newton October 1st
I would love to get this working but for the life of me I could now get it working =(
Andy Bailey October 3rd
if ($count++ <= 10)
that just helped me more than the tutorial lol! thanks for a great tutorial, I can see what to do with my tutorials now
TEEstrict October 11th
hi, if i follow this tutorial, i got both = the regular commentfield and the submitfield. but as i got it right, its an if-post-id-thing, so why it’s showing also the regular comments?
thanks so much for help in advance.
TEEstrict October 11th
puh i really go crazy with that issue. please, ian, gimme some help
i really don’t get it why i can not show only the submitfield (if i use your code).
how can i realise to hide the regular commentarea in this special post. your code contains exactly that or? but why it doesn’t work at my example post?
thanks so much for your help!
FataL October 11th
And how can i remove nofollow function from that same post ?
I could do all this by myself, but nofollow is the tricky part ( at least for me )
yongming October 13th
GOOD TUTURIAL! I was looking for many blogs. now i see it.
thanxx 4 this tutorial
greg October 19th
Hi,
Please, create tutorial: component&module User Link Feeds for CMS JOOMLA. This extension is dont exist for this cms system.
Brokakeroko October 20th
I like your site. Brokakeroko
Blograzy October 21st
Amazing.. i just love the way you step the process.
Big fan!
Do take a look at my blog http://www.blograzy.com
Jhay November 12th
Had a problem, hope someone help. Regular comments still show up and it get info data from the User Link Feed acting like an ordinary post comments. Help!!
Jhay November 29th
Yatte! It now works without the regular comment.. no more double post and I’ve created a ‘page’ instead of a ‘post’ check it out here Clicky.
Thanks NT for this awesome tutorial!
Kasper Michael de Thurah December 13th
Hi there,
I have a big problem. I have followed the tutorial, but…
I added a feed to the community feed:
Name
Link url
Desc.
When I subscribe to my community feed’s feed, I can only get a list of feeds submitted with describition and not the actual content of their feed. Can you follow me?
My blog is in danish, so it can be a bit hard for you to understand, but please write me at dt@aarhusdesign.com if you think you can help me or comment here. Thank you so much!
A question - I have called my new page Community Feed - is the rss feed url not http://www.mywebsite.com/community-feed/feed/ ??
Kasper Michael de Thurah December 13th
I think I misunderstood the functions a bit
Thought the list on the sidebar was the recent stories from the feeds submitted - actually the function i was lookin’ for…
Sorry for the mistake, -does anybody know a plugin or a way to show rss stories from your friend in a merged list? NOT like the regular rss-widget where they are seperated, but in a merged list with the newest on top?
Greetings from Denmark to all of you
Tim December 31st
I would really like to incorporate this on my website but I can’t get it to work. Are there any further instructions available?
I’m an absolute novice with PHP. I’ve run the script through phpDesigner and I keep getting a fatal error message on a line that has this:
Why would that line cause a fatal error?
Tim December 31st
”`
I guess code has to be in between hash marks?
Hein Maas January 6th
Great tutorial, need to know if it’s possible to do this with a page instead of a post
John Wang January 7th
How does this impact WordPress’s Automatic Update now? Since it’s changes to the core code, I imagine updating is a bigger hassle.
Also, I found this plug-in which seems to do something similar.
http://wordpress.org/extend/plugins/fv-community-news/
Add Your Comment
( GET A GRAVATAR )Your Name January 9th
Trackbacks