How to enable email notifications for Product Comments in Prestashop

If you have a solid and active customer base, it is frustrating to go and check the Product Comments module every day just to know if a new review has been posted. Let’s see how to add email notifications for comments!


Download Project Files

  • Compatibility: Prestashop 1.5, Prestashop 1.6
  • Version used: Prestashop 1.6

Introduction

Although I will be using Prestashop 1.6’s code for this tutorial, you can apply the same process to the Prestashop 1.5 version of the product comments module. Just be aware that you will have to use a 1.5 email template instead of copying the 1.6 one I will use here, to have all your emails uniform, if needed.

There is a small thing to notice: no language variable is passed when a new comment is added via ajax. This means we will create a new email template for the default shop language only, as, for the time being, I have found no reliable way to create a multilanguage-enabled function for this.

We will be amending one file only throughout the tutorial: default.php, along with creating two new email templates in the main mails/*language* folder. Let’s get started!

The default Comments controller

Prestashop comments’ submission is handled through an ajax call, so that no page refresh is needed when adding a new one. The main php file beneath all the comment submission process is default.php, and can be found in modules/productcomments/controllers/front/. Open it up in your favorite code editor, then locate the ajaxProcessAddComment() method.

This function is called upon comment submission, and it’s the place where we need to add our email send-out.

	protected function ajaxProcessAddComment()
	{
		$module_instance = new ProductComments();

		$result = true;
		$id_guest = 0;
		$id_customer = $this->context->customer->id;
		if (!$id_customer)
			$id_guest = $this->context->cookie->id_guest;

		$errors = array();
		// Validation
		if (!Validate::isInt(Tools::getValue('id_product')))
			$errors[] = $module_instance->l('ID product is incorrect', 'default');
		if (!Tools::getValue('title') || !Validate::isGenericName(Tools::getValue('title')))
			$errors[] = $module_instance->l('Title is incorrect', 'default');
		if (!Tools::getValue('content') || !Validate::isMessage(Tools::getValue('content')))
			$errors[] = $module_instance->l('Comment is incorrect', 'default');
		if (!$id_customer && (!Tools::isSubmit('customer_name') || !Tools::getValue('customer_name') || !Validate::isGenericName(Tools::getValue('customer_name'))))
			$errors[] = $module_instance->l('Customer name is incorrect', 'default');
		if (!$this->context->customer->id && !Configuration::get('PRODUCT_COMMENTS_ALLOW_GUESTS'))
			$errors[] = $module_instance->l('You must be logged in order to send a comment', 'default');
		if (!count(Tools::getValue('criterion')))
			$errors[] = $module_instance->l('You must give a rating', 'default');

		$product = new Product(Tools::getValue('id_product'));
		if (!$product->id)
			$errors[] = $module_instance->l('Product not found', 'default');

		if (!count($errors))
		{
			$customer_comment = ProductComment::getByCustomer(Tools::getValue('id_product'), $id_customer, true, $id_guest);
			if (!$customer_comment || ($customer_comment && (strtotime($customer_comment['date_add']) + (int)Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME')) < time()))
			{

				$comment = new ProductComment();
				$comment->content = strip_tags(Tools::getValue('content'));
				$comment->id_product = (int)Tools::getValue('id_product');
				$comment->id_customer = (int)$id_customer;
				$comment->id_guest = $id_guest;
				$comment->customer_name = Tools::getValue('customer_name');
				if (!$comment->customer_name)
					$comment->customer_name = pSQL($this->context->customer->firstname.' '.$this->context->customer->lastname);
				$comment->title = Tools::getValue('title');
				$comment->grade = 0;
				$comment->validate = 0;
				$comment->save();

				$grade_sum = 0;
				foreach(Tools::getValue('criterion') as $id_product_comment_criterion => $grade)
				{
					$grade_sum += $grade;
					$product_comment_criterion = new ProductCommentCriterion($id_product_comment_criterion);
					if ($product_comment_criterion->id)
						$product_comment_criterion->addGrade($comment->id, $grade);
				}

				if (count(Tools::getValue('criterion')) >= 1)
				{
					$comment->grade = $grade_sum / count(Tools::getValue('criterion'));
					// Update Grade average of comment
					$comment->save();
				}
				$result = true;

				Tools::clearCache(Context::getContext()->smarty, $this->getTemplatePath('productcomments-reviews.tpl'));
			}
			else
			{
				$result = false;
				$errors[] = $module_instance->l('You should wait').' '.Configuration::get('PRODUCT_COMMENTS_MINIMAL_TIME').' '.$module_instance->l('seconds before posting a new comment');
			}
		}
		else
			$result = false;

		die(Tools::jsonEncode(array(
			'result' => $result,
			'errors' => $errors
		)));
	}

It would be useless to send an email notification if the comment submission process failed; thus, we will insert our code right after that $result = true; declaration.

So, right before Tools::clearCache(Context::getContext()->smarty, $this->getTemplatePath(‘productcomments-reviews.tpl’)); add:

				// send out an email! by Nemo

				$product_name = Product::getProductName($comment->id_product);
				$shop_email = Configuration::get('PS_SHOP_EMAIL');
				$shop_name = Configuration::get('PS_SHOP_NAME');

				Mail::Send(Configuration::get('PS_LANG_DEFAULT'), 'new_comment', Mail::l('New comment added'),
				array(
					'{comment_content}' => $comment->content,
					'{product_name}' => $product_name
				), $shop_email,
					$shop_name, $shop_email);

Explanation: first off, we need some variables. We get the product name, to print out more information in the email, then the shop name and email to be used as arguments of the Mail::Send function. This very same method is really simple:

We pass the default language to it, then the name of the template we need (which doesn’t exist yet at this stage, but we will be creating it shortly), then the email Title. As template variables, we want ourselves to be aware of the content of the comment, as well as the product concerned. Lastly, we set the shop email as sender, receiver, and the shop name as receiver’s name.

We are done with this file already. Let’s create the actual email templates!

Creating the new email templates

This is the easiest part. Two files are needed in order for email notifications to work in Prestashop: an .html version, and a .txt one. Reach the main mails/ folder, and inside it access the subfolder with your default store language’s ISO code. Then, create a new file called new_comment.html and paste the following inside:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
		<title>Message from {shop_name}</title>
		

		<style>	@media only screen and (max-width: 300px){ 
				body {
					width:218px !important;
					margin:auto !important;
				}
				.table {width:195px !important;margin:auto !important;}
				.logo, .titleblock, .linkbelow, .box, .footer, .space_footer{width:auto !important;display: block !important;}		
				span.title{font-size:20px !important;line-height: 23px !important}
				span.subtitle{font-size: 14px !important;line-height: 18px !important;padding-top:10px !important;display:block !important;}		
				td.box p{font-size: 12px !important;font-weight: bold !important;}
				.table-recap table, .table-recap thead, .table-recap tbody, .table-recap th, .table-recap td, .table-recap tr { 
					display: block !important; 
				}
				.table-recap{width: 200px!important;}
				.table-recap tr td, .conf_body td{text-align:center !important;}	
				.address{display: block !important;margin-bottom: 10px !important;}
				.space_address{display: none !important;}	
			}
	@media only screen and (min-width: 301px) and (max-width: 500px) { 
				body {width:308px!important;margin:auto!important;}
				.table {width:285px!important;margin:auto!important;}	
				.logo, .titleblock, .linkbelow, .box, .footer, .space_footer{width:auto!important;display: block!important;}	
				.table-recap table, .table-recap thead, .table-recap tbody, .table-recap th, .table-recap td, .table-recap tr { 
					display: block !important; 
				}
				.table-recap{width: 293px !important;}
				.table-recap tr td, .conf_body td{text-align:center !important;}
				
			}
	@media only screen and (min-width: 501px) and (max-width: 768px) {
				body {width:478px!important;margin:auto!important;}
				.table {width:450px!important;margin:auto!important;}	
				.logo, .titleblock, .linkbelow, .box, .footer, .space_footer{width:auto!important;display: block!important;}			
			}
	@media only screen and (max-device-width: 480px) { 
				body {width:308px!important;margin:auto!important;}
				.table {width:285px;margin:auto!important;}	
				.logo, .titleblock, .linkbelow, .box, .footer, .space_footer{width:auto!important;display: block!important;}
				
				.table-recap{width: 285px!important;}
				.table-recap tr td, .conf_body td{text-align:center!important;}	
				.address{display: block !important;margin-bottom: 10px !important;}
				.space_address{display: none !important;}	
			}
</style>

	</head>
	<body style="-webkit-text-size-adjust:none;background-color:#fff;width:650px;font-family:Open-sans, sans-serif;color:#555454;font-size:13px;line-height:18px;margin:auto">
		<table class="table table-mail" style="width:100%;margin-top:10px;-moz-box-shadow:0 0 5px #afafaf;-webkit-box-shadow:0 0 5px #afafaf;-o-box-shadow:0 0 5px #afafaf;box-shadow:0 0 5px #afafaf;filter:progid:DXImageTransform.Microsoft.Shadow(color=#afafaf,Direction=134,Strength=5)">
			<tr>
				<td class="space" style="width:20px;padding:7px 0">&nbsp;</td>
				<td align="center" style="padding:7px 0">
					<table class="table" bgcolor="#ffffff" style="width:100%">
						<tr>
							<td align="center" class="logo" style="border-bottom:4px solid #333333;padding:7px 0">
								<a title="{shop_name}" href="{shop_url}" style="color:#337ff1">
									<img src="{shop_logo}" alt="{shop_name}" />
								</a>
							</td>
						</tr>

<tr>
	<td align="center" class="titleblock" style="padding:7px 0">
		<font size="2" face="Open-sans, sans-serif" color="#555454">
			<span class="title" style="font-weight:500;font-size:28px;text-transform:uppercase;line-height:33px">Hi!</span>
		</font>
	</td>
</tr>
<tr>
	<td class="space_footer" style="padding:0!important">&nbsp;</td>
</tr>
<tr>
	<td class="box" style="border:1px solid #D6D4D4;background-color:#f8f8f8;padding:7px 0">
		<table class="table" style="width:100%">
			<tr>
				<td width="10" style="padding:7px 0">&nbsp;</td>
				<td style="padding:7px 0">
					<font size="2" face="Open-sans, sans-serif" color="#555454">
						<p data-html-only="1" style="border-bottom:1px solid #D6D4D4;margin:3px 0 7px;text-transform:uppercase;font-weight:500;font-size:18px;padding-bottom:10px">
							You have received a new comment for the product "{product_name}"						</p>
						<span style="color:#777">
							{comment_content}
						</span>
					</font>
				</td>
				<td width="10" style="padding:7px 0">&nbsp;</td>
			</tr>
		</table>
	</td>
</tr>

						<tr>
							<td class="space_footer" style="padding:0!important">&nbsp;</td>
						</tr>
						<tr>
							<td class="footer" style="border-top:4px solid #333333;padding:7px 0">
								<span><a href="{shop_url}" style="color:#337ff1">{shop_name}</a> powered by <a href="http://www.prestashop.com/" style="color:#337ff1">PrestaShop&trade;</a></span>
							</td>
						</tr>
					</table>
				</td>
				<td class="space" style="width:20px;padding:7px 0">&nbsp;</td>
			</tr>
		</table>
	</body>
</html>

Then create another one named new_comment.txt, and paste this inside:


[{shop_url}] 

Hi!,

You have received a new comment for the product "{product_name}"

{comment_content}
{shop_name} [{shop_url}] powered by
PrestaShop(tm) [http://www.prestashop.com/] 


NOTE: If you are using Prestashop 1.6 you can simply copy and paste the above inside a .html and .txt file, otherwise, if you are trying to apply it to 1.5, my suggestion is to pick a default email template, such as the log_alert one, and modify it accordingly by adding the new variables.

We are done! Save, and then test the new email notifications out by adding a comment!

Final Notes

If your emails are not being sent out, make sure you test them by going to Advanced Parameters, E-Mail in the back office. Double check our email settings and try sending out a test email as well.

If everything works at this state, inspect the ajax call by accessing the network tab in a browser console (F12 on Chrome, for example). The comment ajax call looks like default?action=add_comment&secure_key=6efb5690f08b14a4d0c050119418fc68&rand=1397469373235.

You like the tuts and want to say "thank you"? Well, you can always feel free to donate:

  • Joost

    I have installed this module but if I get an new product review I can’t see it in back-office. So I can’t delete my test review, please help?

  • Dany

    Hi, It´s work thx, but just a little problem, it doesn’t show the “product_name” and “comments” fields in the email. I copy everything as you posted even have the same filenames. What error may have made ? (sorry for mmy english)

  • Satkos Van

    Thank you, but it does not work for me, email settings are set correctly, other emails are sent. How can I fix this? Presta 1.6.

  • nicogaldo

    I would like to create a button that sends what is in your cart now to the email client. It will be something like this or keep looking?

  • Milad

    Hi. Thanks for the great article but it does’t work on my ps ver 1.5.6.2 . my email server works properly and i did the email check you said in the end . have you any suggestion ? thank you

    • NemoPS

      Hi there!
      Well it can be anything really, are you sure the correct email template is setup? Make sure you added it for the languages you use both in the back and front office

  • Fran

    Wonderful!!! You’re a machine

  • Marco

    Thank you!

  • http://www.dannetstudio.com.ar/ Daniel Ignacio Fernández

    Excellent explanation! Thanks

  • Doles

    thanks, it’s work iam happy now :)

Store Top Sales

You like the tuts and want to say "thank you"? Well, you can always feel free to donate: