How to markup (using JSON-LD) a Service to show price within a LocalBusiness in Schema.org? - schema.org

When I test this code in validator, I am getting WARNING for the property price and the property priceCurrency. How do I fix this?
Thank you.
The property price is not recognized by the schema (e.g. schema.org) for an object of type Service.
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#type": "LocalBusiness",
"name" : "Charlotte Property Management",
"hasOfferCatalog": {
"#type": "OfferCatalog",
"name": "Charlotte Property Management Plans",
"itemListElement": [
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Silver Plan",
"description": " Our Silver Plan is developed for early-stage investors seeking to learn the intricacies of investment property management but with an added protection layer of professional oversight by our experienced team. This plan is perfect for DIY investment enthusiasts.",
"price": "49",
"priceCurrency": "USD"
}
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Gold Plan",
"description": "The Gold Plan is designed for investors who value their time, treating their investment property as a business. If you are looking to delegate all aspects of property management and maintenance to our experienced team, while you focus on what matters in your life, this program is for you. Our Investment property acquisition, sale, and consulting services are included in this program.",
"price": "99",
"priceCurrency": "USD"
}
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Platinum Plan",
"description": "The Platinum Plan is designed for the avid investor who is actively looking to build wealth by growing their Real Estate investment portfolio. The program includes full professional management services backed by our Uninterrupted Rent and Eviction Guarantees. Our Investment property acquisition, sale, and consulting services are included in this program.",
"price": "249",
"priceCurrency": "USD"
}
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Guaranteed Income Plan",
"description": "On the other hand, our Guaranteed Income Plan is a non-property management plan designed to free up your schedule, avoid rental income fluctuations, and make your rental property a continuously profitable investment.",
"price": "Custom",
"priceCurrency": "USD"
}
}
]
}
}
</script>

In the markup, properties price and priceCurrency are located/belong to the Service object/type, which does not contain such properties. Those properties belong to the Offer, so they should be moved accordingly.
So just move them one level up, outside of the Service, so that they belong to the Offer object/type:
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#type": "LocalBusiness",
"name" : "Charlotte Property Management",
"hasOfferCatalog": {
"#type": "OfferCatalog",
"name": "Charlotte Property Management Plans",
"itemListElement": [
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Silver Plan",
"description": " Our Silver Plan is developed for early-stage investors seeking to learn the intricacies of investment property management but with an added protection layer of professional oversight by our experienced team. This plan is perfect for DIY investment enthusiasts."
},
"price": "49",
"priceCurrency": "USD"
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Gold Plan",
"description": "The Gold Plan is designed for investors who value their time, treating their investment property as a business. If you are looking to delegate all aspects of property management and maintenance to our experienced team, while you focus on what matters in your life, this program is for you. Our Investment property acquisition, sale, and consulting services are included in this program."
},
"price": "99",
"priceCurrency": "USD"
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Platinum Plan",
"description": "The Platinum Plan is designed for the avid investor who is actively looking to build wealth by growing their Real Estate investment portfolio. The program includes full professional management services backed by our Uninterrupted Rent and Eviction Guarantees. Our Investment property acquisition, sale, and consulting services are included in this program."
},
"price": "249",
"priceCurrency": "USD"
},
{
"#type": "Offer",
"itemOffered": {
"#type": "Service",
"name": "Guaranteed Income Plan",
"description": "On the other hand, our Guaranteed Income Plan is a non-property management plan designed to free up your schedule, avoid rental income fluctuations, and make your rental property a continuously profitable investment."
},
"price": "Custom",
"priceCurrency": "USD"
}
]
}
}
</script>

Related

How should I represent "global" events / observances / occasions in Schema.org?

I administer an educational site that includes a calendar of global events, but these are not "Events" in the sense that Schema.org's Event type considers them – they don't have a location, and they are observed across a wide area (e.g. a country, an continent, or worldwide). They are more like global anniversaries, occasions or observances. Examples include Earth Day, Chinese New Year, World Book Day, International Women's Day and so on.
In our initial attempt at introducing microdata for these calendar pages, I have used the Event type, but I'm aware that as many – or most – of these events don't have a definable location (in the sense that Schema.org represents a location), and are not "attended" in a physical or digital sense, they cannot be valid.
Is there a more appropriate type in the Schema.org vocabulary that I should use in this case? Is it inappropriate to try to represent them in Schema.org microdata at all?
Maybe Google's guide for an online event can help you, including an example:
<html>
<head>
<title>The Adventures of Kira and Morrison</title>
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#type": "Event",
"name": "The Adventures of Kira and Morrison",
"startDate": "2025-07-21T19:00:00-05:00",
"endDate": "2025-07-21T23:00-05:00",
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode",
"location": {
"#type": "VirtualLocation",
"url": "https://operaonline.stream5.com/"
},
"image": [
"https://example.com/photos/1x1/photo.jpg",
"https://example.com/photos/4x3/photo.jpg",
"https://example.com/photos/16x9/photo.jpg"
],
"description": "The Adventures of Kira and Morrison is coming to Snickertown in a can't miss performance.",
"offers": {
"#type": "Offer",
"url": "https://www.example.com/event_offer/12345_201803180430",
"price": "30",
"priceCurrency": "USD",
"availability": "https://schema.org/InStock",
"validFrom": "2024-05-21T12:00"
},
"performer": {
"#type": "PerformingGroup",
"name": "Kira and Morrison"
},
"organizer": {
"#type": "Organization",
"name": "Kira and Morrison Music",
"url": "https://kiraandmorrisonmusic.com"
}
}
</script>
</head>
<body>
</body>
</html>
In addition, Schema has the beta version of the type VirtualLocation.

Structured data (schema.org) for Price lists / service lists

I'm building a website for a local beauty salon. They offer services such as massages and various beauty treatments. It's all visible on 1 overview page (price list)
I found out https://schema.org/Product can be used for services:
Any offered product or service. For example: a pair of shoes; a concert ticket; the rental of a car; a haircut
Fist question, can I ignore fields like availability and condition?
Second, should I list this products as ItemOffered inside Offer? Or is this not the correct way?
Example:
{
"#context": "http://schema.org",
"#type": "WebPageElement",
"offers": {
"#type": "Offer",
"itemOffered": [
{
"#type": "Product",
"#id": "/beauty-treatment-a",
"description": "Short description with details",
"name": "Beauty Treatment A",
"offers": {
"#type": "Offer",
"price": "18.28",
"priceCurrency": "EUR",
"description": "Same description",
"name": "Same name",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "image-a.jpg",
"description": "Same name",
"width": 640,
"height": 640
}
}
},
{
"#type": "Product",
"#id": "/beauty-treatment-b",
"description": "Short description with details",
"name": "Beauty Treatment B",
"offers": {
"#type": "Offer",
"price": "18.28",
"priceCurrency": "EUR",
"description": "Same description",
"name": "Same name",
"image": {
"#context": "http://schema.org",
"#type": "ImageObject",
"contentUrl": "image-b.jpg",
"description": "Same name",
"width": 640,
"height": 640
}
}
]
}
}
Fist question, can I ignore fields like availability and condition?
Schema.org never requires a property. A consumer, like Google, might require properties for one of their features.
For Google’s Product feature,
availability is recommended for the rich result in Google Search, and required for the "Related Items" in Google Images, and
itemCondition is neither recommended nor required.
However, their feature is only for pages about a single product. So your page is not eligible for Google’s Product rich result.
Second, should I list this products as ItemOffered inside Offer? Or is this not the correct way?
You can either have Product as top-level item (with offers Offer), or Offer as top-level item (with itemOffered Product).
About your example:
There is no need to use WebPageElement; it’s typically not relevant information that a certain HTML element on a page contains an offer, it’s only relevant that there is an offer.
You have one offer that consists of two products, and two offers that consist of one product each (the same like in the first offer). You probably don’t want to have the first offer (unless there really is an offer that combines the two products).
I would recommend the following:
Use OfferCatalog for the list of offers.
Each list item is an Offer.
Each Offer points to its Product/Service with itemOffered.

How to define a ticket of ten in Schema.org "PriceSpecification"?

I try to get our pricing into the PriceSpecification scheme from Schema.org.
For our time based tickets this is pretty straight forward, like for our 3-month ticket:
"priceSpecification": {
"#type": "UnitPriceSpecification",
"priceCurrency": "USD",
"price": "10",
"referenceQuantity": {
"#type": "QuantitativeValue",
"value": "3",
"unitCode": "MON"
}
},
But we also have a "ticket of 10", which I try to describe, if possible with a unitCode and not a unitText.
Is there any UNECE/CEFACT code for this to describe or do I have to use unitText as fallback?

Connecting multiple organizations and websites via JSON-LD schema.org

I'm trying to accomplish machine-understandable relationship descriptions for companies/subsidiaries and their websites. Let's suppose there is one parent company with two subsidiaries, all of which have their own websites. I deploy one Organization script, and one WebSite script per home page.
The parent organization's JSON-LD reads:
<script type="application/ld+json">
{
"#context": "http://www.schema.org",
"#type": "Organization",
"#id": "https://www.parentorg.com/#organization",
"name": "Parent Org",
"legalName": "Parent Org Inc.",
"description": "Description of company",
"foundingDate": "1978",
"logo": "https://www.parentorg.com/images/logo.png",
"image": "https://www.parentorg.com/de/images/outside.jpg",
"url": "https://www.parentorg.com/",
"address": {
"#type": "PostalAddress",
"streetAddress": "Street 110",
"addressLocality": "City",
"postalCode": "XX XXX",
"addressCountry": "XX"
},
"contactPoint": {
"#type": "ContactPoint",
"contactType": "customer support",
"telephone": "+12-345-678-91011",
"email": "contact#parentorg.com"
},
"sameAs": [
"https://twitter.com/parentorg/",
"https://www.instagram.com/parentorg/",
"https://www.youtube.com/user/parentorg/",
"https://plus.google.com/parentorg"
],
"subOrganization": [
{
"#type": "Organization",
"#id": "https://www.subsidiary-one.de/#organization",
"name": "Subsidiary One"
},
{
"#type": "Organization",
"#id": "https://www.subsidiary-two.de/#organization",
"name": "Subsidiary Two"
}
]
}
</script>
The parent's website JSON-LD is:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "WebSite",
"#id": "https://www.parentorg.com/#website",
"url": "https://www.parentorg.com/",
"author": {
"#type": "Organization",
"#id": "https://www.parentorg.com/#organization",
"name": "Parent Org"
}
}
</script>
And now the subsidiaries' organization JSON-LD contain a parentOrganization property:
"parentOrganization": {
"#type": "Organization",
"#id": "https://www.parentorg.com/#organization",
"name": "Parent Org"
}
Would this be a good way to cross-reference those entities? And do I even need to write out the name properties inside subOrganization, parentOrganization, and author, when there are URIs referenced?
Yes, you follow the best practice how to cross-reference entities (by giving each entity an #id that is different from the url).
You don’t have to provide additional properties when referencing entities, so this is fine:
"author": {"#id": "https://www.parentorg.com/#organization"}
"subOrganization": [
{"#id": "https://www.subsidiary-one.de/#organization"},
{"#id": "https://www.subsidiary-two.de/#organization"}
]
"parentOrganization": {"#id": "https://www.parentorg.com/#organization"}
However, this of course requires that consumers fetch the referenced documents. But not all do (probably). So if you want to provide data for those consumers, too, you could add properties in addition to the #id. It could be just one, a few, or even all properties. I think the two from your example are the most important ones:
Providing #type can also be useful for consumers that are capable of fetching documents, as it may allow them to decide whether the referenced resource is of interest to them before fetching it. For example, a consumer might only care about works authored by an Organization, not by a Person.
Providing the name property can be useful for consumers that display the included structured data in some way that benefits from a name/label.

Errors in Google SDTT for Schema.org Product, Offer, and PriceSpecification

I'm new with Schema.org markup, so I've actually come up with the following codes for my real estate markup, and Google testing keep saying I shouldn't use offer for priceSpecification. I'm so lost now.
{
"#context": "http://schema.org/",
"#type": "Product",
"name": "Nodorus - Precinct 17",
"image": "http://www.setiaalam.com.my/images/products/p17/nodorus-c.jpg",
"description": "A distinct modern link residence set amidst award-winning green spans, wetland wonders and multiple amenities. Come home to articulately crafted spaces where architecture and nature's beauty infuse home with fresh chic. Rejoice in this cosy new addition to Setia Alam North.",
"additionalType": "Product",
"Offer": {
"#type": "PriceSpecification",
"priceCurrency": "RM",
"priceSpecification": {
"minPrice": "593000",
"maxPrice": "890000"
},
"availability": "http://schema.org/InStock",
"seller": {
"#type": "Organization",
"name": "S P Setia"
}
}
}
If you want to add an Offer for a Product, you have to use the offers property.
So instead of this (which doesn’t make sense, because Offer is not a property):
{
"#context": "http://schema.org/",
"#type": "Product",
"Offer": {}
}
You have to use this:
{
"#context": "http://schema.org/",
"#type": "Product",
"offers": {}
}
The type of the offers value should be Offer, not PriceSpecification.
The PriceSpecification can be added to the Offer via the priceSpecification property.
So the structure could look like:
{
"#context": "http://schema.org/",
"#type": "Product",
"offers": {
"#type": "Offer",
"priceSpecification": {
"#type": "PriceSpecification"
}
}
}