Jump to content

Google Microdata Information = Auto Updated Feed


Dirty Butter

Recommended Posts

I've been trying to add the metadata itemprop type info to content.product.php required by Google to get automatic updates to product info. I have been able to get PRICE to update correctly, but I can't figure out how to get AVAILABILITY to work properly.

 

In an attempt to see where I'm coding wrong I tried validating the individual product page with w3c.org. I'm getting these errors, which I suspect may be the reason I can't get Google to read the availability data: This morning's fresh eyes spotted the issues with the validating, so I've deleted the error messages.

Here's the section of my Blueprint skin:

<div id="product-information" class="information right sevencol last">
					<div class="box">
						<div class="wrapper">
							<form action="{$VAL_SELF}" method="post" class="ajax">
								<input type="hidden" name="add" value="{$PRODUCT.product_id}"/>
									<div itemprop="offerDetails" itemscope itemtype="http://data-vocabulary.org/Offer">
										<div class="details">
											<h3>{$LANG.catalogue.product_details}</h3>
											<div class="wrapper">
												<ul>
													<!-- Product Identification -->
													{if $PRODUCT.product_code}
														<li title="{$LANG.catalogue.product_code}">
															<strong>{$LANG.catalogue.product_code}</strong>
															<span class="product-code"><span itemprop="identifier" content="{$PRODUCT.product_code}">{$PRODUCT.product_code}</span></span>
														</li>
													{/if}
													{if $PRODUCT.upc}
														<li title="{$LANG.catalogue.product_upc}">
															<strong>{$LANG.catalogue.product_upc}</strong>
															<span class="upc">{$PRODUCT.upc}</span>
														</li>
													{/if}
													{if $PRODUCT.ean}
														<li title="{$LANG.catalogue.product_ean}">
															<strong>{$LANG.catalogue.product_ean}</strong>
															<span class="ean">{$PRODUCT.ean}</span>
														</li>
													{/if}
													{if $PRODUCT.jan}
														<li title="{$LANG.catalogue.product_jan}">
															<strong>{$LANG.catalogue.product_jan}</strong>
															<span class="jan">{$PRODUCT.jan}</span>
														</li>
													{/if}
													{if $PRODUCT.isbn}
														<li title="{$LANG.catalogue.product_isbn}">
															<strong>{$LANG.catalogue.product_isbn}</strong>
															<span class="isbn">{$PRODUCT.isbn}</span>
														</li>
													{/if}
													<!-- Manufacturer / Brand -->
													{if $PRODUCT.manufacturer}
														<li title="{$LANG.catalogue.manufacturer}">
															<strong>{$LANG.catalogue.manufacturer}</strong>
															<span itemprop="brand"><span class="manufacturer brand">{$MANUFACTURER}</span></span>
														</li>
													{/if}
													<!--added to show condition-->
													{if $PRODUCT.condition}
													<span style="text-transform: capitalize;">
														<li><strong>{$LANG.catalogue.condition}</strong> <span itemprop="condition" content="used">{$PRODUCT.condition}
													</span>
														</li>
													</span>																							
													{/if}
													<!--end condition-->
													<!-- Availability -->																							
													{if $PRODUCT.use_stock_level && $PRODUCT.stock_level != false}
														<li>
														<strong>Availability</strong> <link itemprop="availability" href="http://schema.org/InStock" />In stock
														</li>
														<li><strong>{$LANG.catalogue.stock_level}</strong>{$PRODUCT.stock_level}</li>
													{else}
														<li>
														<strong>Availability</strong> <link itemprop="availability" itemtype="http://schema.org/ItemAvailability" content="http://schema.org/OutOfStock"/>
														Out of Stock
														</li>
											
														{if isset($PRODUCT.discounts)}
														<p><font color="green">(Quantity Discount Available)</font></p>
														{/if}
													{/if}
												
														<!--Pinterest-->										
															<a href="//www.pinterest.com/pin/create/button/?url={$PRODUCT.url}&amp;media={$PRODUCT.medium}&amp;description={$PRODUCT.name}%20Next%20stop%3A%20Pinterest" data-pin-do="buttonPin"><img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_red_28.png" alt="Pinit"  /></a>
															<!-- Please call pinit.js only once per page -->
															<script type="text/javascript" async src="//assets.pinterest.com/js/pinit.js"></script>
															<!-- Pinterest-->
														<!-- Social Bookmarks -->
														{if $SHARE && isset($fusion)}
															<li class="bookmarks">
																{foreach from=$SHARE item=html}
																	{$html}
																{/foreach}
																{if $fusion->get("google_plus_one_size")}
																	<script>Modernizr.load('//apis.google.com/js/plusone.js');</script>
																	<div class="g-plusone" data-size="{$fusion->get('google_plus_one_size')}" data-annotation="{$fusion->get('google_plus_one_annotation')}" data-count="true">
																	</div>
																{/if}
															</li>
														{/if}
												</ul>		
											</div><!-- /.wrapper -->
											
										</div><!-- /.details -->
									</div><!--/#offer-->
										
										{if is_array($OPTIONS)}
											<div class="options">
												<h3>{$LANG.catalogue.title_product_options}</h3>
												<div class="wrapper">
													<ul>
														{foreach from=$OPTIONS item=option}
															<li class="option">
																{if $option.type == '0'}
																	<label for="option-{$option.option_id}">{$option.option_name}{if $option.price} ({$option.symbol}{$option.price}){/if}{if $option.required} *{/if}</label>
																	<span>
																		<select name="productOptions[{$option.option_id}]" {if $option.required}required{/if} id="option-{$option.option_id}" class="{if $option.required}required{/if}">
																			<option value="" data-symbol="" data-price="">{$LANG.form.please_select}</option>
																			{foreach from=$option.values item=value}
																			<option value="{$value.assign_id}" data-symbol="{$value.symbol}" data-price="{$value.price}">{$value.value_name}{if $value.price} ({$value.symbol}{$value.price}){/if}</option>
																			{/foreach}
																		</select>
																	</span>
																	{else}
																	<label for="option-{$option.option_id}">{$option.option_name}{if $option.price} ({$option.symbol}{$option.price}){/if}{if $option.required} *{/if}</label>
																	<span>
																		{if $option.type == '1'}
																			<input type="text" name="productOptions[{$option.option_id}][{$OPT.assign_id}]" {if $option.required}required{/if} data-symbol="{$option.symbol}" data-price="{$option.price}" id="option-{$option.option_id}" class="{if $option.required}required{/if}"  />
																		{elseif $option.type == '2'}
																			<textarea name="productOptions[{$option.option_id}][{$OPT.assign_id}]" {if $option.required}required{/if} data-symbol="{$option.symbol}" data-price="{$option.price}" id="option-{$option.option_id}" class="{if $option.required}required{/if}"></textarea>
																		{/if}
																	</span>
																{/if}
															</li><!-- /.option -->
														{/foreach}
													</ul>
												</div><!-- /.wrapper -->
											</div><!-- /.options -->
									{/if}
										<!-- CHANGE CUTOFF FOR MAKE AN OFFER IN CUBECART.CLASS.PHP  ABOUT LINE 1368 -->
										{if isset($ASKABOUT_PRODUCT_URL)}
											
											{if $ASKABOUT_PRODUCT_OUT_OF_STOCK}
												<p><strong><a href="{$ASKABOUT_PRODUCT_URL}" title="{$LANG.askaboutaproduct.product_link_3}">{$LANG.askaboutaproduct.product_link_3}</a></strong></p>
											{else if !$ASKABOUT_PRODUCT_OUT_OF_STOCK && $ASKABOUT_PRODUCT_PRICING}
												<p><strong><a href="{$ASKABOUT_PRODUCT_URL}" title="{$LANG.askaboutaproduct.product_link_2}">{$LANG.askaboutaproduct.product_link_2}</a></strong></p>
											{else}
												<p><strong><a href="{$ASKABOUT_PRODUCT_URL}" title="{$LANG.askaboutaproduct.product_link}">{$LANG.askaboutaproduct.product_link}</a></strong></p>
											{/if}
										{/if}
									<div class="actions buy">
										<div class="wrapper">
											<span itemprop="offerDetails" itemscope itemtype="http://data-vocabulary.org/Offer">
													{if ($CTRL_ALLOW_PURCHASE) && (!$CATALOGUE_MODE)}
														<input type="number" name="quantity" value="1" min="1" {if $PRODUCT.stock_level}max="{$PRODUCT.stock_level}"{/if} required class="required" />
														<a href="#submit" class="button add-to-cart small" title="{$LANG.catalogue.add_to_basket}">
														<meta itemprop="priceCurrency" content="USD" />
														<span itemprop="price"><span class="price {if $PRODUCT.ctrl_sale}sale{/if}">{if $PRODUCT.ctrl_sale}{$PRODUCT.sale_price}{else}{$PRODUCT.price}{/if}
														</span></span>
														{$LANG.catalogue.add_to_basket}
														</a>
														{elseif $CTRL_HIDE_PRICES}
														<a href="{$STORE_URL}/index.php?_a=login" class="button add-to-cart large">{$LANG.catalogue.login_to_view}</a>
															{else if $CTRL_OUT_OF_STOCK}
															<span class="button add-to-cart large disabled">
																{if $LANG.catalogue.out_of_stock_short}{$LANG.catalogue.out_of_stock_short}{else}{$LANG.catalogue.stock_unavailable}
																{/if}
															</span>
													{/if}
											</span>
									</div><!-- /.wrapper -->
								</div><!-- /.actions buy-->
							</form>
						</div><!-- /.wrapper -->
					</div><!--/#CLASS BOX-->
				</div><!-- /.information .right sevencol last-->

If anyone has been able to work out the microdata required, or sees what I did wrong in nesting that might have caused my issue, I sure would appreciate your help.

 

We have well over 3000 products listed, with more to come. As Google gets pickier about the freshness of data this appears to be more and more inportant.

Link to comment
Share on other sites

Not having any basis for fact, I can't imagine Google having a problem with the two W3C hits. Loosely explained:

 

<span> is considered to effect what's between the tags "in-line". It does not cause line breaks or creating "boxy containers".

 

<p> and <li> do create containers in that they cause the string of text to end and start up again on a new line.

 

The "rules" say that you can have containers within containers, but you can't wrap up a container inside an in-line effect.

 

So, <li> then <span>, and <p> then <span>.

Link to comment
Share on other sites

  • 7 months later...

Now that google merchant is getting a bit tetchy about micro data is there any update from Cubecart regarding inserting this into the code. DB has done well inserting it in her code, however I do not profess to have those skills.  More info see below.

Missing microdata for condition

https://support.google.com/merchants/answer/6069143

Link to comment
Share on other sites

I did finally get this all working, but on Foundation. It meant using the Specification tab for a lot of microdata.

DB, I am using foundation, can you explain a little more please? The specifications tab can be seen in the product public view .

 

Link to comment
Share on other sites

Sorry for the delay in replying.

My content.product.php file is far from stock, but here is my file:

{if isset($PRODUCT) && $PRODUCT}
<div itemscope itemtype="http://schema.org/Product">
   <form action="{$VAL_SELF}" method="post" class="add_to_basket">
      <div class="row">
         <div class="small-12 columns">
            <h1 itemprop="name">{$PRODUCT.name}</h1>
         </div>
      </div>
      <div class="row">
         <div class="small-7 columns">  
<p> <center><h4>All Our Lovies Are Used</h4></center></p>
            <a href="#" class="open-clearing" data-thumb-index="0"><img src="{$PRODUCT.medium}" alt="{$PRODUCT.name}" id="img-preview"></a>
            {if $GALLERY}
            <ul class="clearing-thumbs small-block-grid-3 medium-block-grid-5 marg-top" data-clearing>
               {foreach from=$GALLERY item=image}
               <li><a href="{$image.source}"><img src="{$image.small}" data-image-swap="{$image.medium}" data-caption="{$PRODUCT.name}{if !empty($image.description)}: {/if}{$image.description}" class="th image-gallery" alt="{$LANG.catalogue.click_enlarge}"></a></li>
               {/foreach}
            </ul>
            {/if}
         </div>
         <!--- I DO NOT USE OPTIONS, SO I LEFT THAT PART OF THE CODE OUT FOR YOU -->
            {if $PRODUCT.review_score && $CTRL_REVIEW}
            <p itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
               <meta itemprop="ratingValue" content="{$REVIEW_AVERAGE}">
               <meta itemprop="reviewCount" content="{$REVIEW_COUNT}">
               {for $i = 1; $i <= 5; $i++}
               {if $PRODUCT.review_score >= $i}
               <img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/star.png" alt="">
               {elseif $PRODUCT.review_score > ($i - 1) && $PRODUCT.review_score < $i}
               <img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/star_half.png" alt="">
               {else}
               <img src="{$STORE_URL}/skins/{$SKIN_FOLDER}/images/star_off.png" alt="">
               {/if}
               {/for}
            <div>{$LANG_REVIEW_INFO}</div>
            </p>
            {/if}
            {if ($CTRL_ALLOW_PURCHASE) && (!$CATALOGUE_MODE)}
            <h3>
               {if $PRODUCT.ctrl_sale}
               <span class="old_price" id="fbp" data-price="{$PRODUCT.full_base_price}">{$PRODUCT.price}</span>
               <span class="sale_price" id="ptp" data-price="{$PRODUCT.price_to_pay}">{$PRODUCT.sale_price}</span>
               {else}
				{* MY VERSION *}
				<span class= "regular_price">{$PRODUCT.price}</span>
               {/if}
            </h3>
            {if isset($PRODUCT.discounts)}
            <p><span class="redbold">(<a href="#quantity_discounts">{$LANG.catalogue.bulk_discount}</a>)</span></p>
            {/if}
            <div class="row collapse">
               {if $PRODUCT.available == '0'}
               <div class="small-12 columns">
                  <input type="submit" value="{$LANG.common.unavailable}" class="button small disabled expand marg-top" disabled>
               </div>
               {else}
               <div class="small-2 columns">
<div class="medium-4  large-2 columns show-for-medium-up"> 
                  <input type="text" name="quantity" value="1" class="quantity required text-center">
                  <input type="hidden" name="add" value="{$PRODUCT.product_id}">
               </div>
</div>
 <div class="small-12 medium-8 large-10 columns">
                  <button type="submit" value="{$LANG.catalogue.add_to_basket}" class="button_basket postfix">{$LANG.catalogue.add_to_basket}</button>
               </div>
               {/if}
            </div>
            {else}
            {if $CTRL_HIDE_PRICES}
            <p class="buy_button"><strong>{$LANG.catalogue.login_to_view}</strong></p>
            {else if $CTRL_OUT_OF_STOCK}
            <p class="buy_button"><strong>{$LANG.catalogue.out_of_stock}</strong></p>
            {/if}
            {/if}
<br><!-- I LEFT OUT SOME MOD CODE HERE FOR SIMPLICITY -->
      <hr>
      <dl class="tabs" data-tab data-options="deep_linking:true; scroll_to_content:false">
         {if !empty($PRODUCT.description)}
         <dd class="active"><a href="#product_info">{$LANG.catalogue.product_info}</a></dd>
         {/if}
         <dd><a href="#product_spec">{$LANG.common.specification}</a></dd>
         {if isset($PRODUCT.discounts)}
         <dd><a href="#quantity_discounts">{$LANG.catalogue.quantity_discounts}</a></dd>
         {/if}
      </dl>
      <div class="tabs-content">
         {if !empty($PRODUCT.description)}
         <div class="content active" id="product_info" itemprop="description">
            {$PRODUCT.description}
         </div>
         {/if}
         <div class="content{if empty($PRODUCT.description)} active{/if}" id="product_spec">
            <table>
               <tbody>
                  <tr>
                     <td>{$LANG.catalogue.product_code}</td>
                     <td><span itemprop="productID">{$PRODUCT.product_code}</span></td>
                  </tr>
                  {if $PRODUCT.manufacturer}
                  <tr>
                     <td>{$LANG.catalogue.manufacturer}</td>
                     <td><span itemprop="brand">{$MANUFACTURER}</span></td>
					 {else}
					 <td>{$LANG.catalogue.manufacturer}</td>
					 <td><span itemprop="brand">Unknown</span></td>
                  </tr>				 				  
                  {/if}

                  <tr>
                     <td>{$LANG.catalogue.stock_level}</td>
                     <td>{$PRODUCT.stock_level}</td>
					<tr>
 {if ($CTRL_ALLOW_PURCHASE) && (!$CATALOGUE_MODE)}
{if $PRODUCT.ctrl_sale}
<td>Price</td>
       <td>  <div itemprop="offers" itemscope itemtype="http://schema.org/Offer"><meta itemprop="priceCurrency" content="USD" /><span itemprop="price">{$PRODUCT.sale_price}</span></div></td>
               {else}
 {* MY VERSION *}
<td>Price</td>
<td><div itemprop="offers" itemscope itemtype="http://schema.org/Offer"><meta itemprop="priceCurrency" content="USD" /><span itemprop="price">{$PRODUCT.price}</span></div></td>
 {/if}
                  </tr>
                  {/if}
{if $PRODUCT.stock_level == '0'}
                  <tr>
<td>Sold for </td>
<td><div itemprop="offers" itemscope itemtype="http://schema.org/Offer"><meta itemprop="priceCurrency" content="USD" /><span itemprop="price">{$PRODUCT.price}</span></div></td>
                  </tr>
</div>
{/if}
			{if $PRODUCT.condition} <!-- PLEASE NOTE - ALL OUR ITEMS ARE USED. YOU WOULD NEED TO ADD AN IF/THEN FOR NEW ITEM CONDITION IF SOME ARE USED, SOME NEW - OTHERWISE CHANGE FOR NEW CONDITION-->
                  <tr>
						<td>{$LANG.catalogue.condition} </td>
						<td><span itemprop="itemCondition" href="http://schema.org/UsedCondition" />{$PRODUCT.condition}</span></td>																																														
                  {/if}
					</tr>
               </tbody>
            </table>
         </div>
         {if isset($PRODUCT.discounts)}
         <div class="content" id="quantity_discounts">
            <p>{$LANG.catalogue.quantity_discounts_explained}</p>
            <br>
            <table>
               <thead>
                  <tr>
                     <th>{$LANG.common.quantity}</th>
                     <th>{$LANG.catalogue.price_per_unit}</th>
                  </tr>
               </thead>
               <tbody>
{if $PRODUCT.use_stock_level && $PRODUCT.stock_level != false}
<tr>
						<th>Stock Level </th>
						<th>{$PRODUCT.stock_level}</th>
</tr>
{else}
<tr>
				<th>Stock Level </th>
						<th>{$PRODUCT.stock_level}</th>
 </tr>	
{/if}
                  {foreach from=$PRODUCT.discounts item=discount}
                  <tr>
                     <td>{$discount.quantity}+</td>
                     <td>{$discount.price}</td>
                  </tr>
                  {/foreach}
               </tbody>
            </table>
         </div>
         {/if}
      </div>
   </form>
   {if $SHARE}
   {foreach from=$SHARE item=html}
   {$html}
   {/foreach}
   {/if}
   <hr>
   {include file='templates/element.product_reviews.php'}
   {foreach from=$COMMENTS item=html}
   {$html}
   {/foreach}
</div>
</div>
{else}
<p>{$LANG.catalogue.product_doesnt_exist}</p>
{/if}

 

Link to comment
Share on other sites

  • 1 month later...

Hi DB,

I had a look at this yesterday.

When I use "export catalogue" google base plugin to make a cvs file,

I get a column saying the identifier_exists is False, where as when it is set to true, I can manually upload the file to google merchant and it is accepted.

I note above in your "blue print skin"

<span class="product-code"><span itemprop="identifier" content="{$PRODUCT.product_code}">{$PRODUCT.product_code}</span></span>

However I can  not find it mentioned in your foundation skin above and it does not appear in content.product.php. 

Any suggestions where to put it?

Link to comment
Share on other sites

Thanks DB

When I load the cvs file to google merchant, it now comes back with an error "Automatic item updates: Missing schema.org microdata price information" 

  1. http://schema.org/docs/search_results.html#q=price shows how to insert price into a doc.
  2. eg.
  3. <div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
  4.     <!--price is 1000, a number, with locale-specific thousands separator
  5.     and decimal mark, and the $ character is marked up with the
  6.     machine-readable code "USD" -->
  7.     <span itemprop="priceCurrency" content="USD">$</span><span
  8.           itemprop="price" content="1000.00">1,000.00</span>
  9.     <link itemprop="availability" href="http://schema.org/InStock" />In stock
  10.   </div>

Is there some code available to place this in the foundation code of content.product.php and where to place it?

Link to comment
Share on other sites

You may not have noticed, but I repeated the price information in the specification tab and put the microdata lines there. There is a specific nesting order of these microdata codes needed to get it to work. Price has to come under Offers. I used so much trial and error to get mine working, and now it's "cold", so I fear I can't help much more than to just provide what I did as an example. Sorry.

Link to comment
Share on other sites

This is what I inserted and this works, or seems to. 

                     <td>{$LANG.catalogue.stock_level}</td>
                     <td>{$PRODUCT.stock_level}</td>
                  </tr>
                  {/if}
        {* start insert *}  
                <tr>
                    {if ($CTRL_ALLOW_PURCHASE) && (!$CATALOGUE_MODE)}
                    {if $PRODUCT.ctrl_sale}
                <td>Price</td>
                <td>  <div itemprop="offers" itemscope itemtype="http://schema.org/Offer"><meta itemprop="priceCurrency" content="AUD" /><span itemprop="price">{$PRODUCT.sale_price}</span></div></td>
                    {else}
        {* MY VERSION *}
                <td>Price</td>
                <td><div itemprop="offers" itemscope itemtype="http://schema.org/Offer"><meta itemprop="priceCurrency" content="AUD" /><span itemprop="price">{$PRODUCT.price}</span></div></td>
                {/if}
                  </tr> 
                  
        {* end of insert *}   

 

NB I added after 

" <td>{$PRODUCT.stock_level}</td>" a  </tr>  thanks

Link to comment
Share on other sites

  • 1 year later...

We are in the final stages of testing a new plugin that automatically adds Rich Snippets to CubeCart V6 and will work alongside our recently released Google Merchant Shopping Export plugin https://www.cubecart.com/extensions/plugins/google-merchant-centre-feed.  Do you have any specific requirements and then I can check these are also included

Ian

Link to comment
Share on other sites

The structured data testing tool will only test for that, not whether the data in the feed itself is correct - two different things so you would need to look at the data itself in the products it is complaining about and ensure it meets all of the conditions for your country and the type of products you are uploading.  There are several incorrect assumptions and bugs in the core product export program.

Ian

Link to comment
Share on other sites

ALL our items are used and all are marked that way. So that's not why Google complains about a small percentage of our listings. I've checked them in an effort to see what's different about those listings, and they truly are not different. But thanks for the suggestion. Looking forward to your plugin!

Link to comment
Share on other sites

7 hours ago, Dirty Butter said:

Looking forward to your plugin!

We have released V1.0 of this plugin and it is available via our website and it has been uploaded to the marketplace although it is not yet showing there. A free 7 day trial is available.

Product description follows :

This plugin adds up to 23 different schema.org microdata elements to the product landing pages which has multiple benefits

Firstly, microdata gives search engine spiders more context for the type of information on a website and the way the site should be indexed and ranked. An example on the schema.org website shows that adding microdata to mark up HTML code on a web page related to the movie "Avatar" tells search engine spiders to rank the page in relation to movie sites, not graphic design sites.

Another benefit of microdata is the creation of "rich snippets," which display more information on the search result pages than traditional listings

Thirdly, it helps Google Shopping retrieve up-to-date information directly from the website and while it isnt currently obligatory it is strongly advised which usually comes a short while before it becomes mandatory. Using microdata with automatic item updates helps support a high-quality experience for users who view your ads.

Having valid microdata enables the following two Google Shopping features :

Automatic item updates, which reduces the risk of account suspension for price and availability mismatches and prevents temporary item disapproval. 

Google Sheets Merchant Centre add-on, which uses microdata to help you update many attributes in your feed.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...