A Guide to JSON-LD and Schema.org
1. What JSON-LD and Schema.org are
JSON-LD is a format for embedding structured metadata in a web page. Schema.org is the vocabulary you encode in that format. The two are almost always used together, but they’re separate things: JSON-LD answers “how do I write metadata in HTML,” and Schema.org answers “what nouns and properties am I writing about.” Either could exist without the other. In practice, the combination dominates; when someone says “we have JSON-LD on the site,” they almost always mean “JSON-LD encoding of Schema.org types.”
JSON-LD (JSON for Linked Data) was published as a W3C Recommendation in 2014. It’s JSON that conforms to RDF (Resource Description Framework) semantics: each property has a globally-defined meaning, identifiers are URLs, and entities can reference each other across documents. That cross-document referencing is what distinguishes JSON-LD from plain JSON metadata.
Schema.org launched in 2011 as a joint project between Google, Microsoft, and Yahoo, with Yandex joining later that year. It defines a vocabulary of types (Person, Article, BlogPosting, Recipe, Product, Event, hundreds more), each with a defined property set. The “joint project” detail matters because it shapes what does and doesn’t get added to Schema.org: types that serve search-engine use cases get added; types that don’t, don’t.
JSON-LD is one of three encodings Schema.org supports (alongside Microdata and RDFa-in-HTML, covered briefly in section 3). The other two are slowly fading; JSON-LD has won most new implementations and is what Google’s rich-result documentation explicitly recommends.
Open Graph is the sibling standard, covered in its own post: OG handles “what does this URL look like when shared,” JSON-LD and Schema.org handle “what does this page mean and what entities are on it.” Both live in <head>, both get consumed by automated readers, but the consumers and the data shapes are different.
2. The shape of a JSON-LD block
A JSON-LD block is a single <script> tag in <head> containing a JSON object that describes the page (and the entities on it) in Schema.org terms. Three special keys do most of the work: @context declares the vocabulary, @type declares what kind of thing the entity is, and @id gives the entity a stable URL identifier.
Here’s a minimal block describing this post as a BlogPosting:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"@id": "https://example.com/posts/json-ld-and-schema-org#article",
"headline": "A guide to JSON-LD and Schema.org",
"datePublished": "2026-05-08",
"author": {
"@type": "Person",
"@id": "https://example.com/about#emre",
"name": "Emre Bener",
"url": "https://example.com/about"
}
}
</script>A few details worth naming.
2.1. The script-tag envelope
The block lives inside <script type="application/ld+json">…</script>. The type attribute tells the browser this is data, not executable JavaScript, so the browser parses it as plain text and ignores it for execution. Crawlers, however, look for exactly this MIME type and parse the contents as JSON.
A page can contain multiple JSON-LD blocks and crawlers concatenate them. In practice, one block per page is cleaner, with multiple entities expressed via nesting or via the @graph array (covered in section 2.5).
2.2. @context
@context declares the vocabulary the keys come from. For Schema.org, it’s almost always the literal string "https://schema.org":
"@context": "https://schema.org"That tells parsers that every key in this object (headline, datePublished, author, etc.) is defined in the Schema.org vocabulary at https://schema.org/{KeyName}. Without @context, a key like author has no globally-defined meaning; with it, author resolves to https://schema.org/author and any parser that knows Schema.org understands the property.
2.3. @type
@type declares what kind of thing the entity is. The value is a Schema.org type name:
"@type": "BlogPosting"The full type list lives at schema.org/docs/full.html. Section 4 covers the handful of types most pages actually need.
A type can also be an array, expressing that an entity belongs to multiple types simultaneously:
"@type": ["Article", "BlogPosting"]This is occasionally useful when a stricter consumer (say, Google’s rich-result parser) recognizes only one of the two but you want the metadata accurate for others.
2.4. @id
@id gives the entity a stable URL identifier. This is the field that makes JSON-LD “Linked Data”: once an entity has an @id, anything else (in this document or any other) can reference it by URL.
"@id": "https://example.com/about#emre"The URL doesn’t need to be dereferenceable as a separate page; the convention is to use a URL fragment on a page that does exist (#emre on /about). This way the URL points at “the part of the about page that describes this person” and is unique across the site.
@id matters most for Person and Organization entities that get referenced from multiple pages (every blog post’s author should reference the same Person @id, not redeclare a new Person each time). For one-off entities like the article itself, @id is a useful convention even without external referencers: validators anchor errors to it, and future cross-references resolve cleanly.
2.5. Nesting and references
Entities can be either nested inline or referenced by @id. Nested:
"author": {
"@type": "Person",
"name": "Emre Bener"
}Or referenced by @id:
"author": {
"@id": "https://example.com/about#emre"
}The second form assumes the actual Person entity is declared elsewhere (typically on /about). When a crawler resolves the reference, it pulls in the full entity from the other location. This is the “linked” part of Linked Data doing its work.
For a mixed payload (multiple top-level entities on one page), JSON-LD provides @graph:
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "BlogPosting", "@id": "https://example.com/post#article" },
{ "@type": "BreadcrumbList", "@id": "https://example.com/post#breadcrumbs" },
{ "@type": "Person", "@id": "https://example.com/about#emre" }
]
}@graph expresses “here are several distinct entities, all sharing the same context.” Most pages are simpler and don’t need it; pages that emit Article + BreadcrumbList + Author together do.
3. Microdata, RDFa, and why JSON-LD won
Schema.org supports three encodings: JSON-LD, Microdata, and RDFa-in-HTML. The vocabulary is the same in all three; only the syntax differs. Microdata and RDFa weave the metadata into the page’s existing HTML elements as attributes, while JSON-LD ships it as a separate block in <head>. JSON-LD won.
The same BlogPosting author, in Microdata vs JSON-LD:
Microdata:
<article itemscope itemtype="https://schema.org/BlogPosting">
<h1 itemprop="headline">A guide to JSON-LD and Schema.org</h1>
<span itemprop="author" itemscope itemtype="https://schema.org/Person">
<span itemprop="name">Emre Bener</span>
</span>
</article>JSON-LD:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "A guide to JSON-LD and Schema.org",
"author": {
"@type": "Person",
"name": "Emre Bener"
}
}
</script>RDFa looks similar to Microdata but uses vocab=, typeof=, and property= attributes drawn from the W3C’s RDFa-Lite spec. The differences are syntactic; the encoding shape is the same.
The differences shape why JSON-LD won:
- Decoupling from layout. Microdata and RDFa attach metadata to specific DOM elements. If a designer rearranges the page, the metadata breaks unless the attributes follow. JSON-LD lives in
<head>, untouched by layout changes. - Server-side generation. Emitting one JSON object from a server template is much simpler than threading attributes through every relevant element. Most static-site generators and CMS plugins emit JSON-LD by default for this reason.
- Google’s recommendation. Google’s structured-data documentation explicitly prefers JSON-LD. When the largest consumer of structured data has a preference, the ecosystem follows.
- Single block, easy review. A reviewer or validator looking at the metadata sees one
<script>tag, not attributes sprinkled across the page’s body.
Microdata is still around; many older sites and a handful of CMS templates emit it. RDFa is rarer outside academic publishing. Both still work and Google still parses them, but there’s no reason to start a new project on either. The rest of this post assumes JSON-LD as the encoding.
4. The Schema.org types most pages need
Six or seven Schema.org types cover the vast majority of real-world structured data: Article / BlogPosting, Person, WebSite, BreadcrumbList, ProfilePage, and CollectionPage. The vocabulary defines hundreds more, but the rest are useful only if your site is actually about restaurants, recipes, jobs, or products. The documentation can make it feel like every page needs careful per-domain modeling; in practice, it doesn’t.
4.1. Article and BlogPosting
Article represents a long-form text document: news, opinion, blog posts, essays. BlogPosting is a subtype of Article specifically for blog posts. The relationship matters because Google’s rich-result documentation references both, but most consumers treat them interchangeably.
When to pick which:
- News article on a publication site:
NewsArticle(anotherArticlesubtype, surfaces differently in Google News). - Blog post on a personal or company blog:
BlogPosting, falling back toArticleif you want the broader type. - Documentation page or essay:
Articleis the safer pick.
A common pattern is to type as both via the array form, which keeps the metadata accurate for stricter parsers while staying compatible with consumers that only know Article:
{
"@context": "https://schema.org",
"@type": ["Article", "BlogPosting"],
"headline": "A guide to JSON-LD and Schema.org",
"image": "https://example.com/og/json-ld.png",
"datePublished": "2026-05-08",
"author": { "@id": "https://example.com/about#emre" }
}The required-ish fields for rich-result eligibility (covered in section 5) are headline, image, datePublished, and author. Google’s documentation calls these “required” but a rich result will sometimes still render with just headline.
4.2. Person
Person represents a human. The most common use is the author of an Article or BlogPosting. It’s also used to type an “about me” page’s main entity.
A typical author Person:
{
"@type": "Person",
"@id": "https://example.com/about#emre",
"name": "Emre Bener",
"url": "https://example.com/about",
"sameAs": [
"https://github.com/emrebener",
"https://www.linkedin.com/in/emrebener",
"https://en.wikipedia.org/wiki/Emre_Bener"
]
}The load-bearing field is sameAs. It points to other URLs that describe the same person: GitHub, LinkedIn, Wikipedia, Wikidata. This is how a search engine or answer engine builds the bridge between your site’s Person and the broader web’s understanding of that person. For E-E-A-T (experience, expertise, authoritativeness, and trustworthiness, Google’s quality framework for content), sameAs is the explicit signal that a content author is who they say they are.
Use one canonical Person @id across the whole site; reference it from every article instead of redeclaring the Person each time.
4.3. WebSite
WebSite describes the site itself, not a specific page. Emit it only on the home page. The most concrete reason to bother is the SearchAction, which tells Google’s sitelinks search box which URL pattern to hit:
{
"@context": "https://schema.org",
"@type": "WebSite",
"@id": "https://example.com/#website",
"name": "Example",
"url": "https://example.com/",
"potentialAction": {
"@type": "SearchAction",
"target": "https://example.com/search?q={search_term_string}",
"query-input": "required name=search_term_string"
}
}Useful if you have a working search page; skippable otherwise.
4.4. BreadcrumbList
BreadcrumbList describes the navigation hierarchy from the site root to the current page. It’s what powers the breadcrumbs that appear above the URL in some Google search results.
{
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com/" },
{ "@type": "ListItem", "position": 2, "name": "Web Development", "item": "https://example.com/topics/web-development" },
{ "@type": "ListItem", "position": 3, "name": "JSON-LD and Schema.org" }
]
}position is 1-indexed and contiguous; the last item omits item because it’s the current page; the breadcrumb hierarchy doesn’t have to match the URL hierarchy literally.
4.5. ProfilePage and CollectionPage
Page-type wrappers: ProfilePage for “about” or author pages, CollectionPage for topic indexes or tag archives. They sit alongside the content entity in a @graph with a mainEntity field linking the page to its subject. Recent additions to Google’s rich-result support, useful when the page-type signal helps a parser disambiguate; skippable when the content-entity type already conveys what the page is (an Article page doesn’t need a WebPage wrapper to be understood as an article).
4.6. The long tail
Schema.org’s deeper vocabulary covers domain-specific types: Recipe, JobPosting, Product, LocalBusiness, Event, Course, Restaurant, Movie, and hundreds more. Each unlocks its own rich-result format in Google search; Recipe shows up with a star rating and prep time, JobPosting with salary range and location, Product with price and availability.
Use these only if your site genuinely models the domain. Setting Product on a page that isn’t selling something causes the validator to flag required fields you don’t have, and emitting Recipe on a non-recipe page is at best ignored and at worst penalized as deceptive structured data. Stick with Article, BlogPosting, Person, and BreadcrumbList unless the page is clearly something more specific.
5. Rich results: the SERP payoff
Rich results are Google’s visually enhanced search-result snippets: a recipe with a star rating and a thumbnail, a job posting with salary and location, an FAQ accordion that expands inline, a breadcrumb trail above the URL. They’re the most concrete reason to emit JSON-LD: they change how your page looks on the SERP, and that feeds straight into click-through rate.
The mechanism is straightforward: a Google crawler reads your JSON-LD, recognizes a Schema.org type it has rich-result support for, and (if the required fields are present and the page actually matches what the metadata claims) elevates the listing to the corresponding rich format.
5.1. Which types trigger rich results
Google has rich-result support for a specific subset of Schema.org types, much smaller than Schema.org itself. The current list (Google publishes the full reference at developers.google.com/search/docs/appearance/structured-data/search-gallery) includes:
Article/BlogPosting/NewsArticle: top-stories carousel, article carousel.BreadcrumbList: breadcrumbs above the URL.FAQPage: expandable accordion (Google restricted this in 2023 to authoritative health and government sites; smaller sites get limited or no rich-result rendering).HowTo: step-by-step cards (rich-result rendering largely retired in 2023).Recipe: star rating, prep time, calorie count.Product: price, availability, review stars.Event: date, location, ticket link.JobPosting: salary, location, posted date.Course/LocalBusiness/Movie: niche but live.VideoObject: thumbnail, duration, key moments.Organization/WebSite: knowledge-panel signals, sitelinks search box.ProfilePage: author profiles on some surfaces.
That’s the working map of “JSON-LD type → rich-result format.” Anything not on this list either doesn’t trigger a rich result or feeds general indexing without a special SERP layout.
5.2. JSON-LD makes a rich result possible, not certain
The most common misunderstanding about rich results is treating JSON-LD as a guarantee that one will render. It isn’t a guarantee. The pipeline runs:
- You emit JSON-LD with the right type and required fields.
- The page passes Google’s structured-data validator (no errors, no warnings on required fields).
- Google’s crawler indexes the page.
- Google’s quality systems decide whether to actually show the rich result.
Step 4 is the unpredictable one. Even pages with perfect JSON-LD can fail to get rich results if Google’s quality systems judge the page low-authority, the query type mismatched, or the result a poor match for what users on similar pages clicked through to. No API lets you check “will this page get a rich result”; the only way to find out is to look at the live SERP.
The corollary: don’t view JSON-LD’s job as “force a rich result.” View it as removing the obstacle that prevents one. The page becomes eligible; whether the result actually appears is Google’s judgment.
5.3. What rich results buy you
Three concrete benefits, in rough order of magnitude:
- Visual prominence. Stars, images, and structured layouts take more vertical space than a plain blue link. CTR lifts of 5-30% from rich results are well-documented in the SEO literature.
- Information conveyed without a click. A user who reads recipe rating, prep time, and calorie count from the SERP arrives more qualified, which lowers bounce and lengthens dwell time, both feeding back into ranking signals.
- Knowledge-panel and sitelinks-search-box eligibility. The right-side knowledge panel and the site-internal search box on the SERP require specific types (
Organization,WebSite) emitted on the home page.
5.4. The honest framing
JSON-LD isn’t a direct ranking factor. It changes how your existing rank position renders, not which page you’re on. A site on page 5 doesn’t reach page 1 by adding structured data, but a site already on page 1 with structured data can visibly outrank competitors with the same blue-link layout. On the SEO side, the payoff lives at the SERP-render level, not the rank level.
6. JSON-LD as the AEO lever
JSON-LD is the strongest single technical lever for AEO (answer engine optimization, getting your content cited or summarized by LLM-driven answer engines like ChatGPT, Perplexity, and Google AI Overviews). The reason is structural: answer engines synthesize answers from page content, and structured data hands them a pre-parsed graph of entities and relationships instead of forcing them to extract that graph from prose. A page with clean JSON-LD is easier to cite accurately and faster to parse at retrieval time, and more likely to get picked over a competitor’s page with the same prose but no structured metadata.
Google’s AI Overviews, Perplexity, ChatGPT’s web-browsing mode, and Bing Copilot all pull from structured data when it’s present; this is documented behavior, not speculation.
6.1. Why structured data beats prose for extraction
A traditional NLP (natural language processing) extraction pipeline works through an entire HTML document, tokenizes the text, runs entity recognition, applies coreference resolution, and produces a structured representation that may or may not match the original author’s intent. Good, but expensive and lossy.
JSON-LD skips most of those steps. The page already declares “this article is by this Person, who is the same as the GitHub user emrebener and the linked Wikidata entry for that author.” A retrieval engine doesn’t have to guess; it reads. For an LLM-driven answer engine generating citations on a tight latency budget, the difference between extracting from prose and reading a JSON object is significant.
The implication: if your goal is to be cited correctly, give the answer engine the citation it should produce. Don’t make it infer.
6.2. The article entity graph
A blog post’s structured-data graph has a small set of edges that matter for AEO. The BlogPosting carries an author edge to a Person, an about array to typed Things with Wikidata QIDs, a mentions array to secondary entities, and a publisher edge to an Organization. From the Person, sameAs edges fan out to Wikipedia, Wikidata, GitHub, and other external profiles. Each edge is something an answer engine can follow.
What each edge does:
Article.author→Personsays who wrote it. The engine attributes the citation to that person, with the qualifications they declare.Person.sameAs→ external profiles bridges your site to the broader web’s understanding of that person. An answer engine reads “the author here is the same as the Wikipedia entity for X” and pulls biographical context and credibility signals from the linked source.Article.about→Thingwith a Wikidata QID says what the article is about, in a way that’s unambiguous across sources. “This article is about https://www.wikidata.org/wiki/Q17107778” tells an answer engine “this is the Open Graph Protocol page” with no NLP guesswork.Article.mentions→Thingwith a QID is the looser version: secondary entities the article references. An answer engine ranking pages for “JSON-LD” can directly check whether your article mentions the JSON-LD entity by QID, no keyword matching required.
A concrete example, in JSON-LD:
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "A guide to JSON-LD and Schema.org",
"author": {
"@type": "Person",
"@id": "https://example.com/about#emre",
"name": "Emre Bener",
"sameAs": [
"https://www.wikidata.org/wiki/Q42",
"https://github.com/emrebener"
]
},
"about": [
{ "@id": "https://www.wikidata.org/wiki/Q6108942", "name": "JSON-LD" },
{ "@id": "https://www.wikidata.org/wiki/Q3475322", "name": "Schema.org" }
],
"mentions": [
{ "@id": "https://www.wikidata.org/wiki/Q17107778", "name": "Open Graph Protocol" },
{ "@id": "https://www.wikidata.org/wiki/Q180711", "name": "Search engine optimization" }
]
}The Wikidata QIDs are the load-bearing piece. They’re globally unique entity identifiers that disambiguate across languages and across naming conflicts (“Mercury” the planet vs. the metal vs. the band). An answer engine that sees Q17107778 knows exactly which entity is meant, regardless of how it was named in prose.
6.3. E-E-A-T and the Person entity
Google’s E-E-A-T framework (experience, expertise, authoritativeness, and trustworthiness) is the loose set of quality signals that influence both ranking and rich-result eligibility. For AEO purposes, E-E-A-T is the language an answer engine uses to decide whether to cite you. The signal mostly lives in the Person entity for the article’s author.
The strongest E-E-A-T signal in JSON-LD is Person.sameAs pointing at credibility-conferring external sources:
- Wikipedia / Wikidata. If you have an article, link it. If you don’t, skip; pretending to have a Wikipedia page when you don’t is worse than not linking.
- Authoritative profiles. GitHub for engineers, ORCID for academics, Crossref for published authors, IMDb for film professionals. Pick the one that matches your domain.
- Social profiles. LinkedIn, Mastodon, Bluesky. Lower-strength signals but still readable.
- Personal site. If the canonical
Person@idlives on your about page, make sure the home page’sWebSiteorOrganizationreferences the same@idrather than declaring a new Person.
What doesn’t help: a Person entity with only name (no external anchor to verify against, so functionally anonymous), sameAs pointing at profile pages without verifiable identity, or multiple competing Person entities for the same author across the site. Use one canonical @id everywhere.
6.4. Practical guidance for AEO
The optimization in priority order:
- Set
Person.sameAsfor every article author. This is the single highest-leverage AEO move. One canonicalPersonentity, linked to Wikipedia/Wikidata and GitHub/LinkedIn/etc. - Set
BlogPosting.aboutwith Wikidata QIDs for the article’s primary subjects. Two or three QIDs is enough; the goal is unambiguous topic identification, not coverage. - Set
BlogPosting.mentionswith QIDs for the secondary entities (around 4-6). - Emit valid
BlogPosting(orArticle) withheadline,image,datePublished,authorso rich-result eligibility is also covered. - Keep the JSON-LD consistent with the page’s content. If
aboutclaims the article is about JSON-LD but the prose is mostly about Microsoft Excel, an answer engine that re-reads the prose to verify will downweight or ignore the structured-data claim.
The fifth point matters more than it sounds. Answer engines don’t blindly trust JSON-LD; they cross-check against the page content. JSON-LD is a hint, not an assertion. If the hint is consistent with the prose, it’s load-bearing; if it isn’t, it’s discarded as spam.
7. Validators and debugging
JSON-LD has two validators worth using and a small list of common mistakes that account for most broken implementations. Validating before deploy and re-checking after major content changes is enough; you don’t need ongoing monitoring.
7.1. The two validators
Schema Markup Validator (validator.schema.org). The reference implementation, maintained by Schema.org itself. Fetches your URL or accepts a pasted JSON-LD block, parses against the full Schema.org vocabulary, and reports type errors, unknown properties, and shape issues. Good for “is my JSON-LD syntactically and semantically correct.”
Google Rich Results Test (search.google.com/test/rich-results). Maintained by Google. Same shape as the Schema.org validator but additionally checks rich-result eligibility for the page’s type: missing required fields, fields that don’t meet rich-result thresholds, and page-level issues that block rich-result rendering. Good for “is this going to produce a rich result on Google.”
The two are complementary. Schema Markup Validator catches a wider range of vocabulary errors; Rich Results Test catches the Google-specific gates. Run both on a new implementation; run Rich Results Test on every content change that touches structured-data fields.
7.2. Common pitfalls
The mistakes that account for most broken JSON-LD implementations:
- URL string where a nested entity is expected.
"author": "Emre Bener"instead of"author": { "@type": "Person", "name": "Emre Bener" }. The validator flags this; Google’s parser silently ignores the field. The set of consumers that accept the bare string form without complaint are small enough to ignore, and the shape doesn’t match Schema.org’sPersonanyway. - Missing required fields for rich-result eligibility.
Articleneedsheadline,image,datePublished,author.RecipeneedsrecipeIngredientandrecipeInstructions.ProductneedsofferswithpriceandpriceCurrency. The Rich Results Test lists per-type requirements; consult it before assuming a type works without all the fields. - Multiple competing JSON-LD blocks. Crawlers concatenate, but conflicting
@idvalues across blocks (two differentPersonentities sharing the same@id) can confuse parsers. One block per page, or one block with@graph, is the cleaner pattern. - Inconsistent canonical URLs.
og:url,<link rel="canonical">, and JSON-LD@idshould agree. When they disagree, crawlers pick one and the others become noise; worse, the disagreement can suppress rich-result rendering. - Stale or wrong dates.
datePublishedanddateModifiedmust be ISO 8601 format and must be plausible. AdatePublishedin the future, or adateModifiedbeforedatePublished, triggers validator errors and quality-system suspicion. - Image URLs that don’t fetch.
imagemust be an absolute URL that returns a real image. Validators check the URL is well-formed but don’t fetch; Google’s quality systems do, and fail rich-result eligibility if the image 404s or redirects.
7.3. A short checklist
- Run the JSON-LD through Schema Markup Validator. Fix any errors.
- Run the URL through Google Rich Results Test. Fix any “missing required” warnings.
- Verify
og:url,<link rel="canonical">, and JSON-LD@idagree. - Spot-check that
imageURLs return real images. - Confirm
datePublishedanddateModifiedare ISO 8601 and ordered correctly.
After major content changes, re-run Rich Results Test on changed pages, and if about / mentions QIDs changed, verify each still resolves to the intended entity on Wikidata.
8. Where OG and JSON-LD divide the work
OG and JSON-LD are siblings, not competitors. Each one answers a different question, and a typical page wants both. OG handles “what does this URL look like when shared on social and chat platforms.” JSON-LD handles “what does this page mean to search engines, answer engines, and the broader structured-data web.”
In one table:
| Concern | OG | JSON-LD |
|---|---|---|
| Social unfurl card (Slack, LinkedIn, X, iMessage) | Primary | Not used |
| Google rich result (stars, breadcrumbs, FAQ) | Not used | Primary |
| LLM / answer-engine extraction | Secondary signal | Primary signal |
| Author identity, E-E-A-T | Not expressible | Primary |
| Article topic via Wikidata QID | Not expressible | Primary |
| Page title, description, image | Yes (for the card) | Yes (for the article entity) |
The overlap is the bottom row. Title, description, and image are present in both formats; setting them with consistent values is the right move because crawlers cross-check, and inconsistent values get treated as low-quality signal.
The practical minimum for a typical blog post:
- OG block in
<head>: the ten tags covered in the Open Graph post, plus onetwitter:cardtag. - JSON-LD block in
<head>: aBlogPostingwithheadline,image,datePublished,author(referencing a canonicalPerson@idwithsameAs),aboutandmentionsarrays of Wikidata QIDs, plus aBreadcrumbListif the site has a hierarchy. One@graphblock, not multiple. - Validators: OG via Facebook Sharing Debugger; JSON-LD via Schema Markup Validator and Google Rich Results Test.
That’s the working set. Both blocks in <head>, the right values, validated. The rest is content quality, which neither standard fixes.