Either "offers", "review", or "aggregateRating" should be specified - Google Error

Silvary
Tourist
5 0 0

Thank you for your prompt reply & the time you take to help it’s much appreciated, I noticed it says to contact you if on Judge.me which I am. Can you also confirm if I need to remove any existing code? 
kind regards 

0 Likes
EmmanuelFlossie
Shopify Partner
814 31 182

It's possible, I would not know. As each merchant is different. If you contact me on my website, I am happy to help.

I'm a Google Shopping Specialist & a Google Ads Platinum Product Expert (Only a hand full of Platinum experts in the world!)
Need Premium Data Feed Management Support? Get in touch.
0 Likes
luxuriaistanbul
Excursionist
32 0 4

Hello,

hope this message finds you safe. We have currently approximately 400 reviews for 20% of the products on the web site www.luxuria.com.tr.

I am using debut theme and using the standard shopify review app. 

Currently I have for 1082 products missing "ratingCount" "reviewCount" and "ratingValue" problem in Google Search Console.

Can anyone please help me with this problem?

Best

Aydin

product-template looks like:

 

<div class="product-template__container page-width"
  id="ProductSection-{{ section.id }}"
  data-section-id="{{ section.id }}"
  data-section-type="product"
  data-enable-history-state="true"
  data-ajax-enabled="{{ settings.enable_ajax }}"
>
  {% comment %}
    Get first variant, or deep linked one
  {% endcomment %}
  {%- assign current_variant = product.selected_or_first_available_variant -%}
  {%- assign product_image_zoom_size = '1024x1024' -%}
  {%- assign product_image_scale = '2' -%}
  {%- assign enable_image_zoom = section.settings.enable_image_zoom -%}
  {%- assign compare_at_price = current_variant.compare_at_price -%}
  {%- assign price = current_variant.price -%}
 
  {% case section.settings.media_size %}
    {% when 'small' %}
      {%- assign product_media_width = 'medium-up--one-third' -%}
      {%- assign product_description_width = 'medium-up--two-thirds' -%}
      {%- assign height = 345 -%}
    {% when 'medium' %}
      {%- assign product_media_width = 'medium-up--one-half' -%}
      {%- assign product_description_width = 'medium-up--one-half' -%}
      {%- assign height = 530 -%}
    {% when 'large' %}
      {%- assign product_media_width = 'medium-up--two-thirds' -%}
      {%- assign product_description_width = 'medium-up--one-third' -%}
      {%- assign height = 720 -%}
    {% when 'full' %}
      {%- assign product_media_width = '' -%}
      {%- assign product_description_width = '' -%}
      {%- assign height = 1090 -%}
      {%- assign enable_image_zoom = false -%}
  {% endcase %}
 
  <div class="grid product-single{% if section.settings.enable_payment_button %} product-single--{{ section.settings.media_size }}-media{% endif %}">
    <div class="grid__item product-single__media-group {{ product_media_width }}{% if section.settings.media_size == 'full' %} product-single__media-group--full{% endif %}" data-product-single-media-group>
      {%- assign featured_media = product.selected_or_first_available_variant.featured_media | default: product.featured_media -%}
 
      {%- for media in product.media -%}
        {% include 'media', media: media, featured_media: featured_media, height: height, enable_image_zoom: enable_image_zoom, image_zoom_size: product_image_zoom_size, image_scale: product_image_scale %}
      {%- endfor -%}
 
      <noscript>
        {% capture product_image_size %}{{ height }}x{% endcapture %}
        <img src="{{ featured_media | img_url: product_image_size, scale: product_image_scale }}" alt="{{ featured_media.alt }}" id="FeaturedMedia-{{ section.id }}" class="product-featured-media" style="max-width: {{ height }}px;">
      </noscript>
 
      {% assign first_3d_model = product.media | where: "media_type", "model" | first %}
 
      {%- if first_3d_model -%}
        <button
          aria-label="{{ 'products.product.view_in_space_label' | t }}"
          class="product-single__view-in-space"
          data-shopify-xr
          data-shopify-model3d-id="{{ first_3d_model.id }}"
          data-shopify-title="{{ product.title | escape }}"
          data-shopify-xr-hidden
        >
          {% include 'icon-3d-badge-full-color' %}<span class='product-single__view-in-space-text'>{{ 'products.product.view_in_space' | t }}</span>
        </button>
      {%- endif -%}
 
 
      {% if product.media.size > 1 %}
        {% if product.media.size > 4 %}
          {%- assign enable_thumbnail_slides = true -%}
        {% endif %}
 
        <div class="thumbnails-wrapper{% if enable_thumbnail_slides == true %} thumbnails-slider--active{% endif %}">
          {% if enable_thumbnail_slides == true %}
            <button type="button" class="btn btn--link medium-up--hide thumbnails-slider__btn thumbnails-slider__prev thumbnails-slider__prev--{{ section.id }}">
              {% include 'icon-chevron-left' %}
              <span class="icon__fallback-text">{{ 'sections.slideshow.previous_slide' | t }}</span>
            </button>
          {% endif %}
          <ul class="product-single__thumbnails product-single__thumbnails-{{ section.id }}">
            {% for media in product.media %}
              <li class="product-single__thumbnails-item product-single__thumbnails-item--{{ section.settings.media_size }} js">
                <a href="{{ media.preview_image | img_url: product_image_zoom_size, scale: product_image_scale }}"
                   class="text-link product-single__thumbnail product-single__thumbnail--{{ section.id }}"
                   data-thumbnail-id="{{ section.id }}-{{ media.id }}"
                   {% if enable_image_zoom %}data-zoom="{{ media.preview_image | img_url: product_image_zoom_size, scale: product_image_scale }}"{% endif %}>
 
                    {%- capture thumbnailAlt -%}
                      {%- if media.media_type == 'video' or media.media_type == 'external_video' -%}
                        {{ 'sections.featured_product.video_thumbnail_alt' | t: imageAlt: media.alt | escape }}
                      {%- elsif media.media_type == 'model' -%}
                        {{ 'sections.featured_product.model_thumbnail_alt' | t: imageAlt: media.alt | escape }}
                      {%- else -%}
                        {{ 'sections.featured_product.gallery_thumbnail_alt' | t: imageAlt: media.alt | escape }}
                      {%- endif -%}
                    {%- endcapture -%}
 
                    <img class="product-single__thumbnail-image" src="{{ media.preview_image | img_url: '110x110', scale: 2 }}" alt="{{ thumbnailAlt }}">
                    {%- if media.media_type == 'video' or media.media_type =='external_video' -%}
                      <div class="product-single__thumbnail-badge">
                        {% include 'icon-video-badge-full-color' %}
                      </div>
                    {%- endif -%}
                    {%- if media.media_type == 'model' -%}
                      <div class="product-single__thumbnail-badge">
                        {% include 'icon-3d-badge-full-color' %}
                      </div>
                    {%- endif -%}
                </a>
              </li>
            {% endfor %}
          </ul>
          {% if enable_thumbnail_slides == true %}
            <button type="button" class="btn btn--link medium-up--hide thumbnails-slider__btn thumbnails-slider__next thumbnails-slider__next--{{ section.id }}">
              {% include 'icon-chevron-right' %}
              <span class="icon__fallback-text">{{ 'sections.slideshow.next_slide' | t }}</span>
            </button>
          {% endif %}
        </div>
      {% endif %}
    </div>
 
    <div class="grid__item {{ product_description_width }}">
      <div class="product-single__meta">
 
        <h1 class="product-single__title">{{ product.title }}</h1>
<span class="stamped-product-reviews-badge stamped-main-badge" data-id="{{product.id}}" data-product-title="{{product.title}}" data-product-type="{{product.type}}" style="display: block;"></span>
 
          <div class="product__price">
            {% include 'product-price', variant: current_variant, show_vendor: section.settings.show_vendor %}
          </div>
                
         {% include 'ZooomyListWishlistProduct' %}
          {%- if shop.taxes_included or shop.shipping_policy.body != blank -%}
            <div class="product__policies rte" data-product-policies>
              {%- if shop.taxes_included -%}
                {{ 'products.product.include_taxes' | t }}
              {%- endif -%}
              {%- if shop.shipping_policy.body != blank -%}
                {{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }}
              {%- endif -%}
            </div>
          {%- endif -%}
 
          {% capture "form_classes" -%}
            product-form product-form-{{ section.id }}
            {%- unless section.settings.show_variant_labels %} product-form--hide-variant-labels {% endunless %}
            {%- if section.settings.enable_payment_button and product.has_only_default_variant %} product-form--payment-button-no-variants {%- endif -%}
            {%- if current_variant.available == false %} product-form--variant-sold-out {%- endif -%}
          {%- endcapture %}
 
          {% form 'product', product, class:form_classes, novalidate: 'novalidate', data-product-form: '' %}
            {% unless product.has_only_default_variant %}
              <div class="product-form__controls-group">
                {% for option in product.options_with_values %}
                  <div class="selector-wrapper js product-form__item">
                    <label {% if option.name == 'default' %}class="label--hidden" {% endif %}for="SingleOptionSelector-{{ forloop.index0 }}">
                      {{ option.name }}
                    </label>
                    <select class="single-option-selector single-option-selector-{{ section.id }} product-form__input"
                      id="SingleOptionSelector-{{ forloop.index0 }}"
                      data-index="option{{ forloop.index }}"
                    >
                      {% for value in option.values %}
                        <option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>
                      {% endfor %}
                    </select>
                  </div>
                {% endfor %}
              </div>
            {% endunless %}
 
            <select name="id" id="ProductSelect-{{ section.id }}" class="product-form__variants no-js">
              {% for variant in product.variants %}
                <option value="{{ variant.id }}"
                  {%- if variant == current_variant %} selected="selected" {%- endif -%}
                >
                  {{ variant.title }}  {%- if variant.available == false %} - {{ 'products.product.sold_out' | t }}{% endif %}
                </option>
              {% endfor %}
            </select>
 
            {% if section.settings.show_quantity_selector %}
              <div class="product-form__controls-group">
                <div class="product-form__item">
                  <label for="Quantity-{{ section.id }}">{{ 'products.product.quantity' | t }}</label>
                  <input type="number" id="Quantity-{{ section.id }}"
                    name="quantity" value="1" min="1" pattern="[0-9]*"
                    class="product-form__input product-form__input--quantity" data-quantity-input
                  >
                </div>
              </div>
            {% endif %}
 
            <div class="product-form__error-message-wrapper product-form__error-message-wrapper--hidden{% if section.settings.enable_payment_button %} product-form__error-message-wrapper--has-payment-button{% endif %}"
              data-error-message-wrapper
              role="alert"
            >
              <span class="visually-hidden">{{ 'general.accessibility.error' | t }} </span>
              {% include 'icon-error' %}
              <span class="product-form__error-message" data-error-message>{{ 'products.product.quantity_minimum_message' | t }}</span>
            </div>
 
            <div class="product-form__controls-group product-form__controls-group--submit">
              <div class="product-form__item product-form__item--submit
                {%- if section.settings.enable_payment_button %} product-form__item--payment-button {%- endif -%}
                {%- if product.has_only_default_variant %} product-form__item--no-variants {%- endif -%}"
              >
                <button type="submit" name="add"
                  {% unless current_variant.available %} aria-disabled="true"{% endunless %}
                  aria-label="{% unless current_variant.available %}{{ 'products.product.sold_out' | t }}{% else %}{{ 'products.product.add_to_cart' | t }}{% endunless %}"
                  class="btn product-form__cart-submit{% if section.settings.enable_payment_button %} btn--secondary-accent{% endif %}"
                  data-add-to-cart>
                  <span data-add-to-cart-text>
                    {% unless current_variant.available %}
                      {{ 'products.product.sold_out' | t }}
                    {% else %}
                      {{ 'products.product.add_to_cart' | t }}
                    {% endunless %}
                  </span>
                  <span class="hide" data-loader>
                    {% include 'icon-spinner' %}
                  </span>
                </button>
                {% if section.settings.enable_payment_button %}
                  {{ form | payment_button }}
                {% endif %}
              </div>
            </div>
          {% endform %}
        </div>
 
        {%- comment -%}
          Live region for announcing updated price and availability to screen readers
        {%- endcomment -%}
        <p class="visually-hidden" data-product-status
          aria-live="polite"
          role="status"
        ></p>
 
      
        {%- comment -%}
          Live region for announcing that the product form has been submitted and the
          product is in the process being added to the cart
        {%- endcomment -%}
        <p class="visually-hidden" data-loader-status
          aria-live="assertive"
          role="alert"
          aria-hidden="true"
        >{{ 'products.product.loader_label' | t }}</p>
 
      <!-- orkun -->
          <div class="product-single__description rte" itemprop="description">
          {{ product.description }}
      </div>
      
      <div id="shopify-product-reviews" data-id="{{product.id}}">{{ product.metafields.spr.reviews }}</div> 
      
       {% if section.settings.show_share_buttons %}
         {% include 'social-sharing', share_title: product.title, share_permalink: product.url, share_image: product.featured_media %}
       {% endif %}
      
      <div itemprop="aggregateRating" itemscope itemtype="https://schema.org/AggregateRating">
<span itemprop="ratingValue">{{ product.metafields.spr.reviews | split: '"ratingValue": "' | last | split: '"' | first | plus: 0 }}</span>
yıldız – <span itemprop="reviewCount"> {{ product.metafields.spr.reviews | split: '"reviewCount": "' | last | split: '"' | first | plus: 0 }}</span> yorum
</div>
      
          
      {% comment %} Added on December 8 2020 by Jonathan L at Shopify  {% endcomment %}
    {%- if review_count > 0 -%}
      "aggregateRating": {
        "@type": "AggregateRating",
        "itemReviewed": {{ product.title | json }},
        "bestRating": "5",
        "worstRating": "1",
        "ratingValue": "{{ review_rating }}",
        "reviewCount": "{{ review_count }}"
      },
 {%- endif %}
 
 
    </div>
  </div>
</div>
{% unless product == empty %}
  <script type="application/json" id="ProductJson-{{ section.id }}">
    {{ product | json }}
  </script>
  <script type="application/json" id="ModelJson-{{ section.id }}">
    {{ product.media | where: 'media_type', 'model' | json }}
  </script>
{% endunless %}
 
{%- for field in product.metafields.instructions -%}
      <li>{{ field | first }}: {{ field | last }}</li>
    {%- endfor -%}
 
{% schema %}
 
 
0 Likes
luxuriaistanbul
Excursionist
32 0 4

and here how the product.liquid looks like:

 

{% comment %}
The contents of the product.liquid template can be found in /sections/product-template.liquid
{% endcomment %}

{% section 'product-template' %}
{% section 'product-recommendations' %}

{% if collection %}
<div class="text-center return-link-wrapper page-width">
<a href="{{ collection.url }}" class="btn btn--secondary btn--has-icon-before return-link">
{% include 'icon-arrow-left' %}
{{ 'products.product.back_to_collection' | t: title: collection.title }}
</a>
</div>
{% endif %}

<script>
// Override default values of shop.strings for each template.
// Alternate product templates can change values of
// add to cart button, sold out, and unavailable states here.
theme.productStrings = {
addToCart: {{ 'products.product.add_to_cart' | t | json }},
soldOut: {{ 'products.product.sold_out' | t | json }},
unavailable: {{ 'products.product.unavailable' | t | json }}
}
</script>

{% assign current_variant = product.selected_or_first_available_variant %}

<script type="application/ld+json">
{
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ product.metafields.manysales.review_avg_rating }}",
"reviewCount": "{{ product.metafields.manysales.review_count }}"
},
"@context": "http://schema.org/",
"@type": "Product",
"name": {{ product.title | json }},
"url": {{ shop.url | append: product.url | json }},
{%- if product.featured_media -%}
{%- assign media_size = product.featured_media.preview_image.width | append: 'x' -%}
"image": [
{{ product.featured_media | img_url: media_size | prepend: "https:" | json }}
],
{%- endif -%}
"description": {{ product.description | strip_html | json }},
{%- if current_variant.sku != blank -%}
"sku": {{ current_variant.sku | json }},
{%- endif -%}
"brand": {
"@type": "Thing",
"name": {{ product.vendor | json }}
},
"offers": [
{%- for variant in product.variants -%}
{
"@type" : "Offer",
{%- if variant.sku != blank -%}
"sku": {{ variant.sku | json }},
{%- endif -%}
"availability" : "http://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}",
"price" : {{ variant.price | divided_by: 100.00 | json }},
"priceCurrency" : {{ cart.currency.iso_code | json }},
"url" : {{ shop.url | append: variant.url | json }}
}{% unless forloop.last %},{% endunless %}
{%- endfor -%}
]
}
</script>

0 Likes
EmmanuelFlossie
Shopify Partner
814 31 182

You seem to have multiple codes, make sure to combine and only show one code. It looks like you use someone to do this for you.

I recommend getting back in touch with Added on December 8 2020 by Jonathan L at Shopify

To help you resolve this issue.

SImply copy pasting a few pages, does not work. Structured data can be installed from many different areas.

I'm a Google Shopping Specialist & a Google Ads Platinum Product Expert (Only a hand full of Platinum experts in the world!)
Need Premium Data Feed Management Support? Get in touch.
0 Likes
luxuriaistanbul
Excursionist
32 0 4

Thank you very much for your response. 

We had problem with shopify review app, that snippet was not working, even if we had the code for snippet. 

I will contact shopify support. Lets see if they recommend something.

0 Likes
simone83
Tourist
10 1 2

Is there any news about this case? Our structured data is set up correctly in our theme. And Google's rich snippet test says everything is perfect.

Until someone creates a product review using Shopify's product review app. Then it gets ugly because of the extra ld+json code added by the product review app. I tried to remove the ld+json code from the product review app via JS, but the JS code doesn't work (and I'm not a JS developer, so I'm lost). That's the only problem I have with structured data. I don't want a product review app to interfere with me and embed structured data into our HTML code itself.

So, how can I remove this extra structured data from the Shopify Product Review app? Does anyone have any ideas? Thank you.

0 Likes
EmmanuelFlossie
Shopify Partner
814 31 182

You can simply ignore how ugly it looks. As long as there are no errors.

Warnings are ok as these are optional.

Google Merchant Center will read only the first product container.

Google Search Console will merge all containers together.

I'm a Google Shopping Specialist & a Google Ads Platinum Product Expert (Only a hand full of Platinum experts in the world!)
Need Premium Data Feed Management Support? Get in touch.
0 Likes
simone83
Tourist
10 1 2

Thank you for your reply @EmmanuelFlossie !

Our structured data code in theme is at the top of the page and includes all necessary (and unnecessary) data, including review and breadcrumb data. And in the middle of the HTML code there is the inserted code from the review app which only includes a simple product object (with a lot of missing information) and the review data.

When I look at the rich result testing tool from Google then the order is wrong and the information are double. But at least everything is green.

item-with-review.png

 

 

 

 

 

 

 

 

 

 

 

However, if I go to snippet preview then the search result doesn't contain any rich result information.

If a product doesn't have any reviews then everything works and also the rich result is shown with all information in the preview:
item-without-reviews.png

 

 

 

 

 

 

 

 

What do you think? 

0 Likes
EmmanuelFlossie
Shopify Partner
814 31 182

I recommend looking through your code to ensure the complete data is first, ie at the top.

You will need to sift through the theme and see how everything is built.

Every theme is different, and even with the same theme, the coding will be different depending on custom edits.

I'm a Google Shopping Specialist & a Google Ads Platinum Product Expert (Only a hand full of Platinum experts in the world!)
Need Premium Data Feed Management Support? Get in touch.
0 Likes