Separating Pings from Comments in WordPress 2.7
WordPress 2.7 has introduced many new features surrounding comments. Of these is AJAX commenting and threaded comments. To take advantage of the later, you must use a function wp_list_comments instead of the old way of looping through the comments array with a foreach. Weblog Tools Collection has a good how to on the old way that can be found here.
I wanted to get this hashed out before 2.7 goes live so that theme designers and anyone else can implement this in time for the release.
I’ll be referencing the default theme from 2.7 in this how to. If you are interested in adding the new commenting features to your current pre 2.7 theme see this how to by Otto.
wp_list_comments is not documented yet on the WordPress codex. But some feature that are worth mentioning are the ability to specify the comment type to display and a callback so that you can decide how to structure the output.
Let us start by taking a look at the new comments “loop”:
<?php if ( have_comments() ) : ?>
<h3 id="comments"><?php comments_number('No Responses', 'One Response', '% Responses' );?> to “<?php the_title(); ?>”</h3>
<ol class="commentlist">
<?php wp_list_comments(); ?>
</ol>
<div class="navigation">
<div class="alignleft"><?php previous_comments_link() ?></div>
<div class="alignright"><?php next_comments_link() ?></div>
</div>
<?php else : // this is displayed if there are no comments so far ?>
<?php if ('open' == $post->comment_status) : ?>
<!-- If comments are open, but there are no comments. -->
<?php else : // comments are closed ?>
<!-- If comments are closed. -->
<p class="nocomments">Comments are closed.
<?php endif; ?>
<?php endif; ?>
As you can see it is much simpler than the old comments “loop”. The majority of everything that is happening is now done via the function wp_list_comments.
To remove pings (pingbacks and trackbacks) we only need to make a few small changes. First open up your themes single.php:
Find the following code:
<?php comments_template(); ?>
And change it to:
<?php comments_template('', true); ?>
The above change tells comments_template to create a global array $comments_by_type that we will use later on.
First open up comments.php.
Look for the following code:
<?php if ( have_comments() ) : ?>
Directly below this add:
<?php if ( ! empty($comments_by_type['comment']) ) : ?>
Change this:
<?php wp_list_comments(); ?>
To this:
<?php wp_list_comments('type=comment'); ?>
Directly below the wp_list_comments function we modified is:
</ol>
Directly below this add:
<?php endif; ?>
The if statement prevents the comments heading and ol tags from displaying if you only have trackbacks and pingbacks on this post.
Much easier so far, right?
To display the pings we need to insert the following code beneath the endif we just added:
<?php if ( ! empty($comments_by_type['pings']) ) : ?>
<h3 id="pings">Trackbacks/Pingbacks</h3>
<ol class="commentlist">
<?php wp_list_comments('type=pings'); ?>
</ol>
<?php endif; ?>
The comments “loop” should now look like this:
<?php if ( have_comments() ) : ?>
<?php if ( ! empty($comments_by_type['comment']) ) : ?>
<h3 id="comments"><?php comments_number('No Responses', 'One Response', '% Responses' );?> to “<?php the_title(); ?>”</h3>
<ol class="commentlist">
<?php wp_list_comments('type=comment'); ?>
</ol>
<?php endif; ?>
<?php if ( ! empty($comments_by_type['pings']) ) : ?>
<h3 id="pings">Trackbacks/Pingbacks</h3>
<ol class="commentlist">
<?php wp_list_comments('type=pings'); ?>
</ol>
<?php endif; ?>
<div class="navigation">
<div class="alignleft"><?php previous_comments_link() ?></div>
<div class="alignright"><?php next_comments_link() ?></div>
</div>
<?php else : // this is displayed if there are no comments so far ?>
<?php if ('open' == $post->comment_status) : ?>
<!-- If comments are open, but there are no comments. -->
<?php else : // comments are closed ?>
<!-- If comments are closed. -->
<p class="nocomments">Comments are closed.
<?php endif; ?>
<?php endif; ?>
Now the pings are displayed below the comments. The above code will show the pings in full comment boxes. I personally like a simple ordered list with a link and title of the ping. To achieve this without a foreach (Thanks Ryan Boren for the tip!)
Open your themes functions.php file and create a callback function for wp_list_comments. The following code should be inserted:
<?php
function list_pings($comment, $args, $depth) {
$GLOBALS['comment'] = $comment;
?>
<li id="comment-<?php comment_ID(); ?>"><?php comment_author_link(); ?>
<?php } ?>
Replace this:
<ol class="commentlist">
<?php wp_list_comments('type=pings'); ?>
With this:
<ol class="pinglist">
<?php wp_list_comments('type=pings&callback=list_pings'); ?>
If your theme doesn’t have a functions.php just create it and include the above code.
In this case our full comment “loop” should now look like:
<?php if ( have_comments() ) : ?>
<?php if ( ! empty($comments_by_type['comment']) ) : ?>
<h3 id="comments"><?php comments_number('No Responses', 'One Response', '% Responses' );?> to “<?php the_title(); ?>”</h3>
<ol class="commentlist">
<?php wp_list_comments('type=comment'); ?>
</ol>
<?php endif; ?>
<?php if ( ! empty($comments_by_type['pings']) ) : ?>
<h3 id="pings">Trackbacks/Pingbacks</h3>
<ol class="pinglist">
<?php wp_list_comments('type=pings&callback=list_pings'); ?>
</ol>
<?php endif; ?>
<div class="navigation">
<div class="alignleft"><?php previous_comments_link() ?></div>
<div class="alignright"><?php next_comments_link() ?></div>
</div>
<?php else : // this is displayed if there are no comments so far ?>
<?php if ('open' == $post->comment_status) : ?>
<!-- If comments are open, but there are no comments. -->
<?php else : // comments are closed ?>
<!-- If comments are closed. -->
<p class="nocomments">Comments are closed.
<?php endif; ?>
<?php endif; ?>
One last (optional) task is to modify the comment counts to only reflect the number of comments minus pings.
Open your themes functions.php and add the following code:
<?php
add_filter('get_comments_number', 'comment_count', 0);
function comment_count( $count ) {
if ( ! is_admin() ) {
global $id;
$comments_by_type = &separate_comments(get_comments('status=approve&post_id=' . $id));
return count($comments_by_type['comment']);
} else {
return $count;
}
}
?>
Again if your theme doesn’t have a functions.php just create it and include the above code.
There you have it. If you have any questions let me know.

good write up, thanks.
Absolutely fantastic tutorial! I was wondering if there was going to be a function of the new comments API that would allow this to happen more easily.
I just tweeted this :-)
I just updated the how to with a tip from Ryan Boren about using a callback in wp_list_comments to build the output the way that you want it.
Nice one. :-)
I hope some senior coder will create dedicated page for “wp_list_comments()” on wordpress.org Codex. Because Codex is missing a lot of docs. :-(
Just updated the how to. The comments_template function now accepts an argument for separating comments.
<?php comments_template('', true); ?>When this change is made in single.php the array $comments_by_type will be defined and will not have to be created by the theme itself.
Hi thanks a lot for this instructions – it saves me time ;)
I have a question: Do you know where we can translate the new comments in our language? Because I would like to have another sentence for *your comment is awaiting ….* and I would like to have this in my language German ;)
thanks
Monika
Hey Matt, thanks for the info’s.
However, this doesn’t work / works strange when comment paging is enabled. All Pingbacks/Trackbacks are listed only on the first page (the page with the oldest comments). In my case, they should be on every page after the comment form. Any workaround for this?
Same issue with Pete. The code doesn’t play nice with paged comments.
Thanks for the info.
Hopefully your code will still work without modification after the fix.
Also sorry about the double comment earlier.
Everything should be working as intended now. Only issues you will run into by passing a type or a $comments array is that the “Recent Comments” widget will likely link to the wrong comment page. Not the end of the world though.
@Monika:
Just use a custom callback function for displaying your comments rather than using the default one that wp_list_comments() provides.
Basically have function like the list_pings() this post describes, but instead designed for comments.
Is it possible to count the trackback too? How to do that?
Since I hacked my wp_list_comments already to handle some formatting, I found this to work:
<?php wp_list_comments(array('type'=>comment, 'avatar_size'=>48, 'reply_text'=>'Reply to this Comment')); ?>Now I just have to turn ping/trackbacks back on. Thanks!
Thank you very much, it works like a treat.
Works like a charm!
Thanks for taking the time to write this up! Just used it on a theme on the latest 2.7, and works 100%
Cheers
Richelo
Thank you very much for this useful code. Although it’s pre 2.7, it seems to work! Lifesaver.
I would have to say this is the most straightforward and easy guide on how to separate comments from pings. Thanks!
Hi
Thanks for the tut.. One question!
What do you do if your theme does not have a single.php file??
Mike
@ Mike: check your index.php file for a line along the lines of:
<?php if (!is_single()): ?>Code here
<?php endif; ?>
This indicates that the index will double as a single.php showing everything that is (different) within the is_single statement (sometimes also listed as is_singular). Hope this helps
@ Matt: there is a minor issue with the last code snippet of yours, it can be that you get a “Fatal error: Only variables can be passed by reference in….” in your functions.php file using that. If someone has this problem I would suggest changing:
add_filter('get_comments_number', 'comment_count', 0);function comment_count( $count ) {
global $id;
$comments_by_type = &separate_comments(get_comments('post_id=' . $id));
return count($comments_by_type['comment']);
}
with
add_filter('get_comments_number', 'comment_count', 0);
function comment_count( $count ) {
global $id;
$get_comments= get_comments('post_id=' . $id);
$comments_by_type = &separate_comments($get_comments);
return count($comments_by_type['comment']);
Cheers,
ALEX
Hello there! I see that you’ve done some nice and well-needed upgrades to the 1024px theme. Would you want to contribute to my forthcoming (and also well-needed) 2.7 compability upgrade and join me as a co-author of the theme? I could use some help, since I’ve overloaded with work and feeling that I’m not really able to keep the theme up to date. Contact me if you are interested! :)
Great step by step tutorial! It was really easy to implement.
Thanks. :)
good~!
It is a good article,thanks for your sharing.
I have used this method to separate my pings and comments, together with the wp comments navi plugin.
For pages with pings, the wp comments navigation paging does not shows up. Any idea what might be happening? :(
It worked for pages without pings though. Is the plugin incompatible with this method or..?
Any help or advice is greatly appreciated. Thanks :)
Somehow I can’t get this to work. When I put the code in, my theme breaks and some posts – although they do have comments – do not display the comments anymore. And if I post a new test comment to a post with visible comments, all comments disappear. :-/ Any idea what I’m doing wrong?
great guide which I’ve implemented, but how do I get the pings to all go together on the last page rather than spread out over various pages e.g:
http://www.connectedinternet.co.uk/2005/12“>Page onepage 2
Thanks
Hi
not sure if my previous comment made it. Great writeup but my trackbacks are seperated if I have comment pagination on e.g:
- page 1
- page 2
How do I get all the trackbacks together?
Thanks
EB
I’m trying to do this as well. How do we list all the trackbacks on all the pages? Thanks :)
Thanks so much for this. I was a bit hesitant about editing the source but your instructions were easy to follow and I now have separated comments and pings!! Much better.
Thanks so much for this. Have been using it for few blogs
I’m a noob at this, so don’t hate me when I say this..
I don’t understand what you mean by create a callback function for the functions.php file. What code should I be putting in there exactly.
Thanks for the information. I test it and it works fine.
it is just what i want, thanx.
Nice one. But will it work in 2.8?
@Silver Firefly: It will. There really wasn’t anything changed as far as comments are concerned in WordPress 2.8.
Thanks mate, just what I needed to hear! :-)
Thanks for this discription. Great step by step tutorial. It was very easy to implement :-)
did anyone find a solution to the weird paging issue when separating trackbacks/pingbacks from comments?
I resolved the paging issue by replacing:
Trackbacks/Pingbacks
with:
Trackbacks/Pingbacks
So, trackbacks should go after the navigation.
hey,
yeah posting code doesn’t appear in wordpress.
can you please post it to http://tinypaste.com
then give me the url?
thanks, that would be really appreciated!
http://pastie.org/608175
This works for posts but not for pages. Using this method, the comments in pages doesn’t shows up.
So which way do I need to setup the code for trackbacks to show up on every page and not ruin the page count and stuff?
wow that’s great tutorial! thank you!
Thanks for the information Since I have updated my comment threads have been getting cluttered with Pings It was really getting annoying
This is a great tutorial. Most of it works for me, but I am unable to get any of your functions.php code to work.
When I insert this into my functions.php it breaks the site
<li id="comment-">
All I am doing is copy and pasting that in. Is there more to it? Should it go somewhere specific?
That is nice code.
hello. I’m using wordpress 2.8.4 and I applied the changes of this tutorial. everything works fine except that the comment page. Unfortunately no longer works.
Someone can tell me how to get it to work, taking the division?
Thanks
p.s: sorry for my bad english!
sorry, i wrong digit the e-mail!!
I’ve never used PHP before and have no experience with it. Your tutorial worked like a charm on my Wordpress 2.8.4 install. Thanks a million!
Nice tutorial. Unfortunately after implementing it, my comment form lost the nested comments function.
After following this small guide all my comments all the sudden does’nt show. They are not deleted or anything, they just don’t show below my posts & pages anymore. No error eighter, accespt an error when submitting a new content. That error would be the usual one “Headers allready sent blablabla” witch Wordpress seems to really like.
Is this guide compatible with 2.8.5 ?
Thank you for this information. I was going crazy trying to solve this problem.
Thanks!
all well said, and I didn’t have to go to codex :)
I wanted to personally thank you for posting this. I searched all around the web and only found updated articles regurgitating How-To’s on the old comments of WordPress… nothing helpful for 2.7+.
This simple explaination made it simple to finally update my blogs. I wish Wordpress would have made separation of Trackbacks/Pingbacks apart of the overhaul to the comments when they launch 2.7 versus putting it back on theme designers.
If this is causing your comments or pings to not display at all, you just need to add this line to your comments.php file:
<?php $comments_by_type = &separate_comments($comments); ?>Add it right before:
<?php if ( !empty($comments_by_type['pings']) ) : ?>You aint got nothing on me…(run)…
Great tutorial, thank you.
I have not took a look at 2.7 codes yet, is $comments_by_type a global variable?
<?php $pings = get_comments_by_type('type=pings'); ?>
<?php foreach ($comments_by_type['pings'] as $comment) : ?>
Note the $pings instead of $comments_by_type['pings'];
@GaMerZ: Looks like I had pasted in a wrong bit of code. The code has been updated to its correct values.
@Aeolos: I’m not sure how to fix that and haven’t looked but from a comment made by Viper007Bond in #wordpress-dev today:
it looks like he is aware and working on fixing this in the core code.