Shopify Rich Snippets Tutorial: No App Needed

If you want to increase your organic search traffic without increasing your rankings, one easy strategy is to use rich snippets to stand out in the SERPs.

The good news is:

You’re probably already using them, most themes have them built in. Though, there are usually a few things missing or conflict issues caused by apps, so in this guide we’ll cover how to ensure your store is fully capitalising on this.

What are Rich Snippets?

Rich Snippets (also known as Rich Results) are the additional data sometimes added to normal Google search results.

So if you’re searching on Google, a normal result may look similar to this:

But with a Rich Snippet, it could look like this:

This additional rating part (i.e. Rich Snippet) makes your website stand out and can often lead to higher click-through rate.

Types of Rich Snippets for eCommerce

There are many types of Rich Snippets you can try to get, but a lot of them are specific to certain types of sites such as Recipes or Music.

Below are a few common types you’ll want to use for your store:

Reviews: A star rating out of 5 for aggregate reviews or an individual reviewer. Perfect to show overall reviews for each of your products.

Product Offer: Information about your product, including price, product images, and stock level.

Organisation: Explain the key details of your business, including name, address, logo, and contact information.

FAQ: Answer common questions about this topic and have these questions show in the search results.

What is Structured Data?

These Rich Snippets come from search engines’ ability to understand your content, which is achieved with Structured Data.

Whereas for humans, we can read a product page and instantly understand which part is the name, description, product image, price, etc. This is not always immediately obvious to robots, i.e. search engines.

By deliberately adding some code to your webpages, you can clearly label each of these items for search engines to know.

And if it works, you’ll be rewarded with a lovely Rich Snippet.

The basics of structured data

Structured data format

There are 3 formats of structured data:

  1. Microdata
  2. JSON-LD
  3. RDFa

These represent different ways of coding the structured data into your page. Microdata and JSON-LD are the most popular two, it’s likely your Shopify Theme or App is using one of these two.

My recommendation is to use JSON-LD.

The difference is JSON-LD is a piece of code you can add anywhere on your page, irrespective of your content. Whereas Microdata is a markup to wrap around your existing content, which is more difficult to set up. JSON-LD is also recommended by Google.

We’ll cover how to set up JSON-LD structured data in the “How to add structured data to Shopify” section.

Data vocabulary

Vocabulary refers to the property names you’re using in your structured data. This is how search engines understand your structured data.

On your product page for example, the product brand should be “brand” not “vendor” as Shopify would call it.

The most commonly used vocabulary is schema.org. All popular search engines accept this and most themes/apps will use this, so it’s recommended to stick with it.

Data Types

The data type is what this structured data is describing.

For eCommerce, you’ll commonly use:

  • Product to describe each product
  • Offer to describe your product price and options
  • AggregateRating to summarise each product’s overall rating and reviews
  • Article to describe your blog posts and articles
  • Organization to describe your company details
  • WebSite to describe how to search your website
  • BreadcrumbList to describe your breadcrumbs
  • FAQPage to describe frequently asked questions (and answers) used on your pages

Recommendations for Shopify stores

While every eCommerce store is different, there’s usually a few specific types of pages and types of structured data I’d recommend using.

Homepage

Organization: This is a standard place to explain the details of your company.

WebSite: Searching is important for eCommerce stores, this markup will describe to search engines how to do it.

Collections

BreadcrumbList: Your breadcrumb should link back to your homepage and possibly a parent collection, make sure this is marked up with schema for search engines to understand.

FAQPage: Add a list of frequently asked questions at the bottom of your page for additional content, then mark this up as FAQPage, you may even get the rich snippet.

Products

BreadcrumbList: Your breadcrumb should link back to the homepage along with any collections and sub-collections, make sure this is marked up with schema.

Product: Describe the product details for search engines.

Offer: Describe the product’s pricing options and stock.

AggregateRating: Summarise the overall rating and reviews for this product.

Blog Posts

BreadcrumbList: Your breadcrumb should link to homepage and main blog page, mark this up with schema

Article: Describe the title, author, and article content

Checking your existing structured data

It’s highly likely your Shopify Theme and/or Apps are adding structured data to your pages already, so I’d highly recommend testing them first.

You can do this on an individual page basis or a site-wide basis using Google Search Console, I recommend both.

Google Search Console

If your website is using structured data and has been setup with GSC for a while, you should see an “Enhancements” section in the sidebar of GSC:

Click on one of these, say Breadcrumb, and you’ll be taken to a page like this:

Hopefully there are no Errors, otherwise you’ll want to dive into the Details section to see what they are and which pages they apply to.

For 100+ page websites though, you’re likely to find “Valid with warning” pages. These aren’t a big deal, warnings are normal, but worth checking.

These aggregateRating and review fields warnings are commonly caused by products not having any reviews, though it could also be they’re not being utilised.

And of course the “Valid” ones are good to go. That’s a nice confirmation you’re using Schema and it’s setup correctly.

What you’re looking for is any missing types such as Breadcrumbs, Product, FAQ, Review Snippet, or Sitelinks search box. If these are all being utilised, look for Errors or Warnings next.

Individual Pages

Individual pages can be checked with Google’s Rich Results Testing tool.

Simply enter your URL (or code), then click Test URL:

After this, you’ll be taken to a page like this:

In this case we can see the page is using structured data and is eligible for rich results.

Diving deeper into it, we can see they’re using Products schema and Offer schema within this:

For GymShark, they actually have 11 products on this one page.

Why? They’re marking up every colour and product variant on this page as separate Products. This makes sense for product variants, though I probably wouldn’t do that for completely different products like “Gymshark Arrival 5″ Shorts – Black”, which I presume are pulling in from the “You Might Like” section at the bottom.

How to add structured data to Shopify

You don’t need an app to add Structured Data to Shopify, especially if you’re using JSON-LD format, it’s as simple as pasting some code either into the page directly or the theme files.

Here’s how to do it:

Add to the page description

For FAQPage schema, you can paste this directly into your Collection page by switching to HTML/Code mode:

Then pasting the Schema.org code at the top or bottom (not important which):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [{
    "@type": "Question",
    "name": "Is this article helpful?",
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "I hope so, but feel free to contact us and let us know!"
    }
  },{
    "@type": "Question",
    "name": "Should you hire us for help with SEO and rich snippets?",
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "Probably. You're welcome to try this yourself, but be careful to test it. There's a lot more to SEO than rich snippets though, so wouldn't be a bad idea to get some experienced recommendations."
    }
  }]
}
</script>

As for generating it, just use a FAQPage schema generator.

Add to the theme

For everything else, you’ll want to add it into your theme, though likely a basic version of it is already there by default.

You can edit these by going to Online Store> Themes > Actions > Edit Code:

Here’s an example of where to add it from one of our clients (every theme is slightly different):

Product Schema: The product-template.liquid section includes a product-schema.liquid snippet which contains the structured data code.

<script type="application/ld+json">
{
  "@context": "http://schema.org/",
  "@type": "Product",
  "name": "{{ product.title | strip_html | escape }}",
  "url": "{{ shop.url }}{{ product.url }}",
  "sku": "{{fa_product_id_value}}",
  {%- if product.variants.first.barcode.size == 12 -%}
    "gtin12": {{ product.variants.first.barcode }},
  {%- endif -%}
  {%- if product.variants.first.barcode.size == 13 -%}
    "gtin13": {{ product.variants.first.barcode }},
  {%- endif -%}
  {%- if product.variants.first.barcode.size == 14 -%}
    "gtin14": {{ product.variants.first.barcode }},
  {%- endif -%}
    "productID": "{{ product.id }}",
  "brand": {
    "@type": "Thing",
    "name": "{{ product.vendor | escape }}"
  },
  "description": {{ product.description | strip_html | json }},
  "image": "https:{{ product.featured_image.src | img_url: 'grande' }}",
  {%- if product.variants -%}
  {%- assign fa_count = fa_count | plus: 1 -%}
    "offers":
      {
        "@type" : "Offer",
        "priceCurrency": "{{ cart.currency.iso_code }}",
        "price": "{{ fa_product_price }}",
        "itemCondition" : "http://schema.org/NewCondition",
        "availability" : "http://schema.org/{% if fa_current_variant.available %}InStock{% else %}OutOfStock{% endif %}",
        "url" : "{{ shop.url }}{{ fa_current_variant.url }}",
            {%- if fa_current_variant.image -%}
              {%- assign variant_image_size = fa_current_variant.image.width | append: 'x' -%}
              "image": "https:{{ fa_current_variant.image.src | img_url: variant_image_size }}",
            {%- else -%}
              "image": "https:{{ product.featured_image.src | img_url: 'grande' }}",
            {%- endif -%}
            {%- if fa_current_variant.title != 'Default Title' -%}
              "name" : "{{ product.title | strip_html | escape }} - {{ fa_current_variant.title | escape }}",
            {%- else -%}
              "name" : "{{ product.title | strip_html | escape }}",
            {%- endif -%}
            {%- if fa_current_variant.barcode.size == 12 -%}
              "gtin12": {{ fa_current_variant.barcode }},
            {%- endif -%}
            {%- if fa_current_variant.barcode.size == 13 -%}
              "gtin13": {{ fa_current_variant.barcode }},
            {%- endif -%}
            {%- if fa_current_variant.barcode.size == 14 -%}
              "gtin14": {{ fa_current_variant.barcode }},
            {%- endif -%}
			         "sku": "{{fa_product_id_value}}",
            {%- if product.description != blank -%}
            "description" : {{ product.description | strip_html | json }},
            {%- endif -%}
          "priceValidUntil": "{{ 'now' | date: '%s' | plus: 31536000 | date: '%Y-%m-%d' | uri_encode | replace:'+','%20' }}"
      }
    {%- if product.variants.size > 1 -%},
      "additionalProperty": [{
        "@type": "PropertyValue",
        "propertyID": "item_group_id",
        "value": "{{ product.id }}"
      }]
      {%- endif -%}
    {%- if product.metafields.spr.reviews -%}
    {%- assign fa_rating = product.metafields.spr.reviews | split: '"reviewCount": "' | last | split: '"' | first | plus: 0 -%}
    {%- if fa_rating > 0 -%}
    ,"aggregateRating": {
     "@type": "AggregateRating",
     "ratingValue": {{ product.metafields.spr.reviews | split: '"ratingValue": "' | last | split: '"' | first | plus: 0 }},
     "ratingCount": {{ product.metafields.spr.reviews | split: '"reviewCount": "' | last | split: '"' | first | plus: 0 }}
    }
    {%- endif -%}
    {%- endif -%}
  {%- endif -%}
}
</script>

Breadcrumb Schema: Can be added to or customised in breadcrumbs.liquid under theme snippets.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [{
    "@type": "ListItem",
    "position": 1,
    "item": {
      "@id": "{{ shop.url }}",
      "name": "{{ 'general.breadcrumbs.home' | t }}"
    }
  },
{% if product.metafields.global.breadcrumb != blank %}
{
    "@type": "ListItem",
    "position": 2,
    "item": {
      "@id": "{{ collections[product.metafields.global.breadcrumb].url }}",
      "name": "{{ collections[product.metafields.global.breadcrumb].title }}"
    }
  },{
    "@type": "ListItem",
    "position": 3,
    "item": {
      "@id": "{{ product.url }}",
      "name": "{{ product.title }}"
    }
  }
{% elsif %}
{
    "@type": "ListItem",
    "position": 2,
    "item": {
      "@id": "{{ product.url }}",
      "name": "{{ product.title }}"
    }  
}]
{% endif %}
}
</script>

(Note: The above code presumes you’re using a custom meta field for breadcrumbs, as explained in our full Shopify SEO guide)

Organization Schema: We created a new organization-schema.liquid snippet which contains the structured data code then included this in index.liquid template.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Corporation",
  "name": "{{ shop.name }}",
  "url": "{{ shop.secure_url }}/",
  "logo": "https://enter-logo-url",
  "sameAs": [
    "https://link-to-social-profile-like-fb",
    "https://link-to-social-profile-like-twitter",
    "https://link-to-social-profile-like-ig"
  ]
}
</script>

WebSite Schema: Added after <head> tag in theme.liquid layout.

<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "WebSite",
  "name": "{{ shop.name }}",
  "url": "{{ shop.secure_url }}",
  "potentialAction": {
    "@type": "SearchAction",
    "target": "{{ shop.secure_url }}/search?type=product&q={search_term_string}",
    "query-input": "required name=search_term_string"
  }
}
</script>  

Article Schema: The article.liquid template file includes an article-template.liquid section which contains the schema.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "{{ article.url }}"
  },
  "headline": "{{ article.title }}",
  "description": "{{ article.excerpt }}",
  "image": "{{ article.image.src }}",  
  "author": {
    "@type": "Person",
    "name": "{{ article.author }}"
  },  
  "publisher": {
    "@type": "Organization",
    "name": "{{ shop.name }}",
    "logo": {
      "@type": "ImageObject",
      "url": "https://enter-logo-url"
    }
  },
  "datePublished": "{{ article.published_at | date: '%Y-%m-%d' }}",
  "dateModified": "{{ article.updated_at | date: '%Y-%m-%d' }}",
}
</script>

Frequently Asked Questions

I have set up structured data, but why don’t I have a rich snippet?

That could happen for any of these reasons:

  1. They haven’t crawled your updated page yet.
  2. They don’t think it’s relevant.
  3. You’re in a competitive niche where they don’t show them often.
  4. It’s not the right type of page/structured data for this keyword.
  5. Your website doesn’t have enough trust/authority.

Do I need to worry about GSC warnings?

Warnings are nothing to worry about, they’re usually recommendations only. Especially if it’s warnings for lack of reviews/ratings on products, this usually is a result of having no reviews for that product yet. Errors, however, should absolutely be addressed.

Why are there multiple / duplicate structure data tags on my page?

Sometimes there’s a conflict between the theme and apps, which causes structured data to be added multiple times. I recommend having a developer look at the code to see if they can identify where it’s coming from, then remove one of them.

Do I need an app for this?

Absolutely not. In fact, I’d recommend against it. Most these apps are trying to sell you something your theme probably does by default. The extras they’re offering can be done easily with a free JSON-LD structured data generator tool – very easy.

Final Thoughts

I’d highly recommend using structured data on your Shopify store, to recap, here’s what you should do now:

  1. Check Google Search Console for issues with your existing setup (and fix them)
  2. Manually check a few different page types with Google’s rich snippet tester tool
  3. Tweak/fix your existing structured data setup for product, collections, homepage, breadcrumbs, and blog posts (as explained above)
  4. Manually add structured data to descriptions such as FAQ schema
  5. Re-test this after adding, then periodically check on GSC for issues

Hopefully this will result in landing some rich snippets, if not, keep going with your SEO and they’ll probably come. A lot of this depends on the specific keyword, overall niche, and your website’s trust/authority.

Either way, this is well worth putting in the small effort to set it up correctly.

Additional Reading

For more Shopify SEO advice, check out these articles: