How to correctly set up multiple product offer schema per page - seo

For some reason I am having great difficulty finding this out. I have had a look here:
https://developers.google.com/search/docs/data-types/product
And here:
https://schema.org/Product
But none of the examples given show me how to add multiple product offers on a page. To illustrate what I am talking about, here is an example on our site:
https://reclaimdesign.org/vases-reclaimed-wood-stands.html
I have been having a to and fro with RankMath support about this and they tell me this is not possible. I don't believe they are right in saying that but I cannot find 100% irrefutable evidence to illustrate otherwise.
I am currently working to set up the schema myself (as the to and fro is now feeling like a waste of time). My schema code for the above page validates in the Structured Data Testing Tool:
`<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Product",
"brand": "Reclaim Design",
"logo": "https://reclaimdesign.org/wp-content/uploads/reclaim-design-logo.jpg",
"name": "4 Glamorous Sustainable Vases – Home Decor | Reclaim Design",
"image": [ "https://reclaimdesign.org/wp-content/uploads/1x1/test-tube-vases-sustainable-reclaimed-wood-stand1.jpg",
"https://reclaimdesign.org/wp-content/uploads/4x3/test-tube-vases-sustainable-reclaimed-wood-stand1.jpg",
"https://reclaimdesign.org/wp-content/uploads/16x9/test-tube-vases-sustainable-reclaimed-wood-stand1.jpg","https://reclaimdesign.org/wp-content/uploads/1x1/test-tube-vases-sustainable-reclaimed-wood-stand5.jpg",
"https://reclaimdesign.org/wp-content/uploads/4x3/test-tube-vases-sustainable-reclaimed-wood-stand5.jpg",
"https://reclaimdesign.org/wp-content/uploads/16x9/test-tube-vases-sustainable-reclaimed-wood-stand5.jpg","https://reclaimdesign.org/wp-content/uploads/1x1/bottle-vases-sustainable-reclaimed-wood-stand1.jpg",
"https://reclaimdesign.org/wp-content/uploads/4x3/bottle-vases-sustainable-reclaimed-wood-stand1.jpg",
"https://reclaimdesign.org/wp-content/uploads/16x9/bottle-vases-sustainable-reclaimed-wood-stand1.jpg","https://reclaimdesign.org/wp-content/uploads/1x1/recycled-gin-bottle-vase-sustainable-reclaimed-wood-stand.jpg",
"https://reclaimdesign.org/wp-content/uploads/4x3/recycled-gin-bottle-vase-sustainable-reclaimed-wood-stand.jpg",
"https://reclaimdesign.org/wp-content/uploads/16x9/recycled-gin-bottle-vase-sustainable-reclaimed-wood-stand.jpg"
],
"url": "https://reclaimdesign.org/vases-reclaimed-wood-stands.html",
"#id": "https://reclaimdesign.org/vases-reclaimed-wood-stands.html",
"potentialAction": {
"#type": "SearchAction",
"target": "https://reclaimdesign.org/search?q={search_term_string}",
"query-input": "required name=search_term_string"
},
"sameAs":
["https://www.facebook.com/reclaimdesignza",
"https://twitter.com/ReclaimDesignZA",
"https://www.instagram.com/reclaimdesign/",
"https://za.pinterest.com/reclaimdesignza/",
"https://www.google.com/maps/place/Reclaim+Design/#-34.03081,18.4517513,17z/data=!3m1!4b1!4m5!3m4!1s0x1dcc4242e6ad5367:0xcf5844aec51f1a43!8m2!3d-34.03081!4d18.45394"
],
"description": "Click here to find out more about our sustainable vases and vase sets with reclaimed wood stands | Reclaim Design",
"offers": [{
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "390",
"priceCurrency": "ZAR",
"url": "https://reclaimdesign.org/home-decor-shop.html/Test-Tube-Vases-With-Stand-p134947241"
},{
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "290",
"priceCurrency": "ZAR",
"url": "https://reclaimdesign.org/home-decor-shop.html/Test-Tube-Vases-With-Stand-p134947241"
},{
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "370",
"priceCurrency": "ZAR",
"url": "https://reclaimdesign.org/home-decor-shop.html/Bottle-Vases-with-Stand-p65343612"
},{
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "250",
"priceCurrency": "ZAR",
"url": "https://reclaimdesign.org/vases-reclaimed-wood-stands.html"
},{
"#type": "Offer",
"availability": "http://schema.org/InStock",
"price": "300",
"priceCurrency": "ZAR",
"url": "https://reclaimdesign.org/home-decor-shop.html/Floating-Globe-Vase-With-Stand-p65346003"
}]
}
</script>`
The RankMath support tell me "you should not use more than one product Schema per page. It does not make much sense and would only confuse Google." If they are right, why then would the code validate in Google's own testing tool?
Please can somebody with experience in this arena explain which is the correct way of doing this? TIA

You can markup your services as a product.
Two reasons to do this
Google doesn’t support “service” markup
Services are included in Product’s definition in schema.org
If you have multiple different services on a single page, then markup them one by one - individually.
If you have same services but with vivid options and price packages then use aggregate product markup.
Read about Google’s structured data product markup. You will get the sample code, which you can modify as per the requirements.

Related

Error: Missing '}' or object member name. For Schema Job Posting

When I test the code I keep seeing an error. even though I copied the code from Google WebDev website.
I tried removing some extra comma but the error keeps appearing on the test page
Here is my code. I am not able to find the issue.
{
"#context": "http://schema.org",
"#type": "JobPosting",
"title": "Varsity Squash Coach at Léman Manhattan Preparatory School",
"description": "The responsibilities of the Head Coach include:
Organizing daily sessions taking attendance, communication with players and parents.
Proven ability to exemplify the highest standards of leadership, sportsmanship, and respect
Excellent organizational skills and the ability to communicate effectively with all constituents
Willingness and ability to work evenings as dictated by game schedule
",
"identifier": {
"#type": "PropertyValue",
"name": "Léman Manhattan Preparatory School",
"value": "SG183"
},
"datePosted": "2022-09-12",
"validThrough": "2022-11-11",
"employmentType": "TEMPORARY",
"hiringOrganization": {
"#type": "Organization",
"name": "Léman Manhattan Preparatory School",
"sameAs": "https://www.lemanmanhattan.org/",
"logo" : "https://v5.airtableusercontent.com/v1/7/7/1663804800000/NP8X2ipIaw46UWmRKjo34Q/f6dZOI2Z0GjagfFsHhf7KT28qq7EBvzKwvoSLV7XczwvLpCAjzo3yYYWQSJpeS8fx6jK89TlrnYRuJDBiHOv4g/l1QsKwP2dRMo_vZ_zqRZq8fUwCKJmHXDzgBTXkr5Iao"
},
"jobLocation": {
“#type": "Place",
"address": {
"#type": "PostalAddress",
"streetAddress": "41 Broad St",
"addressLocality": "New York",
"addressRegion": "NY",
"postalCode": "10004",
"addressCountry": "USA"
}
}
}
There is a “typographic” quotation mark instead of a regular "typewriter" mark in jobLocation.#type. With syntax highlighting you can see that something is off starting at that line.
"jobLocation": {
"#type": "Place",
...

Star Rating Rich Snippets Not Showing on Google

I have tried several ways to try to get Rich Snippets Markup showing for my Reviews. I am currently just testing it on one page in order to find out what to do to get it to show on Google.
I have re-indexed my site and no luck.
Google says for the test that it is working correctly, but I cannot get it to show up.
Does anyone have any ideas what I might be doing wrong? I am lost.
https://bitcoincasinolord.com/casino-reviews/bitstarz/
​
<script type="application/ld+json">
{
"#context": "http://schema.org/",
"#type": "Review",
"url": "https://bitcoincasinolord.com/casino-reviews/bitstarz-casino-review/",
"itemReviewed": {
"#type": "Organization",
"name": "Bitstarz Casino"
},
"reviewRating": {
"#type": "Rating",
"ratingValue": "8.9",
"bestRating": "10",
"worstRating": "0"
},
"author": {
"#type": "Organization",
"name": "BitcoinCasinoLord"
}
}
</script>
it is not must to show the everything as rich results. if you page passes rich result test that's good but google decides what to show as rich result. it depends upon many factors.
Reasons Why Your Rich Snippets Aren’t Showing

Schema.org PriceSpecification with a sale price

I'm currently building a Schema.org template for an ecommerce website, for the purposes of generating a Google Shopping Feed.
I'm struggling to understand the correct way to define a sale price - i.e. a product which has a temporary reduced price.
The options I've considered areL
a single "Offer" with multiple "PriceSpecification" items
multiple "Offer" items with a single "PriceSpecification"
or maybe something else completely?
Single "Offer" with multiple "PriceSpecification" items
"offers": {
"#type": "Offer",
"url": "https://kx.com/url",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"PriceSpecification": [
{
"#type": "PriceSpecification",
"price": 15.00,
"priceCurrency": "USD"
},
{
"#type": "PriceSpecification",
"price": 15.00,
"priceCurrency": "USD",
"validFrom": "2020-01-01",
"validThrough": "2020-02-01",
}
],
},
Multiple "Offer" items with a single "PriceSpecification"
"offers": [
{
"#type": "Offer",
"url": "https://kx.com/url",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"PriceSpecification": [
{
"#type": "PriceSpecification",
"price": 15.00,
"priceCurrency": "USD"
}
],
},
{
"#type": "Offer",
"url": "https://kx.com/url",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"PriceSpecification": [
{
"#type": "PriceSpecification",
"price": 15.00,
"priceCurrency": "USD",
"validFrom": "2020-01-01",
"validThrough": "2020-02-01",
}
],
}
]
},
Or is it something completely different? I'm struggling to find any conclusive documentation around this.
I'd note that Google strongly recommends the priceValidUntil value on Offer. I also usually use the rule of thumb that your Structured Data should match what's in your markup, so I think the starting point of the sale is likely unnecessary, especially for a Google shopping feed.
If I were approaching this, I feel the safe route would be updating your Product structured data along with the content on the day of the sale, using the priceValidUntil field to note when that sale ends, then removing the attribute and updating the price once that date hits. You'd end up with something like:
"offers": {
"#type": "Offer",
"url": "https://kx.com/url",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"price": 15.00,
"priceCurrency": "USD",
"priceValidUntil": "2/1/2020"
}
In this example, on 2/1/2020 the priceValidUntil attribute would be removed and the price attribute would update, along with the content on the page.
Your first example does validate in the Structured Data Testing Tool, but I don't think it will do you any good. I can see where you might want to advertise a sale ahead of time, but as far as I know a Google Shopping Feed/Carousel does not announce sales that are going to happen - just prices that are happening.
A final note that while priceSpecification does validate on the testing tool and is applicable to a product, details around it seem a bit vague and I'd be hesitant in expecting it to provide much value. priceSpecification on schema.org has no example of it being used in a product (although again, not to say that means it is wrong).

Can AggregateRating in Schema Be Extended to include a Source or URL Property?

I don't really know if there is a way around it, kindly chip in your suggestions.
I think aggregateRating of an entity is limiting in schema markup. If there is a possibility of extension I believe an attribute such as source or url would be great because we can tell from which source the rating is coming from.
Challenge scenario:
I am marking up a schema for a book, this book has ratings on both goodreads.com and amazon.com. Both ratings are different, however, there is no way to account for the different aggregate ratings since it is not available at the moment. I don't think it is cool to just take an average.
Right now:
"keys": "values",
"aggregateRating": {
"#type": "AggregateRating",
"reviewCount": "25",
"ratingValue": "5"
},
Suggestion:
"keys": "values",
"aggregateRating": [
{
"#type": "AggregateRating",
"reviewCount": "25",
"ratingValue": "5",
"source": "https://amzn.com/product/url/reviews"
},
{
"#type": "AggregateRating",
"reviewCount": "5",
"ratingValue": "4",
"source": "https://gdreads.com/product/url/reviews"
}
],

Structured Data Testing Tools following #id references for JSON-LD – Will this work as expected?

I'm working on marking up a site with schema data using JSON-LD. After doing my homework, I learned that #id could be used to reference other snippets of schema. Such as writing WebPage schema that isPartOf my WebSite schema.
Following this, I created the basic schemas for my website; Organization, WebSite, and WebPage where WebSite links to WebPage and Organization.
When I plug my markup into Google's Structured Data Testing tool, it all gets rolled up into the WebSite schema. However, when I remove the #id references, then it is shown as three different types of schema.
With #id
Without #id
Of course, I want my schema data to be interpreted as a series of relationships, that's the whole point. But I also want to make sure each individual schema is being parsed.
So what do you think, will this be okay?
Organization
{
"#context": "http://schema.org",
"#type": "Organization",
"#id": "https://example.com/#organization",
"name": "Organization",
"legalName": "Organization, Inc",
"description": "We rock",
"logo": "https://www.example.com/images/logo.jpg",
"url": "https://www.example.com",
"telephone": "+1-111-111-1111",
"sameAs": ["https://twitter.com/example", "https://www.linkedin.com/company/example/", "https://plus.google.com/u/0/+example", "https://www.facebook.com/example", "https://www.youtube.com/user/example", "https://www.instagram.com/example/", "https://en.wikipedia.org/wiki/example", "https://www.wikidata.org/wiki/Q1", "https://www.crunchbase.com/organization/example"],
"address":
{
"#type": "PostalAddress",
"streetAddress": "111 Street",
"addressLocality": "Nowhere",
"postalCode": "11111",
"addressCountry": "United States"
}
}
WebSite
{
"#context": "http://schema.org",
"#type": "WebSite",
"#id": "https://example.com/#website",
"name": "Website",
"alternateName": "Web",
"url": "https://www.example.com",
"hasPart":
{
"#type": "WebPage",
"#id": "https://www.example.com/#webpage"
}
}
WebPage
{
"#context": "http://schema.org",
"#type": "WebPage",
"#id": "https://www.example.com/#webpage",
"name": "Webpage",
"description": "Told you, we rock",
"url": "https://www.example.com/",
"isPartOf":
{
"#id": "https://www.example.com/#website"
},
"potentialAction":
{
"#type": "SubscribeAction",
"agent":
{
"#type": "Organization",
"#id": "https://example.com/#organization"
},
"object":
{
"#type": "Product",
"name": "Mailing List"
}
}
}
Of course, I want my schema data to be interpreted as a series of relationships, that's the whole point.
Exactly. Making use of #id references is one way to achieve this, nesting the full items is the other way. The result will be the same, i.e., they are equivalent.
But I also want to make sure each individual schema is being parsed.
If you know a consumer that only recognizes top-level items, you might want to adapt. It’s often possible to have one item of your choice on the top-level (by making use #reverse or inverse properties, if existing), but tools like Google’s SDTT might of course display the parsed result in a different way.
But unless you know such a consumer, I don’t think it would be advisable to omit using properties with item values. You would miss out on the most important semantic signal: relations.
In theory, providing the mainEntity/mainEntityOfPage property should be sufficient for page-oriented consumers to learn what the primary entity on that page is. In practice, consumers might not recognize/support this property, of course. But I don’t see how it should be easier for consumers to handle several top-level items, where it’s unclear in which relation they stand to each other (because the relations aren’t specified), so consumers should have an interest to support the common way how Schema.org structured data is provided on the Web.