Bigcommerce Rich Snippet Product Reviews

Star Ratings & Prices

Bigcommerce is a CMS that enables businesses to sell their products online and lets visitors write reviews on them.

Meanwhile, Google understands special html that helps it gather information on products and reviews. This information may result in Google directly showing review ratings and product prices in it's search results. Just like the examples to the right. These enhanced listings can help you stand out in the search results and attract more clicks.

This article explains a way to enhance Bigcommerce so that it contains the required html to get those enhanced listings in Google.

I offer a Bigcommerce SEO Tune-up Services which includes setting this up plus many other activities.

Support this work
I'd like to buy Tony a
My Email Address is
Acceptance Mark

This is advanced stuff. I'd recommend only people very familiar with editing templates should try this. And back all the files up first. All the following instructions relate to editing template files:

Defining a Product

The first thing we want to do is make the product pages say they are Product pages.

Layouts/product.html

Make the following additions (in red) to the template file:

Note: it seems newer templates have changed things. If you don't see the code shown below then ignore this and follow the later instructions fro the newer templates.

...
<div class="Content" id="LayoutColumn2">
%%Panel.ProductBreadcrumb%%
<div itemscope itemtype="http://schema.org/Product">
%%Panel.ProductDetails%%
%%Panel.ProductTabs%%
%%Panel.ProductDescription%%
%%Panel.ProductVideos%%
%%Panel.ProductWarranty%%
%%Panel.ProductOtherDetails%%
%%Panel.SimilarProductsByTag%%
%%Panel.ProductByCategory%%
%%Panel.ProductVendorsOtherProducts%%
%%Panel.ProductReviews%%
%%Panel.SimilarProductsByCustomerViews%%
</div>
</div>
...

This bit of code change wraps the products content in a div that defines the content as being a Product. Thanks to Karen S for coming up with this solution which is a lot cleaner than my original hacky one.

Note that the Breadcrumb panel is excluded. This is because its content is not really about the Product but the page structure. I also provide instructions on How To Add Breadcrumb Markup .

Marking up the Product Details (Panels/ProductDetails.html)

It is very hard to create these instructions as I'm sure most templates are different and therefore will need to be enhanced in different ways. However all the changes are additions to the existing template file, so if you can find the right bit of code you can enhance it.

I may not have associated the right properties with the right information. And there may be more that can be mapped. The important thing is that it includes enough to get the rich snippet results in Google.

I have provided line numbers and surrounding code from the template I edited to help you find roughly where to make the edits.

Line 1

These two lines are for Pinterest which supports product markup via open graph (og) like Facebook. Inserting these two extra meta lines to the start of the file should get things working. Make sure you set the currency to the 3 letter code for your own currency, like USD. Once done use the Pinterest Validator to check it is working. Thanks to Islamic Art for posting this solution in the comments. I also had to move the tags into this file so that Bigcommerce would insert the right value.

<meta property="og:price:amount" content="%%GLOBAL_ProductPrice%%"/>
<meta property="og:price:currency" content="USD" />
...

If you use more than one currency then this will probably not work correctly. Also, the price provided is not in the required format especially if you display two prices (with and without tax). I suggest you skip this code if you cannot get it to validate correctly.

Line 28

If you ignored the first step in this article because you have a newer template then you need to make this change. Find the first <div> in the file and add the code highlighted here.

...
<div class="Block Moveable Panel PrimaryProductDetails" id="ProductDetails"
itemscope itemtype="http://schema.org/Product">
...

Line 31

Tell Google what the product is called.

<h1 itemprop="name" >%%GLOBAL_ProductName%%</h1>

Line 66

Define an Offer which will contain the price of the product.

<div itemprop="offers" itemscope itemtype="http://schema.org/Offer"
class="DetailRow PriceRow" style="%%GLOBAL_HidePrice%%">
<div class="Label">%%GLOBAL_PriceLabel%%:</div>

Warning: If you are also setting up the Google Merchant Centre to do AdWords Shopping ads then this price markup can sometimes cause problems. The merchant centre may look at this markup to confirm pricing is correct, however it will only see what prices are shown to your US customers. If you have multiple currencies including USD and are advertising outside the USA then it may report a problem. If so do not add the above and below code.

Line 69

Here is the price it contains. To get around Bigcommerce limitations I have used JavaScript to enter the correct currency, price, and stock status. Note that the validation tool does not run the JavaScript so will show the default values, but the real Google Algorithm does pick up those generated by JavaScript.

<em itemprop="price" class="ProductPrice VariationProductPrice">%%GLOBAL_ProductPrice%%</em>
<meta itemprop="priceCurrency" content="USD"/>
<meta itemprop="availability" itemtype="http://schema.org/ItemAvailability" content="http://schema.org/InStock"/>
<div id="AllPricesAreInCurrency" style="display: none;">%%GLOBAL_AllPricesAreInCurrency%%</div>
<script type="text/javascript"> //<![CDATA[ $(function() { var cleanPrice = '%%GLOBAL_ProductPrice%%'.replace(/[^0-9. ]/g,"").split(" ")[0]; $("em[itemprop='price']").attr('content',cleanPrice); var currency = $("#AllPricesAreInCurrency span").text(); $("meta[itemprop='priceCurrency']").attr('content',currency); if ($(".ExpectedReleaseDate").length != 0) { $("meta[itemprop='availability']").attr('content','http://schema.org/PreOrder'); }; if ($(".CurrentlySoldOut").length != 0) { $("meta[itemprop='availability']").attr('content','http://schema.org/OutOfStock'); }; }); //]]> </script>

In reality you probably only need to hard code the currency to what people in the US see. This is because Googlebot is typically in the US and Bigcommerce detects this and provides them with the appropriate currency for there. Change the USD to your own default currency if you don't sell in USD.

You will need to alter that code if you don't use a dot (.) as a decimal point. Replace the dot in [0-9. ] with whatever decimal point character you use.

The availability code sets itself to OutOfStock if the stock level reaches zero and to PreOrder if there is an expected release date. It does not test for any other availability signals.

Please test that the JavaScript does not error and it is generating the correct values for your data.

Next we want to add the products condition. If your products are always new you can add this line:

<meta itemprop="itemCondition" itemtype="http://schema.org/OfferItemCondition" content="http://schema.org/NewCondition"/>

Or if they are always used then this line would work:

<meta itemprop="itemCondition" itemtype="http://schema.org/OfferItemCondition" content="http://schema.org/UsedCondition"/>

If the conditions vary then you need to make sure you always switch on "Show the condition in the product page" for every product, then you can use this line:

<meta itemprop="itemCondition" itemtype="http://schema.org/OfferItemCondition" content="http://schema.org/%%GLOBAL_ProductCondition%%Condition"/>

Line 77

The SKU.

<span itemprop="sku" class="VariationProductSKU">

Line 93

The Brand.

<a itemprop="brand" href="%%GLOBAL_BrandLink%%">%%GLOBAL_BrandName%%</a>

Line 113

Starting the reviews section.

<div itemprop="aggregateRating" itemscope
itemtype="http://schema.org/AggregateRating" class="DetailRow" style="display: %%GLOBAL_HideRating%%">

Line 116

What was the average rating and the max.min ratings. The extra JavaScript here is to clean up values if there were no ratings.

<img itemprop="ratingValue" content="%%GLOBAL_Rating%%" width="64" height="12" src="%%GLOBAL_IMG_PATH%%/IcoRating%%GLOBAL_Rating%%.gif" alt="" />
<meta itemprop="worstRating" content="1"/>
<meta itemprop="bestRating" content="5" />
<script type="text/javascript">
//<![CDATA[
$(function() {
if (%%GLOBAL_ProductNumReviews%% == 0) {
$("div[itemprop='aggregateRating']").removeAttr('itemtype');
$("div[itemprop='aggregateRating']").removeAttr('itemscope');
$("div[itemprop='aggregateRating']").removeAttr('itemprop');
$("img[itemprop='ratingValue']").removeAttr('content');
$("img[itemprop='ratingValue']").removeAttr('itemprop');
$("meta[itemprop='worstRating']").remove();
$("meta[itemprop='bestRating']").remove();
$("*[itemprop='reviewCount']").removeAttr('content');
$("*[itemprop='reviewCount']").removeAttr('itemprop');
}
});
//]]>
</script>

Line 118

And how many people wrote reviews.

<a itemprop="reviewCount" content="%%GLOBAL_ProductNumReviews%%" href="#reviews" onclick="%%GLOBAL_ReviewLinkOnClick%%">

If you can't find the above line or one similar to use, you will have to add the count as a meta tag like the following code. I'm currently not sure if this will work as Google does not like this sort of information to be hidden from users.

<meta itemprop="reviewCount" content="%%GLOBAL_ProductNumReviews%%"/>

End of File

In a second we will be adding markup for each of the reviews. Unfortunately Bigcommerce does not provide the review dates in the correct format. This code is designed to fix that for us:

<script type="text/javascript">
//<![CDATA[
$(function() {
$("li[itemprop='review']" ).each(function( index ) {
var timeElement = $(this).find("time[itemprop='datePublished']");
var reviewDate = new Date(timeElement.text());
if (!isNaN(reviewDate.getTime())) {
var isoDate = reviewDate.getFullYear()+"-";
if (reviewDate.getMonth()+1 < 10) {
isoDate += '0';
}
isoDate += (reviewDate.getMonth()+1)+"-";
if (reviewDate.getDate() < 10) {
isoDate += '0';
}
isoDate += reviewDate.getDate();
timeElement.attr('datetime',isoDate );
}
});
});
//]]>
</script>

For this to work the JavaScript needs to be able to parse the date supplied by Bigcommerce. Again, unfortunately the default date format is not parseable. In Bigcommerce admin go to Setup & Tools->Store Settings->Language & Dates. Here you can see the settings for the Display Date Format. I know the default value of "jS M Y" does not parse, but "M d, Y" does. Change it if you want this code to be able to fill in those dates.

Marking up the Product Description (Panels/ProductDescription.html)

This time we need to create the span tag so we can add the markup around the description.

<span itemprop="description">%%GLOBAL_ProductDesc%%</span>

Marking up the Product Image (Snippets/ProductThumbImage.html)

Use the thumbnail as the official product image.

<img itemprop="image" src="%%GLOBAL_ThumbImageURL%%" alt="%%GLOBAL_ImageDescription%%" title="%%GLOBAL_ImageDescription%%" />

Marking up the Product Reviews (Snippets/ProductReviewItem.html)

This snippet repeats for each review. These edits will mark up each one.

<li itemprop="review" itemscope
itemtype="http://schema.org/Review" class="%%GLOBAL_AlternateReviewClass%%">
…
<span itemprop="name">%%GLOBAL_ReviewTitle%%</span>
<span itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating"> <img itemprop="ratingValue" content="%%GLOBAL_Rating%%" width="64" height="12" src="%%GLOBAL_IMG_PATH%%/IcoRating%%GLOBAL_ReviewRating%%.gif" alt="" /> </span> … %%LNG_PostedBy%% <span itemprop="author" itemscope itemtype="http://schema.org/Person"> <span itemprop="name">%%GLOBAL_ReviewName%%</span> </span> %%LNG_xOn%% <time itemprop="datePublished">%%GLOBAL_ReviewDate%%</time> … <p itemprop="reviewBody" >%%GLOBAL_ReviewText%%</p>

That's it. You can check things out using the Google Rich Snippet Tool then wait with fingers crossed.