Mixing JSON-LD CollectionPage and Microdata `hasPart` of Schema.org
Asked Answered
S

1

5

The microdata markup below works perfectly, Google's structured data testing tool shows one CollectionPage and WebSite/WebPage as children.

<body itemscope itemtype="https://schema.org/CollectionPage">
  <span itemscope itemtype="https://schema.org/WebSite" itemprop="hasPart">
    <a href="https://springfield-xxxx.us" itemprop="url">Official site of Springfield</a>
  </span>
  <span itemscope itemtype="https://schema.org/WebPage" itemprop="hasPart">
    <a href="https://facebook.com/group/XXXX" itemprop="url">Local events in Springfield</a>
  </span>
  <span itemscope itemtype="https://schema.org/WebPage" itemprop="hasPart">
    <a href="https://news.us/city/springfield-xxxx" itemprop="url">Latest news in Springfield</a>
  </span>
</body>

However when I add JSON-LD Google's structured data testing tool shows objects CollectionPage and WebPage/WebSite separately like if they had no connection. Here is a sample with JSON-LD:

<!DOCTYPE html>
<html>
<head>
  <script type="application/ld+json">
    {
      "description": "...",
      "author": {"@type":"Person", "name": "Homer J. Simpson"},
      "@type": "CollectionPage",
      "url": "http://my-springfield.us/sites",
      "publisher": {
        "@type": "Organization",
        "logo": "Object of type ImageObject here",
        "name": "Homer J. Simpson"
      },
      "image": "...",
      "headline": "Springfield Sites",
      "sameAs": ["..."],
      "@context": "http://schema.org"
    }
  </script>
</head>
<body>
  <span itemscope itemtype="https://schema.org/WebSite" itemprop="hasPart">
    <a href="https://springfield-xxxx.us" itemprop="url">Official site of Springfield</a>
  </span>
  <span itemscope itemtype="https://schema.org/WebPage" itemprop="hasPart">
    <a href="https://facebook.com/group/XXXX" itemprop="url">Local events in Springfield</a>
  </span>
  <span itemscope itemtype="https://schema.org/WebPage" itemprop="hasPart">
    <a href="https://news.us/city/springfield-xxxx" itemprop="url">Latest news in Springfield</a>
  </span>
</body>
</html>

I tried putting @id in JSON-LD and itemid on the body to no avail: Google testing tool shows two separate CollectionPages or two separate items of other types.

My question: how to connect JSON-LD and microdata so that Google testing tool shows one CollectionPage with WebPage/WebSite as children/props?

Sheep answered 3/6, 2018 at 15:7 Comment(0)
N
3

like if they had no connection

Well, they aren’t connected in your example. JSON-LD and Microdata can’t work together on the syntax-level.

If you want to connect entities defined in different syntaxes, the only way is to

  • give these entities URIs (the same URI if they are the same thing), and
  • reference these URIs as property values (if one entity is the value of another entity’s property).

Giving entities URIs works in the way you mentioned: with @id in JSON-LD, and with itemid in Microdata (and with resource in RDFa Lite).

Consumers (services like search engines or Google’s SDTT, local clients like browser add-ons etc.) would have to support following references (not all do), and if they do support following references, they would also have to support parsing the additional syntax (not all do).

But even if you make use of such URI references, it doesn’t change the conformance requirements of the syntaxes you use. Your HTML document is invalid, because you have itemprop attributes that don’t belong to an itemscope. This is not allowed. So if you want to keep using Microdata, you have to provide the parent item in Microdata, too (CollectionPage in your case).

This would be the way to convey that both CollectionPage occurrences represent the same entity (they have the same URI = the base URL of the current document):

<script type="application/ld+json">
  {
    "@context": "http://schema.org",
    "@type": "CollectionPage",
    "@id": ""
  }
</script>

<div itemscope itemtype="http://schema.org/CollectionPage" itemid="">
  <span itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite"></span>
  <span itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite"></span>
  <span itemprop="hasPart" itemscope itemtype="http://schema.org/WebPage"></span>
</div>

Google’s SDTT still displays two CollectionPage entries (if syntaxes are mixed), but they (correctly) have the same URI. It’s up to Google to decide what to do with this information for their various structured data features. Maybe mixed-syntax references are supported for none/some/all of their features (they don’t seem to document it); how their SDTT displays things doesn’t necessarily reflect how they interpret it for their features.

More examples

Narcolepsy answered 3/6, 2018 at 17:3 Comment(3)
(Note that my answer assumes that you have to mix syntaxes. However, it should typically be possible to use only one syntax, so if there is an issue preventing you from using only one syntax, you might want to create another question about it.)Narcolepsy
I want to use microdata syntax, but then I will have to make author and publisher visible, because I see no way of using <meta> or <link> for defining them. And hiding other html elements that contain microdata is not recommended. If you have solution for this then I will create another question.Sheep
@ilyaigpetrov: Using meta/link (and div/span if grouping is needed) is the solution :) You don’t have to hide these elements, they are typically hidden by default in user agents. -- With the recommendation you probably refer to SEO advice. What it means is that you shouldn’t provide content in your structured data (that isn’t also part of your page) for the purpose of manipulating search engines. There are many reasons where it’s perfectly fine to provide hidden structured data in Microdata/RDFa; and with JSON-LD, everything is hidden anyway.Narcolepsy

© 2022 - 2024 — McMap. All rights reserved.