I implemented a stars rating system on my one page html site. The system uses jQuery, AJAX and PHP. I found the code here and it works well regarding the storage of the ratings and the updating of the votes.
This is the Javascript code:
// STARS
$(document).ready(function() {
$('.rate_widget').each(function(i) {
var widget = this;
var out_data = {
widget_id : $(widget).attr('id'),
fetch: 1
};
$.post(
'ratings.php',
out_data,
function(INFO) {
$(widget).data( 'fsr', INFO );
set_votes(widget);
},
'json'
);
});
$('.ratings_stars').hover(
// Handles the mouseover
function() {
$(this).prevAll().andSelf().addClass('ratings_over');
$(this).nextAll().removeClass('ratings_vote');
},
// Handles the mouseout
function() {
$(this).prevAll().andSelf().removeClass('ratings_over');
// can't use 'this' because it wont contain the updated data
set_votes($(this).parent());
}
);
// This actually records the vote
$('.ratings_stars').bind('click', function() {
var star = this;
var widget = $(this).parent();
var clicked_data = {
clicked_on : $(star).attr('class'),
widget_id : $(star).parent().attr('id')
};
$.post(
'ratings.php',
clicked_data,
function(INFO) {
widget.data( 'fsr', INFO );
set_votes(widget);
},
'json'
);
});
});
function set_votes(widget) {
var avg = $(widget).data('fsr').whole_avg;
var votes = $(widget).data('fsr').number_votes;
var exact = $(widget).data('fsr').dec_avg;
window.console && console.log('and now in set_votes, it thinks the fsr is ' + $(widget).data('fsr').number_votes);
$(widget).find('.star_' + avg).prevAll().andSelf().addClass('ratings_vote');
$(widget).find('.star_' + avg).nextAll().removeClass('ratings_vote');
$(widget).find('.total_votes').text(votes);
$(widget).find('.avg_votes').text(exact);
}
// END STARS
There is a PHP script for storing and update the ratings:
$rating = new ratings($_POST['widget_id']);
isset($_POST['fetch']) ? $rating->get_ratings() : $rating->vote();
class ratings {
var $data_file = './ratings.data.txt';
private $widget_id;
private $data = array();
function __construct($wid) {
$this->widget_id = $wid;
$all = file_get_contents($this->data_file);
if($all) {
$this->data = unserialize($all);
}
}
public function get_ratings() {
if($this->data[$this->widget_id]) {
echo json_encode($this->data[$this->widget_id]);
}
else {
$data['widget_id'] = $this->widget_id;
$data['number_votes'] = 0;
$data['total_points'] = 0;
$data['dec_avg'] = 0;
$data['whole_avg'] = 0;
echo json_encode($data);
}
}
public function vote() {
# Get the value of the vote
preg_match('/star_([1-5]{1})/', $_POST['clicked_on'], $match);
$vote = $match[1];
$ID = $this->widget_id;
# Update the record if it exists
if($this->data[$ID]) {
$this->data[$ID]['number_votes'] += 1;
$this->data[$ID]['total_points'] += $vote;
}
# Create a new one if it doesn't
else {
$this->data[$ID]['number_votes'] = 1;
$this->data[$ID]['total_points'] = $vote;
}
$this->data[$ID]['dec_avg'] = round( $this->data[$ID]['total_points'] / $this->data[$ID]['number_votes'], 1 );
$this->data[$ID]['whole_avg'] = round( $this->data[$ID]['dec_avg'] );
file_put_contents($this->data_file, serialize($this->data));
$this->get_ratings();
}
# ---
# end class
}
And the ratings are obtained through this code inside my html page:
<div class='movie_choice'>
<div id="r1" class="rate_widget">
<div class="star_1 ratings_stars"></div>
<div class="star_2 ratings_stars"></div>
<div class="star_3 ratings_stars"></div>
<div class="star_4 ratings_stars"></div>
<div class="star_5 ratings_stars"></div>
<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<div class="avg_votes" style="display: table-cell; float: left;" itemprop="ratingValue"></div><div style="float:left;">/</div><div itemprop="bestRating" style="float:left;">5</div><div style="float: left;">, </div><div class="total_votes" style="display: table-cell; float:left;" itemprop="ratingCount"></div><div style="width: 200px;"> voti</div>
</div>
</div>
</div>
The method works and show the correct average ratings and the total number of votes. The problem is that Google does not recognize the ratingValue
. In the testing tool for structured data, Google says me that "ratingValue field can't be empty". In other words, for Google the line of code <div class="avg_votes" style="display: table-cell; float: left;" itemprop="ratingValue"></div>
means that ratingValue
is empty, although the rating is correctly showed in the page.
I suppose the problem is that this method is based on jQuery and my page is in html, but I can't find the solution for this issue.
Do you know the source of the problem, please?
Google doesn't run javascript when indexing your webpage, so all it will see is the empty html elements on the page and not the rating (since the rating is generated by javascript). If you want google to see the rating, you will need to generate the correct html on the server when you serve the page. This way, google will see the html with the ratings.