You are here:  » Rich snippets


Rich snippets

Submitted by Bakalinge on Thu, 2012-05-24 12:43 in

Hi,

Anybody with a good experience with rich snippets (http://support.google.com/webmasters/bin/answer.py?hl=en&answer=99170) / microdata (http://support.google.com/webmasters/bin/answer.py?hl=en&answer=176035) and PT ?

Thanks

Submitted by support on Thu, 2012-05-24 20:17

Hi,

This thread covers an hReview microformat - if you want to incorporate a specific rich snippet / microformat on your site let me know what page and markup you require and I should be able to work out the code required....

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Tue, 2012-11-20 16:31

Hi David,

I decided to follow the recommandation of Google and to use microdata. Basically, I get the following code in products.php :

$rows[$k]["extraHTML"] = "<p><div itemprop='rating' itemscope itemtype='http://data-vocabulary.org/Rating'><span itemprop='value'>".tapestry_stars($rows[$k]["rating"],"")."</span><meta itemprop='best' content='5' /></div>&nbsp;<a href='".$rows[$k]["reviewHREF"]."'>".$rows[$k]["reviews"]." ".translate("Reviews")."</a></p>";

My only concern is how to get the rating "value" in itemprop property...

Thanks for your help !

Submitted by support on Tue, 2012-11-20 16:40

Hi Bakalinge,

Very close - but you don't want to use the tapestry_stars() function which turns the rating into a graphic! Have a go with:

$rows[$k]["extraHTML"] = "<p><div itemprop='rating' itemscope itemtype='http://data-vocabulary.org/Rating'><span itemprop='value'>".$rows[$k]["rating"],""."</span><meta itemprop='best' content='5' /></div>&nbsp;<a href='".$rows[$k]["reviewHREF"]."'>".$rows[$k]["reviews"]." ".translate("Reviews")."</a></p>";

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Tue, 2012-11-20 22:00

Well, thanks for your help David, but unfortunatly it doesn't work. Google Structured Data Testing Service (http://www.google.com/webmasters/tools/richsnippets) doesn't validate the code.

I'm trying to label content using microdata specidication as described here : http://support.google.com/webmasters/bin/answer.py?hl=en&answer=176035 , especially the following review rating example :

  <div itemscope itemtype="http://data-vocabulary.org/Review-aggregate">
    <span itemprop="itemreviewed">L’Amourita Pizza</span>
    <img itemprop="photo" src="pizza.jpg" />
    <span itemprop="rating" itemscope itemtype="http://data-vocabulary.org/Rating">
      <span itemprop="average">9</span>
      out of <span itemprop="best">10</span>
    </span>
    based on <span itemprop="votes">24</span> ratings.
    <span itemprop="count">5</span> user reviews.
  </div>

As you can see, Google takes into consideration many propertys : , itemscope, itemtype, itemreviewed, photo, rating, average, best, votes, count... Many tests gave the result "Avertissement : Itemtype not recognized", so I went to the conclusion that this propertys where not inserted at the right place...

So your help would be highly appreciated ;)

Thanks

Submitted by support on Wed, 2012-11-21 09:44

Hi,

I think the best way to go about it, and to ensure that all the microformat information can be included without having to hide anything using CSS would be to encapsulate the entire product HTML output as the itemscope DIV. To do this, first edit html/product.php insert opening and closing itemscope DIV tags at the beginning and end, e.g.

<div itemscope itemtype='http://data-vocabulary.org/Review-aggregate'>
  ... rest of html/product.php here ...
</div>

Next to include the image and product name tags, so in the same file look for the following code at line 7 (in the original):

<img width='180' src='<?php print $mainProduct["image_url"]; ?>' alt='<?php print htmlentities($mainProduct["name"],ENT_QUOTES,$config_charset); ?>' />

...and REPLACE with:

<img itemprop='photo' width='180' src='<?php print $mainProduct["image_url"]; ?>' alt='<?php print htmlentities($mainProduct["name"],ENT_QUOTES,$config_charset); ?>' />

Then look for the following code _within_ line 11:

<?php print $mainProduct["name"]; ?>

...and REPLACE with:

<span itemprop='itemreviewed'><?php print $mainProduct["name"]; ?></span>

The remaining tags do need to be incorporated into the extraHTML variable as you have already identified; so to do this edit products.php and look for the following code at line 40:

$rows[$k]["extraHTML"] = "<p>".tapestry_stars($rows[$k]["rating"],"")."&nbsp;<a href='".$rows[$k]["reviewHREF"]."'>".$rows[$k]["reviews"]." ".translate("Reviews")."</a></p>";

...and REPLACE with:

$rows[$k]["extraHTML"] = "<p><span itemprop='rating' itemscope itemtype='http://data-vocabulary.org/Rating'>".tapestry_stars($rows[$k]["rating"],"")."&nbsp;<a href='".$rows[$k]["reviewHREF"]."'> Rated <span itemprop='average'>".$rows[$k]["rating"]."</span> out of <span itemprop='best'>5</span> in <span itemprop='votes'>".$rows[$k]["reviews"]."</span> ".translate("Reviews")."</a></span></p>";

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Wed, 2012-11-21 11:46

Great David, it works like a charm now !

Thank you !

Submitted by Bakalinge on Thu, 2013-01-17 04:05

Hi David,

I took a look at the node 2374 that I found very interesting for SEO, but not that much for user (why suggest him some words he already searched ?). From my point of view, it would be more relevant to suggest related searchs, built on user's queries (see node 822). Do you think it's possible to suggest all queries with at least one word (or more) from the user search.

For example if the user search was "Paintball game", related searches could be : "Paintball tactics", "Paintball shop", "war game", etc...

If this hack is possible, there are 2 problems to manage :
- we have to limit the number of related search suggested to the user : for some word it could easily be hundreds and hundreds of suggestions
- we have to supervise the quality of queries (since hack 822 is installed, I noticed a lot of trash queries indexed, probably from spam bots) : easy with Phpmyadmin but never good to manipulate database like this...From back-end it would be safer.

Thank you !

Bak

Submitted by support on Thu, 2013-01-17 12:45

Hello Bak,

A related searches query on the `querylog` table is straight forward in principle. If not already, add the `count` field (node 892) and results can be ordered by count which should help with quality. Have a go with something like;

$words = explode(" ",$q);
$ors = array();
foreach($words as $word)
{
  $ors[] = " query LIKE '%".database_safe($word)."%' ";
}
$or = implode(" OR ",$ors);
$sql = "SELECT * FROM `".$config_databaseTablePrefix."querylog` WHERE (".$or.") AND query <> '".database_safe($q)."' ORDER BY count DESC LIMIT 10";
if (database_querySelect($sql,$rows))
{
  print "<h2>Related Searches</h2>";
  print "<ul>";
  foreach($rows as $row)
  {
    print "<li><a href='".$config_baseHREF."search.php?q=".urlencode($row["query"])."'>".$row["query"]."</a></li>";
  }
  print "</ul>";
}

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Thu, 2013-01-17 15:42

Hi David,

Of course it helps a lot. Unfortunately, searches are not stored anymore in the querylog table. I think it's because of the redirect in the search form. Here's what I have :

    <form action="<?php print $config_baseHREF ?>search.php" method="get" name="formSearch" id="cse-search-box" style="margin-top:10px;">
       <input name="q" value="" type="text" class="Textbox" size="25" style="background:#fefef1;" />
       <input type='hidden' name='redir' value='1' />
       <input type='hidden' name='log' value='1' />
       <input type="image" src="<?php print $config_baseHREF ?>images/search.gif" name="btnGo" alt="Chercher" align="middle" class="Button" />
    </form>

If I remove

       <input type='hidden' name='redir' value='1' />

everything is fine (except urls of course), my search are stored.

I found something similar to the forum (http://www.pricetapestry.com/node/892/13841 ), but it doesn't change anything for me.

(sorry, just saw that my yesterday post is in the wrong place...)

Thanks,

Bak

Submitted by support on Thu, 2013-01-17 15:47

Hi Bak,

You could put log=1 in the redirect rewrite rule - since it is only search form submissions that you want to log, and it is only search form submissions that are redirected... In your .htaccess, look for your search redirect rule, which should contain:

?q=$1

...and REPLACE with:

?q=$1&log=1

That should do the trick!

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Thu, 2013-01-17 16:26

David,

Thanks for your answer,

The search redirect rules are written like this in .htaccess

RewriteRule ^s/(.*)/(.*)/$ search.php?q=$2&sort=$1&rewrite=1&%{QUERY_STRING} [L]
RewriteRule ^s/(.*)/(.*)/(.*).html$ search.php?q=$2&sort=$1&page=$3&rewrite=1&%{QUERY_STRING} [L]

If I replace the way you mentioned, I got a SQL error (?)

[SELECT DISTINCT(merchant) FROM `pt_products` WHERE ORDER BY merchant][You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ORDER BY merchant' at line 1]
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/moto/www/includes/database.php on line 27

Line 27 of database.php

while($row = mysql_fetch_array($result,MYSQL_ASSOC))
    {
      $rows[] = $row;
    }

Thanks,

Bak

Submitted by support on Thu, 2013-01-17 20:51

Hi Bak,

Could you post the section of search.php that performs the redirect so I can see it in context and I'll check that out for you...

Thanks
David.
--
PriceTapestry.com

Submitted by Bakalinge on Thu, 2013-01-17 21:46

David,

This is what I have in search.php :

line 12

  $rewrite = isset($_GET["rewrite"]);
    if ($_GET["redir"])
    {
       $location = $config_baseHREF."s/".$sort."/".tapestry_hyphenate($q)."/";
       header("Location: ".$location);
       exit();
    }

and then line 73 :

  if ($q)
  {
$rewrite = isset($_GET["rewrite"]);
if ($_GET["log"])
{
$sql = "INSERT INTO pt_querylog SET query='".database_safe($q)."'";
database_queryModify($sql,$result);
$sql = "UPDATE pt_querylog SET count=count+1 WHERE query='".database_safe($q)."'";
database_queryModify($sql,$result);
}
if ($_GET["redir"])
{
$location = $config_baseHREF."".$sort."/".tapestry_hyphenate($q)."/";
header("Location: ".$location);
exit();
}

Thanks

Bak

Submitted by support on Fri, 2013-01-18 12:16

Thanks Bak,

So it's the first rule that would need to be modified, have a go with:

RewriteRule ^s/(.*)/(.*)/$ search.php?q=$2&log=1&sort=$1&rewrite=1&%{QUERY_STRING} [L]

Cheers,
David.
--
PriceTapestry.com

Submitted by Bakalinge on Fri, 2013-01-18 13:56

thanks David,,

The url rewrite works correctly. I modified search.php in line 12 to get url rewrited also for related search :
{code saved}

FYI I have a warning when debug mode is activated :

[INSERT INTO `pt_querylog` SET query='term1 term2'][Duplicate entry 'term1 term2' for key 2]
Warning: Cannot modify header information - headers already sent by (output started at /home/domain/www/includes/database.php:55) in /home/motomoin/www/html/header.php on line 12

but despite that, it's working fine !

Thanks !

Bak

Submitted by support on Fri, 2013-01-18 14:18

That's great, Bak! Don't worry about the warning, the query column has a unique index against it to do exactly that - prevent duplicate entries, removing the need for conditional code within the script.

Cheers,
David.
--
PriceTapestry.com

Submitted by bat on Sat, 2013-03-09 16:17

Is it possible to use the Product Rich Snippets in conjunction with PT?
https://support.google.com/webmasters/bin/answer.py?hl=en&answer=146750

Submitted by support on Sun, 2013-03-10 08:43

Hello bat,

Absolutely - a number of users have implemented some of the product related microdata already. The relevant schema.org page is here.

The itemscope and type attributes can be added the existing product div, so in html/product.php the first line is:

<div class='product'>

...REPLACE with:

<div class='product' itemscope itemtype="http://schema.org/Product">

The individual item tags can then be added around the various elements as required, for example, where the product name is displayed within line 11:

<?php print $mainProduct["name"]; ?>

...REPLACE with:

<span itemprop="name"><?php print $mainProduct["name"]; ?></span>

...the description at line 13:

<?php print $mainProduct["description"]; ?>

...REPLACE with:

<span itemprop="description"><?php print $mainProduct["description"]; ?></span>

And for the price at line 23:

<?php print $config_currencyHTML.$mainProduct["price"]; ?>

...REPLACE with:

<div style='display:inline;' itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<span itemprop="price">
<?php print $config_currencyHTML.$mainProduct["price"]; ?>
</span>
</div>

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by bat on Sun, 2013-03-10 15:11

Thank you, David.
Is the itemprop span tags meant to show up in the source code of the product page? I can't see any.
I tried to validate the pages in the Structured Data Testing Tool in Webmaster Tools but it doesn't seem to show a result on how the page would now look to Google with the rich snippet addition. I'm just a little confused on how it's going to turn out...

Submitted by support on Mon, 2013-03-11 08:58

Hi Bat,

Yes - the span's should definitely be appearing in the output with the above mod in place - would you like to forward to me a copy of your html/product.php and I'll double check - just in case your version has PHP control structures in place that may be holding back the output...

Cheers,
David.
--
PriceTapestry.com

Submitted by bat on Mon, 2013-03-11 10:09

My mistake, the file didn't copy over correctly. It's working now. Thanks David!

Submitted by BenTaylor on Wed, 2013-11-06 15:14

Hi David,

I've followed your advice in this thread, and have a couple of queries - when using Google's validator I can see the image (had to change the tag from 'photo' to 'image' - maybe Schema updated this in the past year?), description and price are being extracted from the data, but the preview isn't showing any of them, is this normal? the post above this would suggest it isn't so I'm stumped, see {link saved}

The other issue I had was around adding a review using the Schema.org template. From what I can gather I'll need to modify ratings.php somehow to identify the rating amount, and link this to the product information in product.php, which is already contained within the Product itemtype, can you give me a hand on how to add ratings using Schema.org's template?

Any help much appreciated

Submitted by support on Wed, 2013-11-06 15:52

Hello Ben and welcome to the forum!

I don't believe the preview shows marked-up data as Google tailors the result display to the query but I will investigate this further.

Regarding review markup, based on the basic "Review" properties from http://schema.org/Review as a starting point, if you edit html/ratings.php the first step is to output each review within the itemprop="review" containing div, so to do this, look for the following code at line 8:

  <?php foreach($ratings["reviews"] as $review): ?>

...and REPLACE with:

  <?php foreach($ratings["reviews"] as $review): ?>
  <div itemprop="review" itemscope itemtype="http://schema.org/Review">

And correspondingly, look for the following code at line 21:

  <?php endforeach; ?>

...and REPLACE with:

  </div>
  <?php endforeach; ?>

To markup the review text, look for the following code at line 15:

<?php print htmlspecialchars($review["comments"],ENT_QUOTES,$config_charset); ?>

...and REPLACE with:

<span itemprop="reviewBody">
<?php print htmlspecialchars($review["comments"],ENT_QUOTES,$config_charset); ?>
</span>

Finally to include the rating, look for the following code at line 10:

  <td class='ratings_stars'>

...and REPLACE with:

  <td class='ratings_stars'>
  <span itemprop="ratingValue" style="display:none;"><?php print $review["rating"]; ?></span>

I spent a while considering the final replacement above as previously I have been hesitant to suggest using mechanisms to "hide" anything as I thought it could adversely affect SEO but in this case, it's an absolutely genuine requirement to use a hidden element; plus hidden elements are now becoming a necessary part of both responsive web design and the development of every increasingly sophisticated "web apps" - I have been using them on other projects of mine and not noticed any undesired side effects. If you're not sure of course, let me know and we can look at alternatives.

My understanding is that the reviews will be automatically associated with the corresponding itemScope/product on the page so there is no need to include itemReviewed tags. Indeed, the examples on http://schema.org/Review don't include this tag.

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by BenTaylor on Wed, 2013-11-06 17:08

I think I know the issue, I'm using a template that places the reviews on to the product page, rather than having it's own section - so it makes sense that this would confuse the issue.

I'm not really sure if this entitles me for the same level of support, but please let me know if so and I'll send over whatever you need to have a look.

Submitted by support on Wed, 2013-11-06 17:12

Hi Ben,

No problem - lots of users (and templates) merge product / reviews pages - the distribution review pages generated still use the same html/product.php template file as the product pages so product specific markup should still be present if you're happy that you've edited that file as required for schema.org markup, but if you'd like to email me your html/ratings.php I'll apply the above for you...

Cheers,
David.
--
PriceTapestry.com