21st March 2018
Geeky Snippets Tutorials WordPress

WordPress tutorial: Comment reply notifications with 40 lines of code

If you’re tired of Disqus and Jetpack, then you need to switch back to default WordPress comments. And it hurts.

Both, Disqus and Jetpack do two things: spam prevention and notifications. Plus Disqus looks good, while Jetpack needs some styling. But that’s another case.

Spam prevention

Probably that’s me being lazy, but I just took the Akismet. It works, doesn’t add javascript to the page and it’s invisible. Cool, I like that. I’m using Akismet for years and it’s all good. Sometimes legit comments land in spam, but it’s not a common issue and it requires checking that tab once in two weeks. No biggie.

Without a plugin? Eee… I do not recommend that. My main blog is not a big one, with ~300 daily visitors and I got 42 spam comments within last 5 days. Wow, right?

Notifications

You, as a blog post author, have the notifications on by default. Every time someone leaves a comment on the post you’ve written, you’ll get the email. But the thing we all love about Disqus, is the notification about a reply.

With default WordPress comments you don’t have any option to enable notifications. With Jetpack comments you can add the “subscribe” button, but it’s not good—it’ll email you with comments on a specific post, not just a replies to yours. Annoying? For sure. May work with smaller blogs, but it’s still not that what people really want.

Plugins? I’ve tried to find something and I failed, but that was years ago. Maybe there is something that actually works and my work is unnecessary (but I don’t want to think about it).

Let’s code, okay?

add_action();

What do you need to do when you want to do something? Think about it. Think it through. You need to know what you want to achieve and then collect all the pieces you might need.

add_action — actions are the hooks that launch in WordPress core and then do specific things.

We need two actions:

One for posts that are published right away, meaning: posted by you or people who left comments before and you’ve approved them. They’re not jumping to the moderation panel. That’s important.

Second for comments that are moderated and changing status to approved.

The actions we need are called comment_post and transition_comment_status. And to these actions we need to attach functions. Mine will be called dyzqus, since it’s Disqus-based and made by Yz (Yzoja)—me. Hi!

function dyzqus_nomoderation($comment_ID, $comment_approved ) {
}
add_action('comment_post', 'dyzqus_nomoderation', 10, 2 );

function dyzqus_moderation($new_status, $old_status, $data ) {
}
add_action('transition_comment_status', 'dyzqus_moderation', 10, 3);

add_action structure: name of the hook, name of the function, priority and number or parameters used in your function and hook. I think the names states clearly which parameters do what.

That’s the base. Rest of the code will be inside the function.

function();

What we need to do now?

Check the status of the comment, right? We want to notify people only in the case that the comment is published. In nomoderation it’s easy, second parameter may have only three values : 0 , 1 and spam. We just compare if the value of $comment_approvedis 1.

if ($comment_approved === 1) {
	// magic, soon.
}

With moderation, we have statuses with values:approved, unapproved and spam. We have to check if the $new_status is approved AND if the previous value is different than that. Because that would fire the function when you edit already approved comment to fix the typos or something like that. We don’t need that.

if ($old_status != 'approved' && $new_status == 'approved') {
	// magic, soon.
}

Cool! What’s next?

Parent?

There is no point in trying if the comment doesn’t have parent—right?

We need to get the comment’s data to find out if the parent is 0or something else. If 0 then we can skip sending emails since that’s something that WordPress does by default.

$data = get_comment($comment_ID); // for nomoderation

In moderatated part we have the $data set already in the hook.

$parent = $data->comment_parent;
	if ($parent != 0) {
	}
}

Another code block to check if there is a parent or there isn’t (default value for the comment_parent is 0. If there is a parent, then the value is the parent comment ID).

Parent done. We can send emails!

Data for the email

The fun starts here, right? I like using default wp_mail function. Easy, works and allows to send HTML emails.

What we need?

Email address of the parent comment’s author. Check.

$parentData = get_comment($parent);
$email = $parentData->comment_author_email;

We could actually stop right there. Just send an email “Hi, someone replied to your comment”. But it would be nice to include at least the name of your blog, the post title, maybe the comment’s content and author?

$reply = $data->comment_content; // child comment's content
$author = $data->comment_author; // child comment's author name
$link = get_permalink($data->comment_post_ID); // post's link

With the title it’s a little bit complicated. We could just use get_the_title() but it doesn’t work perfectly. If you’re using unicode characters in your title that might get messy. Like “„Death Note””. Ugh, right?

Funny thing: Disqus “handles” it exactly that way. But we can do it better than Disqus, okay?

$title = get_the_title($data->comment_post_ID); // if you're not using special characters

$post = get_post($data->comment_post_ID);
$title = $post->post_title; // if you want to be careful

Now it’s time for gathering all the stuff we have, ready?

Sending emails

Now we need: email’s subject and content. We already have the email.

$blogname = get_bloginfo('name');
$subject = sprintf('[%1$s] Reply to your comment: "%2$s"', $blogname, $post_title );

That’s the “syntax” used in WordPress notification, basic but have everything. First part is the name of your blog and the second one the post title. So, it’s: [CSS Princess] Reply to your comment: Gutenberg 1.7.0. Feel free to change it. You can drop the blogname part, use the Disqus style.

$subject = 'Re: Comment on ' . $post_title;

If you want, and I think you do, use the HTML in your emails, then you need to have headers set.

$headers = array('Content-Type: text/html; charset=UTF-8');

Headers can contain Bcc:, Cc: and From: parameters. 

$headers = array('Content-Type: text/html; charset=UTF-8', 'From: CSS Princess <notifications@devgirl.space>');

It’s time for the message.

$message = '<body style="font-size:16px;font-family:Arial;width: 100%;max-width: 500px;margin:0 auto;"><div style="color: #fff;font-weight:bold; border-radius:40px;background: #b90063;padding: 20px;font-size: 20px;">Someone replied to your comment</div><div style="padding:10px 20px;"><p>Hi,<br><strong>' . $author . '</strong> replied to your comment:</p></div><div style="margin: 20px;background:#eee;padding:10px;line-height:170%;font-size:14px;">' . wpautop($reply) . '.</div><div style="padding:10px 20px;"><p>Go to the post (' . $link . ') to reply.</p></div></body>';

Inline styles and all stacked together, sorry.

And more Disqus-looking alternative:

$message = '<body style="font-size:16px;font-family:Arial;background: #eee;"><div style="background: #fff;width: 100%;margin:0 auto;max-width: 500px;padding:20px;box-shadow:0 2px 4px rgba(0,0,0,0.1);"><p>Hi, there is a new comment on ' . blogname .'.</p><div style="background: #9be9f2;height: 5px;margin-bottom:20px;"></div><strong>' . $author . '</strong>:<div style="background:#eee;padding:10px;line-height:170%;font-size:14px;">' . wpautop($reply) . '.</div><div style="margin-top:30px;padding:10px 0px;"><a style="color:#fff;text-decoration:none;border-radius:4px;background:#9be9f2;font-weight:bold;font-size:12px;padding:10px 20px" href="' . $link . '">Go to the post to reply.</a></div></div></body>';

With email’s body, you can play for hours. Add images, buttons, posts excerpt, thumbnail, the avatar of the person who left a comment or the parent comment’s content, to let people know the context right there in the email notification.

Grand finale

wp_mail( $email, $subject, $message, $headers);

Done. 

The full code:

function dyzqus_notifications($data, $comment_ID) {
	$reply = $data->comment_content;
	$author = $data->comment_author;
	$post = get_post($data->comment_post_ID);
	$post_title = $post->post_title;
	$blogname = get_bloginfo('name');
	$subject = sprintf( __('[%1$s] Reply to your comment: "%2$s"'), $blogname, $post_title );
	$link = get_permalink($data->comment_post_ID);
	$parent = $data->comment_parent;

	if ($parent != 0) {
		$parentData = get_comment($parent);
		$email = $parentData->comment_author_email;
		$message = '<body style="font-size:16px;font-family:Arial;background: #eee;"><div style="background: #fff;width: 100%;margin:0 auto;max-width: 500px;padding:20px;box-shadow:0 2px 4px rgba(0,0,0,0.1);"><p>Hi, there is a new comment on ' . blogname .'.</p><div style="background: #9be9f2;height: 5px;margin-bottom:20px;"></div><strong>' . $author . '</strong>:<div style="background:#eee;padding:10px;line-height:170%;font-size:14px;">' . wpautop($reply) . '.</div><div style="margin-top:30px;padding:10px 0px;"><a style="color:#fff;text-decoration:none;border-radius:4px;background:#9be9f2;font-weight:bold;font-size:12px;padding:10px 20px" href="' . $link . '">Go to the post to reply.</a></div></div></body>';
		$headers = array('Content-Type: text/html; charset=UTF-8', 'From: CSS Princess <angie@devgirl.space>');
		wp_mail( $email, $subject, $message, $headers);
	}	
}

function dyzqus_nomoderation( $comment_ID, $comment_approved ) {
	if ($comment_approved === 1) {
		$data = get_comment($comment_ID);
		dyzqus_notifications($data, $comment_ID);
	}
}
add_action( 'comment_post', 'dyzqus_nomoderation', 10, 2);

function dyzqus_moderation( $new_status, $old_status, $data ) {
	if ($old_status != 'approved' && $new_status == 'approved') {
		$comment_ID = $data->comment_ID;
		dyzqus_notifications($data, $comment_ID);
	}
}
add_action( 'transition_comment_status', 'dyzqus_moderation', 10, 3);

35 lines of code. 34 if you’ll delete that empty line 16 before the wp_mail but I like to keep the grand finale clear.

The code works, it feels good! Can work with just default WordPress comments or with Jetpack, or with any other plugin for comments that still saves that to your WordPress database.

(P.S.: paste the code to your functions.php, of course)

|
5

Leave a Reply

Your email address will not be published. Required fields are marked *

Klaatu says:

This is a great hack, and a really nice tutorial. Thank you for posting this!

Ivan says:

Hi. Thanks for this code. I have question. How add link “unsubscribe”?

CSS Princess says:

There is no such thing right now, but I’ll need to update the code to fit into GDPR guidelines (which is kinda tricky, because most efficient way would be to store the emails of the people, who want to unsubscribe…)