Best JSON-LD practices: using multiple <script> elements?
Asked Answered
J

3

94

I'm curious about the best practice for applying JSON-LD onto a site for schema.org.

If I have a page with an Article and I also want to define WebSite on my page, I would have this:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "url": "http://www.example.com/",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "http://www.example.com/search?&q={query}",
      "query-input": "required"
    }
}
</script>

<!- … -->

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "Article",
  "author": "John Doe",
  "interactionCount": [
    "UserTweets:1203",
    "UserComments:78"
  ],
  "name": "How to Tie a Reef Knot"
}
</script>

Is this correct or wrong? Is there any benefit or need to merge these into the same script or array of items?

Jhansi answered 9/6, 2015 at 5:18 Comment(3)
read this w3.org/TR/json-ld/#h3_advanced-context-usage, just use a simple listHolystone
Updated link: w3.org/TR/json-ld/#advanced-context-usagePuccini
Related: JSON-LD script elements (data blocks) MUST only contain valid JSONConventicle
F
67

It’s valid. You can have as many data blocks (= script elements) as you wish.

A possible benefit of using only one script element: it allows to make relationships between multiple items easier (e.g., should you decide to use hasPart or mainEntity), as you simply have to nest the items.
But making these relationships is of course also possible when using separate data blocks, by referencing the URI of the item with @id (thanks, @ Gregg Kellogg).

(For reference, adding two or more top-level items in a single script is possible with @graph.)

Fit answered 9/6, 2015 at 11:9 Comment(4)
You can also tie together the nodes in JSON-LD script block using @id. From a model perspective, they all get treated as triples in a common graph. However, search engines may "optimize" and not so what you expect. Using JSON-LD algorithms there's probably not a good reason to use separate script blocks; just merge them into a common object, or even an array of objects.Knighterrant
@GreggKellogg and unor - Thanks for the answers! My main concern was due to the limitations of a CMS, since WebSite is something I would specify at a global level and Article is specified at the page level. I wasn't quite sure what to expect in this scenario. Google's Structured Data Tool gives it an okay but I'm always a little skeptical there :)Jhansi
@GreggKellogg so it's 2017, is the recommendation now@graph or an array of objects? The relevant discussion was done in 2012 (github.com/json-ld/json-ld.org/issues/96), and the consensus from my reading was @graph for multiple top-level objects. Thanks in advance.Mapping
@AmirR Typically you'll use @graph (or an alias of @graph) to allow the use of a single top-level object with shared context. Both are quite legitimate, however. Note that another pattern is to use a reverse property with a common object value used as the top-level object, linking to all resources that reference it. See Reverse Properties.Knighterrant
C
81

There is no benefit in having single or multiple data blocks, other than limitations around how you might store and manage schema data in your website.

For example, you might need them separate if different components within your website are responsible for generating each data block independently. Alternatively, if your website is able to manage all schemas for one page in one place, it may be simpler to manage a single data block and render this as a single script element.

You can combine these into a single script by listing each schema as an array like this:

<script type="application/ld+json">
[
  {
    "@context": "http://schema.org",
    "@type": "WebSite",
    "url": "http://www.example.com/",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "http://www.example.com/search?&q={query}",
      "query-input": "required"
    }
  },
  {
    "@context": "http://schema.org",
    "@type": "Article",
    "author": "John Doe",
    "interactionCount": [
      "UserTweets:1203",
      "UserComments:78"
    ],
    "name": "How to Tie a Reef Knot"
  }
]
</script>
Cervin answered 5/10, 2015 at 17:21 Comment(3)
why not graph upbuild.io/blog/…Travistravus
@ujwaldhakal because they would have to be the same typeLongmire
I stand corrected - https://mcmap.net/q/225452/-how-do-you-combine-several-json-ld-markupsLongmire
F
67

It’s valid. You can have as many data blocks (= script elements) as you wish.

A possible benefit of using only one script element: it allows to make relationships between multiple items easier (e.g., should you decide to use hasPart or mainEntity), as you simply have to nest the items.
But making these relationships is of course also possible when using separate data blocks, by referencing the URI of the item with @id (thanks, @ Gregg Kellogg).

(For reference, adding two or more top-level items in a single script is possible with @graph.)

Fit answered 9/6, 2015 at 11:9 Comment(4)
You can also tie together the nodes in JSON-LD script block using @id. From a model perspective, they all get treated as triples in a common graph. However, search engines may "optimize" and not so what you expect. Using JSON-LD algorithms there's probably not a good reason to use separate script blocks; just merge them into a common object, or even an array of objects.Knighterrant
@GreggKellogg and unor - Thanks for the answers! My main concern was due to the limitations of a CMS, since WebSite is something I would specify at a global level and Article is specified at the page level. I wasn't quite sure what to expect in this scenario. Google's Structured Data Tool gives it an okay but I'm always a little skeptical there :)Jhansi
@GreggKellogg so it's 2017, is the recommendation now@graph or an array of objects? The relevant discussion was done in 2012 (github.com/json-ld/json-ld.org/issues/96), and the consensus from my reading was @graph for multiple top-level objects. Thanks in advance.Mapping
@AmirR Typically you'll use @graph (or an alias of @graph) to allow the use of a single top-level object with shared context. Both are quite legitimate, however. Note that another pattern is to use a reverse property with a common object value used as the top-level object, linking to all resources that reference it. See Reverse Properties.Knighterrant
E
0

Just tested this on Google's Rich Result Test.

I have one script that contains the info that should always be present in the schema: name, brand, description, etc. I have another script that contains optional things: reviews and aggregate ratings.

Unfortunately, RRT tells me it's missing the reviews and aggregate ratings properties.

Multiple JSON-LD scripts doesn't seem to be supported.

It's a real hassle, because an empty review array and a review count of 0 (for the aggregate rating) are also not supported.

Conditional JSON-LD properties are turning out to be quite the challenge for those who want to dynamically put them on the page.

Ensepulcher answered 11/8, 2022 at 15:4 Comment(2)
This doesn't sound like an issue with multiple scripts to me, but an issue with JSON-LD and expectation on products. Google (or at least the testing tools in my experience, granted it's been a while since I've tested) are very picky about product JSON structures. As @GreggKellogg mentioned above you might want to try mapping them with an ID if your product JSON-LD is split up. I agree with you that forcing reviews/ratings on a product isn't realistic for all scenarios. It might be worth asking that question here for some examples of getting around it.Jhansi
Reviews and ratings aren't forced in the sense that they are expected to be on there. You can leave'em out and it won't cause warnings in the RRT. Naturally, you can put as many scripts on your page as you want. But RRT isn't looking at the second one. They don't get treated as merged-into-a-single-script.Ensepulcher

© 2022 - 2024 — McMap. All rights reserved.