Schema.org for Category page - categories

Backstory: I'm working on e-commerce shop, we have category page displaying thumbnails of products, along with their prices, names, and short description. Can't buy from this page, need to enter product details page first.
I'm really confused about the usage of schema.org on category pages.
Came up with couple of solutions but can't tell which one's best (prefer the last one tbh)
ItemList with ListItems inside as recommended on https://developers.google.com/search/docs/guides/mark-up-listings
(Products are not supported, but it shows the idea behind placing several items on the site)
{
"#context": "http://schema.org",
"#type": "ItemList",
"name": "T-Shirt",
"url": "/category/t-shirt/",
"description": "Deserunt quibusdam ipsa illo ex nam ea illo qui. Itaque maiores doloribus accusamus ratione. Aperiam ipsa veritatis quas nisi.",
"itemListOrder": "Unordered",
"numberOfItems": 2,
"itemListElement": [
{
"#type": "ListItem",
"position": 1,
"url": "/products/lopez-smith-25/?color=yellow&size=XXL",
"name": "Yellow Lopez-Smith",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/yellow_n2QjKzn-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
},
{
"#type": "ListItem",
"position": 2,
"url": "/products/lopez-smith-25/?color=blue&size=37",
"name": "Blue Lopez-Smith",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/blue_FZ3yJjG-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
}
]
}
Several Products as recommended on https://developers.google.com/search/docs/guides/sd-policies
Joined together using #graph
A category page listing several different products (or recipes, videos, or any other type). Each entity should be marked up using the relevant schema.org type, such as schema.org/Product for product category pages. However, if one item is marked, all items should be marked. Also, unless this is a carousel page, the marked items should not link out to separate details pages.
{
"#context": "http://schema.org",
"#graph": [
{
"#type": "Product",
"#id": "/category/t-shirt/p-1",
"description": "Nobis vel fugiat e",
"name": "Yellow Lopez-Smith",
"offers": {
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "18.28",
"priceCurrency": "GBP",
"itemCondition": "http://schema.org/NewCondition",
"description": "Nobis vel fugiat e",
"name": "Yellow Lopez-Smith",
"gtin13": "68614",
"category": "T-Shirt",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/yellow_n2QjKzn-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
}
},
{
"#type": "Product",
"#id": "/category/t-shirt/p-2",
"description": "Nobis vel fugiat e",
"name": "Blue Lopez-Smith",
"offers": {
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "22.64",
"priceCurrency": "GBP",
"itemCondition": "http://schema.org/NewCondition",
"description": "Nobis vel fugiat e",
"name": "Blue Lopez-Smith",
"gtin13": "73963",
"category": "T-Shirt",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/blue_FZ3yJjG-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
}
}
]
}
Different Products listed as ItemOffered inside of Offer (based on Ebay)
{
"#context": "http://schema.org",
"#type": "WebPageElement",
"offers": {
"#type": "Offer",
"itemOffered": [
{
"#type": "Product",
"#id": "/category/t-shirt/p-1",
"description": "Nobis vel fugiat e",
"name": "Yellow Lopez-Smith",
"offers": {
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "18.28",
"priceCurrency": "GBP",
"itemCondition": "http://schema.org/NewCondition",
"description": "Nobis vel fugiat e",
"name": "Yellow Lopez-Smith",
"gtin13": "68614",
"category": "T-Shirt",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/yellow_n2QjKzn-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
}
},
{
"#type": "Product",
"#id": "/category/t-shirt/p-2",
"description": "Nobis vel fugiat e",
"name": "Blue Lopez-Smith",
"offers": {
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "22.64",
"priceCurrency": "GBP",
"itemCondition": "http://schema.org/NewCondition",
"description": "Nobis vel fugiat e",
"name": "Blue Lopez-Smith",
"gtin13": "73963",
"category": "T-Shirt",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "/media/__sized__/products/blue_FZ3yJjG-thumbnail-640x640-70.jpg",
"description": "Lopez-Smith",
"width": 640,
"height": 640
}
}
}
]
}
}
Any help would be appreciated

Related

What is the correct structure to represent a list of movie showtimes on the same page?

I am building a website to reference movie showtimes.
The site shows a now playing page with a list of movies, each movie has a page with the upcoming showtimes.
I added some structured data to enhance the way search engines sees the data on my website.
Here is what I have so far:
{
"#context": "https://schema.org",
"#type": "ItemList",
"numberOfItems": 2,
"itemListElement": [
{
"#type": "ListItem",
"name": "Screening Event 1",
"position": 1,
"item": {
"#context": "https://schema.org",
"#type": "ScreeningEvent",
"startDate": "2021-09-18T15:15:00.000Z",
"url": "http://localhost:3000/film/Boite-noire/663260#6144ab7a22b6d900165aa836",
"inLanguage": "fr",
"location": {
"#context": "https://schema.org",
"#type": "MovieTheater",
"name": "Pathé Tunis City",
"url": "http://localhost:3000/medium/pathe-tunis-city"
},
"workPresented": {
"#context": "https://schema.org",
"#type": "Movie",
"name": "Boîte noire",
"image": "https://image.tmdb.org/t/p/w300_and_h450_bestv2/jIfFFC4YwiI8TVaGtbl1eT9BRaI.jpg",
"url": "http://localhost:3000/film/Boite-noire/663260",
"sameAs": "https://imdb.com/title/tt10341034",
"director": {
"#type": "Person",
"name": "Yann Gozlan"
}
}
}
},
{
"#type": "ListItem",
"name": "Screening Event 2",
"position": 2,
"item": {
"#context": "https://schema.org",
"#type": "ScreeningEvent",
"startDate": "2021-09-18T20:15:00.000Z",
"url": "http://localhost:3000/film/Boite-noire/663260#6144ab8522b6d900165aa837",
"inLanguage": "fr",
"location": {
"#context": "https://schema.org",
"#type": "MovieTheater",
"name": "Pathé Tunis City",
"url": "http://localhost:3000/medium/pathe-tunis-city"
},
"workPresented": {
"#context": "https://schema.org",
"#type": "Movie",
"name": "Boîte noire",
"image": "https://image.tmdb.org/t/p/w300_and_h450_bestv2/jIfFFC4YwiI8TVaGtbl1eT9BRaI.jpg",
"url": "http://localhost:3000/film/Boite-noire/663260",
"sameAs": "https://imdb.com/title/tt10341034",
"director": {
"#type": "Person",
"name": "Yann Gozlan"
}
}
}
}
]
}
Is there a better way to represent this kind of information without repeating data ?
My suggestion gave the google guide for Carousel --> Single, all-in-one-page list:
{
"#context": "https://schema.org",
"#type": "Movie",
...
"#id":"https://cinema.com/lordofrings.html",
"name":"Lord of the rings",
"subjectOf":{
"#type": "ItemList",
"itemListElement": [
{
"#type": "ListItem",
"position": "1",
"item": {
"#type": "ScreeningEvent",
"url": "https://cinema.com/lordofrings.html#15",
"startDate": "2021-09-18T15:00:00+01:00"
}
},
{
"#type": "ListItem",
"position": "2",
"item": {
"#type": "ScreeningEvent",
"url": "https://cinema.com/lordofrings.html#18",
"startDate": "2021-09-18T18:00:00+01:00"
}
}
]
}
}
For ellipsis, set the required movie info and add all the required and recommended properties for the Google Rich Results Test.

SDTT warning: "The property priceSpecification is not recognized by Google for an object of type Product."

I have the following JSON-LD and am trying to represent a pay monthly product such as a mobile phone contract which consists of an upfront fee and a monthly fee.
When I try to add the unitCode, I get the following warning:
The property priceSpecification is not recognized by Google for an object of type Product.
{
"#context": "https://schema.org/",
"#type": "Product",
"name": "Apple iPhone",
"image": [
"https://example.com/photos/1x1/photo.jpg",
"https://example.com/photos/4x3/photo.jpg",
"https://example.com/photos/16x9/photo.jpg"
],
"description": "Apple iPhone XS ...",
"sku": "0446310786",
"mpn": "925872",
"brand": {
"#type": "Thing",
"name": "ACME"
},
"review": {
"#type": "Review",
"reviewRating": {
"#type": "Rating",
"ratingValue": "4",
"bestRating": "5"
},
"author": {
"#type": "Person",
"name": "Fred Benson"
}
},
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": "4.4",
"reviewCount": "89"
},
"offers": {
"#type": "Offer",
"url": "https://example.com/anvil",
"priceCurrency": "GBP",
"price": "39.99",
"priceValidUntil": "2020-11-05",
"itemCondition": "https://schema.org/UsedCondition",
"availability": "https://schema.org/InStock",
"seller": {
"#type": "Organization",
"name": "Executive Objects"
}
},
"priceSpecification": {
"#type": "UnitPriceSpecification",
"price": "25",
"priceCurrency": "GBP",
"referenceQuantity": {
"unitCode": "MON"
}
}
}
You need to add the priceSpecification property to the Offer, not to the Product.
{
"#context": "https://schema.org/",
"#type": "Product",
"offers": {
"#type": "Offer",
"priceSpecification": {
"#type": "UnitPriceSpecification"
}
}
}
You can find the expected domain/range of a property on its page. For priceSpecification, it says:
Used on these types
Demand
Offer
TradeAction
So, it’s not expected on Product.

What's the best schema.org type to use to describe weekly yoga classes?

The page https://www.hello-yoga.co.uk describes two yoga classes, that run every week.
Is an Event with a potentialAction of type ExerciseAction the best way to represent the classes?
Note these are classes that take place in various locations (e.g. church halls) so HealthClub didn't seem an appropriate type.
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Event",
"name": "hello YOGA",
"startDate": "2018-06-13T19:45",
"endDate": "2018-06-13T20:45",
"description":
"Yoga class at Friends Meeting House (Harrogate) every Thursday.",
"image": "https://www.hello-yoga.co.uk/yoga-people.svg",
"location": {
"#type": "Place",
"name": "Friends Meeting House",
"address": {
"#type": "PostalAddress",
"streetAddress": "12A Queens Parade",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"postalCode": "HG1 5PP",
"addressCountry": "GB"
}
},
"offers": {
"#type": "Offer",
"availability": "http://schema.org/LimitedAvailability",
"price": "7.00",
"priceCurrency": "GBP",
"validFrom": "2018-05-01T12:00",
"url": "https://www.hello-yoga.co.uk"
},
"potentialAction": {
"#type": "ExerciseAction",
"name": "hello YOGA",
"description": "Small, friendly yoga class. Suitable for all abilities.",
"exerciseType": "Yoga",
"startTime": "2018-06-13T19:45",
"endTime": "2018-06-13T20:45",
"location": {
"name": "Friends Meeting House",
"#type": "PostalAddress",
"streetAddress": "12A Queens Parade",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"postalCode": "HG1 5PP",
"addressCountry": "GB"
}
},
"performer": {
"#type": "LocalBusiness",
"description":
"Small, friendly yoga classes. Suitable for all abilities. Strengthen body, increase flexibility and calm the mind.",
"name": "hello YOGA",
"email": "clare#hello-yoga.co.uk",
"url": "https://www.hello-yoga.co.uk",
"priceRange": "£7",
"image": "https://www.hello-yoga.co.uk/yoga-people.svg",
"address": {
"#type": "PostalAddress",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"addressCountry": "GB"
}
}
}
</script>
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Event",
"name": "hello YOGA",
"startDate": "2018-06-07T19:00",
"endDate": "2018-06-07T20:00",
"description":
"Yoga class at Beckwith Health Club (Harrogate) every Wednesday.",
"image": "https://www.hello-yoga.co.uk/yoga-people.svg",
"location": {
"#type": "Place",
"name": "Beckwith Health Club",
"address": {
"#type": "PostalAddress",
"streetAddress": "Beckwith Health Club",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"postalCode": "HG3 1UF",
"addressCountry": "GB"
}
},
"offers": {
"#type": "Offer",
"availability": "http://schema.org/LimitedAvailability",
"price": "7.00",
"priceCurrency": "GBP",
"validFrom": "2018-05-01T12:00",
"url": "https://www.hello-yoga.co.uk"
},
"potentialAction": {
"#type": "ExerciseAction",
"name": "hello YOGA",
"description": "Small, friendly yoga class. Suitable for all abilities.",
"exerciseType": "Yoga",
"startTime": "2018-06-07T19:00",
"endTime": "2018-06-07T20:00",
"location": {
"name": "Beckwith Health Club",
"#type": "PostalAddress",
"streetAddress": "Beckwith Health Club",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"postalCode": "HG3 1UF",
"addressCountry": "GB"
}
},
"performer": {
"#type": "LocalBusiness",
"description":
"Small, friendly yoga classes. Suitable for all abilities. Strengthen body, increase flexibility and calm the mind.",
"name": "hello YOGA",
"email": "clare#hello-yoga.co.uk",
"url": "https://www.hello-yoga.co.uk",
"priceRange": "£7",
"image": "https://www.hello-yoga.co.uk/yoga-people.svg",
"address": {
"#type": "PostalAddress",
"addressLocality": "Harrogate",
"addressRegion": "North Yorkshire",
"addressCountry": "GB"
}
}
}
</script>

aggregateRating within Review object

We're trying to use the aggregateRating tag but we're getting this warning in the SDTT:
The aggregateRating property inside a Review object applies to the review itself, as a creative work. Did you mean to use reviewRating instead.
We want to aggregate the reviews from all users, not use reviewRating (we already use that one for our own reviews).
Does anyone know how to fix this error?
JSON-LD (example page):
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Review",
"name": "It",
"datePublished": "2017-09-06",
"description": "Based on Stephen King's 1986 novel, […]",
"url": "https://dev.commonsensemedia.org/movie-reviews/it",
"reviewBody": "Based on Stephen King's 1986 novel, […]",
"author": {
"#type": "Person",
"name": "Jeffrey M. Anderson",
"sameAs": "https://dev.commonsensemedia.org/users/jeffrey-m-anderson"
},
"itemReviewed": {
"#type": "Movie",
"name": "It",
"sameAs": "http://www.imdb.com/title/tt1396484/",
"datePublished": "2017-09-08",
"image": {
"#type": "ImageObject",
"url": "image.jpg"
},
"director": {
"#type": "Person",
"name": "Andres Muschietti"
},
"actor": [
{
"#type": "Person",
"name": "Bill Skarsg\u00e5rd"
},
{
"#type": "Person",
"name": "Jaeden Lieberher"
},
{
"#type": "Person",
"name": "Finn Wolfhard"
}
]
},
"publisher": {
"#type": "Organization",
"name": "Common Sense Media",
"sameAs": "https://www.commonsensemedia.org"
},
"reviewRating": {
"#type": "Rating",
"ratingValue": "4"
},
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": "4.04651",
"bestRating": 5,
"worstRating": 1,
"reviewCount": "43",
"name": "Parents say",
"description": "All parent member reviews for It"
}
}
</script>
When you add the aggregateRating property to the Review item, the aggregated rating is for the review, not for the reviewed item.
If the aggregated rating is for the reviewed item, you have to add the aggregateRating to this item (e.g., Movie).
If that is what you want, you can move the aggregateRating under Movie, e.g.:
{
"#context": "http://schema.org",
"#type": "Review",
"itemReviewed": {
"#type": "Movie",
"aggregateRating": {
"#type": "AggregateRating"
}
}
}

Error in Google SDTT: "Duplicate values for url are not allowed."

Google Structured Data Testing Tool returns for the following JSON-LD:
Duplicate values for url are not allowed.
Why? I do not understand.
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "ItemList",
"itemListElement": [{
"#type": "ListItem",
"position": 0,
"item": {
"#type": "Article",
"headline": "Bonito de norte",
"alternativeHeadline": "Thunnus alalunga.",
"image": {
"#type": "ImageObject",
"url": "http://dechado09.softgalia.com/producto/imagenes/facebook/2/BONITO.jpg?1502195043",
"width": "1200",
"height": "830"
},
"author": "SoftGalia Aplicaciones Informáticas S.L.",
"editor": "Pescados Trocheros",
"keywords": "Venta pescado, Mayorista de Pescado",
"publisher": {
"#type": "Organization",
"name": "Academia Lucense de Balonmano",
"logo": {
"#type": "ImageObject",
"url": "http://dechado09.softgalia.com/logo/facebook/1/logo-trochero-01.jpg?1504175529",
"width": "1200",
"height": "830"
}
},
"url": "http://dechado09.softgalia.com/productos/index",
"datePublished": "2017-08-08 12:24:11 UTC",
"dateCreated": "2017-08-08 12:24:11 UTC",
"dateModified": "2017-08-22 07:43:53 UTC",
"description": "Thunnus alalunga.",
"articleBody": "Thunnus alalunga.",
"mainEntityOfPage": "http://dechado09.softgalia.com/productos/index"
}
},
{
"#type": "ListItem",
"position": 1,
"item": {
"#type": "Article",
"headline": "Merluza",
"alternativeHeadline": "Merluccius merluccius",
"image": {
"#type": "ImageObject",
"url": "http://dechado09.softgalia.com/producto/imagenes/facebook/4/merluza-primer-plano.jpeg?1504525751",
"width": "1200",
"height": "830"
},
"author": "SoftGalia Aplicaciones Informáticas S.L.",
"editor": "Pescados Trocheros",
"keywords": "Venta pescado, Mayorista de Pescado",
"publisher": {
"#type": "Organization",
"name": "Academia Lucense de Balonmano",
"logo": {
"#type": "ImageObject",
"url": "http://dechado09.softgalia.com/logo/facebook/1/logo-trochero-01.jpg?1504175529",
"width": "1200",
"height": "830"
}
},
"url": "http://dechado09.softgalia.com/productos/index",
"datePublished": "2017-09-04 11:49:13 UTC",
"dateCreated": "2017-09-04 11:49:13 UTC",
"dateModified": "2017-09-05 08:38:27 UTC",
"description": "Merluccius merluccius",
"articleBody": "Merluccius merluccius",
"mainEntityOfPage": "http://dechado09.softgalia.com/productos/index"
}
}
]
}
</script>
There are two ways to implement a list format for your structured data:
Summary page + multiple full details pages
List item A single, all-in-one-page list
My case is a sumary page of articles, and google guide say: "The summary page has a short description of each item in the list, and each description points to a separate details page that is focused entirely on one item."
well the markup must be.
{ "#context": "http://schema.org",
"#type": "ItemList",
"itemListElement":
[
{
"#type":"ListItem",
"position": 0,
"url": "http://dechado09.softgalia.com/productos/bonito-de-norte"
},
{
"#type":"ListItem",
"position": 1,
"url": "http://dechado09.softgalia.com/productos/merluza"
}
]
}