Fix SDTT warning on JobPosting: "The value field is recommended." - schema.org

On the Google Structured Data Testing Tool I get a warning for not entering a value in the baseSalary property.
The value field is recommended. Please provide a value if available.
However, I have added a value.
{
"#context": "http://schema.org",
"#type": "JobPosting",
"hiringOrganization": "Google",
"validThrough": "2018-12-31T00:00",
"baseSalary": {
"#type": "MonetaryAmount",
"currency": "USD",
"value": {
"#type": "QuantitativeValue",
"minValue": 40.00,
"maxValue": 50.00,
"unitText": "HOUR"
}
},
"jobBenefits": "Medical, Life, Dental",
"datePosted": "2011-10-31",
"description": "Description: ABC Company Inc. seeks a full-time mid-level software engineer to develop in-house tools.",
"educationRequirements": "Bachelor's Degree in Computer Science, Information Systems or related fields of study.",
"employmentType": "Full-time",
"experienceRequirements": "Minumum 3 years experience as a software engineer",
"incentiveCompensation": "Performance-based annual bonus plan, project-completion bonuses",
"industry": "Computer Software",
"jobLocation": {
"#type": "Place",
"address": {
"#type": "PostalAddress",
"addressLocality": "Poole",
"addressRegion": "Dorset",
"streetAddress": "33 Holton Road",
"postalCode": "BH16 6LT"
}
},
"occupationalCategory": "15-1132.00 Software Developers, Application",
"qualifications": "Ability to work in a team environment with members of varying skill levels. Highly motivated. Learns quickly.",
"responsibilities": "Design and write specifications for tools for in-house customers Build tools according to specifications",
"salaryCurrency": "USD",
"skills": "Web application development using Java/J2EE Web application development using Python or familiarity with dynamic programming languages",
"specialCommitments": "VeteranCommit",
"title": "Software Engineer",
"workHours": "40 hours per week"
}
Could someone please provide a fix so the code passes the Google Structured Data Testing Tool?

Your code violates the standard:
baseSalary doesn't contain something like hours, but only currency and the value or range.
Beside of this there is a inconsistency:
you write on one place:
"minValue": 40.00,
"maxValue": 50.00,
"unitText": "HOUR"
On another place:
"workHours": "40 hours per week"
What now? 40 hours or between 40 and 50?
Another thing: workHours are not for amount of working hours per week, but for typical beginning and ending of shift.

Related

How to markup (using JSON-LD) a Service to show price within a LocalBusiness in 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>

Confused about how #id in structured data works

Basically, I'm trying to add BlogPosting, TechArticle and WebPage structured data types to my posts, but I'm getting errors in Google's structured data testing tool. They seem to be centred around when I link back to an Organization structured data type I've defined on my homepage, to save me having to repeat the same code across multiple pages.
Here's the structured data testing tool instance. Can anybody explain how I can properly link to the Organization data type (which is sitting on my homepage) in the author, creator and publisher properties?
https://search.google.com/structured-data/testing-tool#url=https%3A%2F%2Fwww.lukeharrison.dev%2Farticles%2Fmike-brewer-motors-wins-best-online-experience-at-autotraders-2018-retailer-awards%2F
I feel as though it may be down to me not fully understanding the #id property, and how to properly can use it to link structured data together to reduce repetitive data.
Here's the code involved:
The BlogPosting
The linked Organisation
The errors I'm receiving
Example of BlogPosting
{
"#context": "http://schema.org",
"#type": "BlogPosting",
"about": "Great news! Mike Brewer Motors - a project I've been heavily involved in over the past few years - has won the 'Best Online Experience' at the Autotrader 2018 Retailer Awards.",
"articleSection": "Blog Posts",
"author": {
"id": "https://www.lukeharrison.dev#organization"
},
"copyrightHolder": {
"id": "https://www.lukeharrison.dev#person"
},
"copyrightYear": "2019",
"creator": {
"id": "https://www.lukeharrison.dev#organization"
},
"dateCreated": "2018-07-20",
"dateModified": "2018-07-20",
"datePublished": "2018-07-20",
"description": "Great news! Mike Brewer Motors - a project I've been heavily involved in over the past few years - has won the 'Best Online Experience' at the Autotrader 2018 Retailer Awards.",
"genre": "Web Design & Front-End Development",
"headline": "Mike Brewer Motors wins 'Best Online Experience' at Autotrader's 2018 Retailer Awards - Luke Harrison",
"image": {
"#type": "ImageObject",
"height": 512,
"url": "https://s.gravatar.com/avatar/c34b34964896ad0552a5b342ae08c1e2?s=512",
"width": 512
},
"inLanguage": "en-GB",
"isFamilyFriendly": "true",
"keywords": [
"news"
],
"mainEntityOfPage": "https://www.lukeharrison.dev/articles/mike-brewer-motors-wins-best-online-experience-at-autotraders-2018-retailer-awards",
"publisher": {
"id": "https://www.lukeharrison.dev#organization"
}
}
Example linked Organization, which sits on another page
{
"#context": "http://schema.org",
"#id": "https://www.lukeharrison.dev#organization",
"#type": "Organization",
"additionalType": [
"http://www.productontology.org/id/Web_design",
"http://www.productontology.org/doc/Search_engine_optimization",
"http://www.productontology.org/doc/Web_development"
],
"foundingDate": "2013",
"legalName": "Luke Harrison - UX / Web Developer",
"logo": "https://www.lukeharrison.dev/img/share-26bfb69f23.png",
"name": "Luke Harrison - UX / Web Developer",
"sameAs": [
"https://twitter.com/webdevluke?lang=en-gb",
"https://www.linkedin.com/in/lukedidit/",
"https://github.com/WebDevLuke",
"https://codepen.io/lukedidit/"
],
"url": "https://www.lukeharrison.dev"
}
The errors I'm receiving in my BlogPosting structure
author, creator and publisher:
The attribute publisher.itemtype has an invalid value.
A value for the name field is required.
The errors are about Google’s Article rich result (if you don’t want to get this rich result, you can ignore these errors).
For AMP pages, author and publisher are required properties. They require actual items as value, #id references are not supported. You can still provide the #id, but you need to specify the #type and the required properties in addition.

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.

Is the Event type suitable for running races?

I have inline Schema.org code via itemprop attributes, on all event pages on a website.
Search Console is flagging up recommendations that I use performer and various other properties, however due to the nature of the events (they are races), there are no performers.
Does this imply that event is the wrong type of Schema.org here, or can the warnings be safely ignored?
The tags used are:
type
image
name
location
type
address
type
streetaddress
addresslocality
address country
type
name
aggregaterating
type
reviewcount
ratingvalue
The Event type is perfectly suitable for races. But you should use the more specific SportsEvent.
Schema.org never requires any property, but consumers (who offer features based on Schema.org structured data) have their own requirements. If you want to get the feature, you would have to comply; if you don’t want the feature (or you can’t get it because you can’t provide all the required data), you can simply ignore any kind of errors/warnings from this consumer.
The consumer Google Search offers the event rich result feature, which has required and recommended properties. The performer property is just recommended, so it should be possible to get the event rich result without providing a performer.
Note that the guide of Google for Event requires the use of the following property that are not in the markup scheme you specified: startDate.
There are also many recommended properties out there that you are missing and these lower the value of the rich results of Google in the SERP:
description
endDate
location.name
offers
Note that the property executor can have the embedded type PerformingGroup, e.g.:
"performer": {
"#type": "PerformingGroup",
"name": "McLaren"
}
This way you can create markup for the team but not for each rider.
More detailed markup with structured data enriches the SERP of your web pages.
Beeing a webdeveloper and racedirector, I have been looking into this for some time now. If you take a look at the races website (no, this is no advertising for the best race on the planet), you can see that I have an event (SportsEvent) and six different competitions on that very day: 100km ultramarathon
What you see here is what I assembled so far to make my race as machine readable as possible. I have the adress, the different competitions, the place, the entry fees and the offers, the dooring time and all the stuff I might need google to know.
The only thing that is missing is the list of the competitors, the runners of each race. I am doing research about how to do this right now, but "sports" in microformats seems to be a team based thing. If I found out how to do it right, I'll post an update here. And you'll see it in the websites source code of course.
I have copied the LD-JSON here for future reference in case I'd edit the code of the website.
FYI: I am getting the participants data as XML feed directly from the raceresult registration website.
<script type='application/ld+json'>
{
"#context": "http://schema.org",
"#type": "SportsEvent",
"#id": "https://whew100.de/wettbewerbe/whew100.html",
"name": "WHEW100 Ultramarathon",
"image": "https://whew100.de/assets/images/WHEW100_transparent.png",
"url": "https://whew100.de/wettbewerbe/whew100.html",
"description": "WHEW100 Ultramarathon in Wuppertal über Wülfrath, Velbert, Heiligenhaus, Essen, Hattingen und Sprockhövel. Auf alten Bahntrassen zwischen Wuppert und Ruhr.",
"startDate": "2019-05-04T07:00:00",
"endDate": "2019-05-04T22:00:00",
"doorTime": "2019-05-04T06:00:00",
"maximumAttendeeCapacity": "200",
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": "4.9",
"reviewCount": "84"
},
"location": {
"#type": "Place",
"name": "Utopiastadt",
"sameAs": "https://www.clownfisch.eu/utopia-stadt/bahnhof-mirke/",
"address": {
"#type": "PostalAddress",
"streetAddress": "Mirker Straße 48",
"addressLocality": "Wuppertal",
"postalCode": "42105",
"addressCountry": "Germany"
}
},
"competitor": [
],
"offers": {
"#type": "Offer",
"description": "Anmeldung zum WHEW100",
"url": "http://my.raceresult.com/105067/",
"price": "75",
"priceCurrency": "EUR",
"availability": "200",
"validFrom": "2018-09-01T00:00:00"
},
"superEvent": {
"#id": "https://whew100.de",
"name": "WHEW100",
"startDate": "2019-05-04T07:00:00",
"endDate": "2019-05-04T22:00:00",
"location": {
"#type": "Place",
"name": "Utopiastadt",
"sameAs": "https://www.clownfisch.eu/utopia-stadt/bahnhof-mirke/",
"address": {
"#type": "PostalAddress",
"streetAddress": "Mirker Straße 48",
"addressLocality": "Wuppertal",
"postalCode": "42105",
"addressCountry": "Germany"
}
}
}
}
</script>

Adding a 'license' field to a schema.org Place record

I have a database of locations that I would like to publish as Open Data. each record can have one of several licenses depending on where the data was sourced from so each record needs to have a license attached. I'm publishing the data as json-ld. Sample record:
{
"#context": "http://schema.org",
"#type": "Place",
"name": "METROPOLITAN MUSEUM OF ART",
"address": {
"#type": "PostalAddress",
"streetAddress": "1000 5TH AVE",
"addressLocality": "NEW YORK",
"addressRegion": "NY",
"addressCountry": "United States",
"postalCode": "10028-0198"
},
"hasMap": "http://www.openstreetmap.org/?mlat=40.7784&mlon=-73.9627#map=15/40.7784/-73.9627",
"geo": {
"#type": "GeoCoordinates",
"latitude": 40.7784,
"longitude": -73.9627
},
"description": null,
"telephone": "+1 (212) 472-2764",
"url": "http://www.metmuseum.org",
"openingHours": null,
"photo": {
"#type": "ImageObject",
"contentUrl": "http://127.0.0.1:8888/fSunhLAJFSmnx55GNJee2-YKcgE=/1000x1000/museums/logos/000/149/449/original/NYC_-_Metropolitan_-_Temple_of_Dendur.JPG",
"creator": "Jean-Christophe BENOIST",
"license": "CC BY 3.0"
}
}
The schema.org Place model doesn't have a field for 'license'. What is the correct way to add a license type field to the record? Essentially I want to embed a CreativeWork field in there if possible.
It seems that you want to provide a license for the document that is about the Place, not for the Place itself.
So go with CreativeWork (or one of its sub-types, like WebPage if the document is a web page) and make use of its license property.
To state that this CreativeWork is about the Place, you could use the about property, and to state that the Place is the primary entity described in this document, you could use the mainEntity property.
If you want to keep Place as the top-level node, you could use JSON-LD’s #reverse for the about property, and use mainEntity’s inverse property, mainEntityOfPage.
Using http://schema.org/Dataset (which is a type of CreativeWork) will allow you to set a license. Place is a field within Dataset so they fit together. The license for your ImageObject should also be the URL of the license not the text (which I found out after having issues with it).
Dataset includes datasetTimeinterval, distribution, includedDataCatalog and spatial (a Place). Dataset was only introduced in May