This article correlates to PowerReviews' Enhanced SEO: Option 2.
The on_change callback function exposes a method to provide structured data for Review schemas. This callback function is a direct replacement for the on_render function -- you cannot have both on one page.
How to Enable
Define the callback function and check for the presence of reviews.
on_change: function(config, data) {
if(config.component === 'ReviewList') {
// Check for the presence of reviews
if(data.review_count > 0 && (data.reviews).length > 0) {
var reviews = [];
If there are reviews, dynamically create your Review schema objects with the data exposed in the "data" parameter.
// Dynamically create an object for the Reviews schema
for (var i = 0; i <= ((data.reviews).length)-1; i++)
var pwrReview = data.reviews[i];
var review = {
"@type": "Review",
"name": pwrReview.details.headline,
"reviewBody": pwrReview.details.comments,
"datePublished": new Date(pwrReview.details.created_date).toISOString(),
Date(pwrReview.details.created_date).toISOString(),
"author": {
"@type": "Person",
"name": pwrReview.details.nickname
},
"reviewRating": {
"@type": "Rating",
"ratingValue": pwrReview.metrics.rating
}
};
if(pwrReview.details.location &&
(pwrReview.details.location).toLowerCase() != 'undisclosed') {
review["locationCreated"] = {
"@type": "AdministrativeArea",
"name": pwrReview.details.location
};
}
reviews.push(review);
}
Append the Review schemas to the existing Product schema.
// Attach the Review schemas to the existing Product schema
var scriptTag = document.getElementById('productschema');
var scriptTagObject = JSON.parse(scriptTag.innerHTML);
for (var i = 0; i <= (scriptTagObject.length-1); i++) {
if(scriptTagObject[i]) {
scriptTagObject[i]['review'] = reviews;
}
}
scriptTag.innerHTML = JSON.stringify(scriptTagObject);
}
If there are no reviews available (pagination, filtering, etc.), remove the Review schema.
// If no reviews available due to filtering/pagination/search
// remove review object from each product variation group in
// the product schema
if((data.reviews).length == 0) {
var scriptTag = document.getElementById('productschema');
var scriptTagObject = JSON.parse(scriptTag.innerHTML);
for (var i = 0; i <= (scriptTagObject.length-1); i++) {
if(scriptTagObject[i]) {
delete scriptTagObject[i]['review'];
}
}
scriptTag.innerHTML = JSON.stringify(scriptTagObject);
}
Full Code:
<script>
on_change: function(config, data) {
if(config.component === 'ReviewList') {
// Check for the presence of reviews
if(data.review_count > 0 && (data.reviews).length > 0) {
var reviews = [];
// Dynamically create an object for the Reviews schema
for (var i = 0; i <= ((data.reviews).length)-1; i++) {
var pwrReview = data.reviews[i];
var review = {
"@type": "Review",
"name": pwrReview.details.headline,
"reviewBody": pwrReview.details.comments,
"datePublished": new
Date(pwrReview.details.created_date).toISOString(),
"author": {
"@type": "Person",
"name": pwrReview.details.nickname
},
"reviewRating": {
"@type": "Rating",
"ratingValue": pwrReview.metrics.rating
}
};
if(pwrReview.details.location &&
(pwrReview.details.location).toLowerCase() != 'undisclosed') {
review["locationCreated"] = {
"@type": "AdministrativeArea",
"name": pwrReview.details.location
};
}
reviews.push(review);
}
// Attach the Review schemas to the existing Product schema
var scriptTag = document.getElementById('productschema');
var scriptTagObject = JSON.parse(scriptTag.innerHTML);
for (var i = 0; i <= (scriptTagObject.length-1); i++) {
if(scriptTagObject[i]) {
scriptTagObject[i]['review'] = reviews;
}
}
scriptTag.innerHTML = JSON.stringify(scriptTagObject);
}
// If no reviews available due to filtering/pagination/search
// remove review object from each product variation group in the product schema
if((data.reviews).length == 0) {
var scriptTag = document.getElementById('productschema');
var scriptTagObject = JSON.parse(scriptTag.innerHTML);
for (var i = 0; i <= (scriptTagObject.length-1); i++) {
if(scriptTagObject[i]) {
delete scriptTagObject[i]['review'];
}
}
scriptTag.innerHTML = JSON.stringify(scriptTagObject);
}
}
}
</script>