Structured data is machine-readable markup, usually schema.org vocabulary written as JSON-LD, that tells search engines what a page is about. Google uses it to understand content and to make a page eligible for rich results such as recipe cards and product details. Schema.org was founded by Google, Microsoft, Yahoo and Yandex, and JSON-LD 1.1 became a W3C Recommendation on 16 July 2020.
You pick a type from the schema.org vocabulary, such as Recipe, Product or Event, and describe the page with that type's properties. The markup sits in the page next to the visible content and must describe that same content.
Google Search reads three formats, and it says all three are equally fine if the markup is valid:
application/ld+json, allowed in the head or the body. Google recommends it because the markup is not interleaved with visible text. Google can also read JSON-LD that JavaScript injects after load.itemscope and itemprop on the elements that already hold the content.In JSON-LD, @context names the vocabulary (https://schema.org) and @type names the type. Everything else is an ordinary JSON property, and nested objects carry their own @type.
Each Google feature lists required and recommended properties. Missing a required property makes the item ineligible for that rich result. Google says a few complete, accurate recommended properties beat many sloppy ones.
import json
from html.parser import HTMLParser
page = """<script type="application/ld+json">
{"@context": "https://schema.org", "@type": "Recipe", "name": "Pancakes",
"author": {"@type": "Person", "name": "Ada Lee"},
"recipeIngredient": ["200 g flour", "2 eggs", "300 ml milk"]}
</script>"""
class LD(HTMLParser):
def __init__(self):
super().__init__()
self.on, self.blocks = False, []
def handle_starttag(self, tag, attrs):
self.on = tag == "script" and ("type", "application/ld+json") in attrs
def handle_endtag(self, tag):
self.on = False
def handle_data(self, data):
if self.on:
self.blocks.append(json.loads(data))
p = LD()
p.feed(page)
b = p.blocks[0]
print(b["@type"], "|", b["name"], "|", b["author"]["name"], "|", len(b["recipeIngredient"]), "ingredients")
# Recipe | Pancakes | Ada Lee | 3 ingredients
Google presents structured data as a way to understand content and become eligible for rich results, not as a ranking switch. Its guidelines say a structured data manual action removes rich result eligibility but does not affect how the page ranks. Valid markup does not guarantee a rich result, because Google also applies quality guidelines. Use the Rich Results Test while building a page and the rich result status reports in Search Console after deployment.
Expecting property name enclosed in double quotes: line 1 column 40 (char 39) for {"@type": "Recipe", "name": "Pancakes",}. Validate the JSON before shipping.