WebSchemas/ChainingLayoutElements
Overlapping topics brought together
Intro
This document is an attempt at supporting ongoing discussions
- about adding a reverse-mechanism to microdata
- about how to chain WebPageElements to a WebPage
- about how to chain WebPageElements to the Things they contain
- about how to express the Order of WebPageElements
- about how to express ItemLists / CollectionPages (over multiple pages)
Note: Examples will use the same HTML examples over and over again so to illustrate the differences in markup needed, depending on what needs to be expressed. They aren't meant to be implemented by publishers of structured data but serve as an experimental base to find out which solution(s) are best suited for the matters at hand.
Discussion history
Inverse mechanism for microdata
- http://lists.w3.org/Archives/Public/public-vocabs/2014Aug/0000.html
- proposal: https://www.w3.org/wiki/WebSchemas/InverseProperties
- http://lists.w3.org/Archives/Public/public-vocabs/2014Apr/0200.html
Chaining WebPageElement and WebPage
- http://lists.w3.org/Archives/Public/public-vocabs/2014Aug/0000.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Jul/0053.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Apr/0272.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Jan/0091.html
- http://lists.w3.org/Archives/Public/public-vocabs/2011Oct/0100.html
mainContentOfPage / mainEntity / primaryTopic
- http://lists.w3.org/Archives/Public/public-vocabs/2014Jun/0149.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014May/0248.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014May/0125.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Apr/0255.html
- http://lists.w3.org/Archives/Public/public-vocabs/2013Sep/0156.html
- http://lists.w3.org/Archives/Public/public-vocabs/2011Nov/0073.html
ItemList
- http://lists.w3.org/Archives/Public/public-vocabs/2014Sep/0059.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Aug/0038.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Jun/0121.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014May/0121.html
- http://lists.w3.org/Archives/Public/public-vocabs/2013Sep/0143.html
- http://lists.w3.org/Archives/Public/public-vocabs/2013Jun/0042.html
@itemid
- http://lists.w3.org/Archives/Public/public-vocabs/2014Sep/0056.html
- http://lists.w3.org/Archives/Public/public-vocabs/2014Jun/0098.html
- http://lists.w3.org/Archives/Public/public-html-data-tf/2011Oct/0197.html
Possible solutions for chaining entities and specifying the main entity
- All 'reverse relations' require adding an @itemprop-reverse attribute to microdata.
Chaining / Main entity examples
ItemPage, Article
- ItemPage > relation > Article (mainContentOfPage / mainEntity)
These variants require the range of 'mainContentOfPage' to be expanded to Thing or that 'mainEntity' be added to schema.org/WebPage.
An ItemPage which has an Article as it's mainContentOfPage (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/ItemPage">
<main>
<article itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/Article">
[...]
</article>
</main>
</body>
</html>
An Article which is the mainContentOfPage of an ItemPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/ItemPage">
<main>
<article itemscope itemtype="http://schema.org/Article">
[...]
<link itemprop-reverse="mainContentOfPage" href="https://example.com" />
</article>
</main>
</body>
</html>
An ItemPage which has an Article as it's mainEntity (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/ItemPage">
<main>
<article itemprop="mainEntity" itemscope itemtype="http://schema.org/Article">
[...]
</article>
</main>
</body>
</html>
An Article which is the mainEntity of an ItemPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/ItemPage">
<main>
<article itemscope itemtype="http://schema.org/Article">
[...]
<link itemprop-reverse="mainEntity" href="https://example.com" />
</article>
</main>
</body>
</html>
CollectionPage, ItemList
- CollectionPage > relation > ItemList (mainContentOfPage / mainEntity)
These variants require the range of 'mainContentOfPage' to be expanded to Thing or that 'mainEntity' be added to schema.org/WebPage.
A CollectionPage which has an ItemList as it's mainContentOfPage (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/ItemList">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
An ItemList which is the mainContentOfPage of a CollectionPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemscope itemtype="http://schema.org/ItemList">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
<link itemprop-reverse="mainContentOfPage" href="https://example.com" />
</div>
</main>
</body>
</html>
A CollectionPage which has an ItemList as it's mainEntity (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
An ItemList which is the mainEntity of a CollectionPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemscope itemtype="http://schema.org/ItemList">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
<link itemprop-reverse="mainEntity" href="https://example.com" />
</div>
</main>
</body>
</html>
CollectionPage, ItemList, Product
- CollectionPage > mainContentOfPage > ItemList
- ItemList > relation > Product (itemListElement)
These variants is requires the schema.org/ItemList proposal to be integrated.
An ItemList which has Products as itemListElements (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="itemListOrder" content="Unordered">
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
Products which are itemListElements of an ItemList (up the DOM, reverse relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemid="#ItemList" itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="itemListOrder" content="Unordered">
<ul>
<li itemscope itemtype="http://schema.org/Product">
[...]
<link itemprop-reverse="itemListElement" href="#ItemList" />
</li>
<li itemscope itemtype="http://schema.org/Product">
[...]
<link itemprop-reverse="itemListElement" href="#ItemList" />
</li>
<li itemscope itemtype="http://schema.org/Product">
[...]
<link itemprop-reverse="itemListElement" href="#ItemList" />
</li>
</ul>
</div>
</main>
</body>
</html>
CollectionPage, WebPageElement, ItemList, Product
- CollectionPage > mainContentOfPage > WebPageElement
- CollectionPage > relation > ItemList (mainEntity)
- WebPageElement > hasPart > ItemList
- ItemList > itemListElement > Product
These variants is require the schema.org/ItemList proposal to be integrated, as well as having 'hasPart' and 'mainEntity' being added
A CollectionPage which has an ItemList as it's mainEntity (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<link itemprop="mainEntity" href="#ItemList" />
<main itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#ItemList" itemprop="hasPart" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="itemListOrder" content="Unordered">
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
An ItemList which is the mainEntity of a CollectionPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/CollectionPage">
<main itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<div itemprop="hasPart" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="itemListOrder" content="Unordered">
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
<link itemprop-reverse="mainEntity" href="https://example.com">
</div>
</main>
</body>
</html>
CollectionPage, WebPageElement
- CollectionPage > relation > WebPageElement (mainContentOfPage / mainEntity)
These variants requires the range of 'mainContentOfPage' to be expanded to Thing or that 'mainEntity' be added to schema.org/WebPage.
A CollectionPage which has a WebPageElement as it's mainContentOfPage (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
A WebPageElement which is the mainContentOfPage of a CollectionPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
<link itemprop-reverse="mainContentOfPage" href="https://example.com" />
</div>
</main>
</body>
</html>
A CollectionPage which has a WebPageElement as it's mainEntity (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainEntity" itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
A WebPageElement which is the mainEntity of a CollectionPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li>
[...]
</li>
<li>
[...]
</li>
<li>
[...]
</li>
</ul>
<link itemprop-reverse="mainEntity" href="https://example.com" />
</div>
</main>
</body>
</html>
CollectionPage, WebPageElement, ImageObject
- CollectionPage > mainContentOfPage > WebPageElement
- WebPageElement > relation > ImageObject (*Part*)
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
A WebPageElement which has multiple ImageObject parts (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/ImageObject">
[...]
</li>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/ImageObject">
[...]
</li>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/ImageObject">
[...]
</li>
</ul>
</div>
</main>
</body>
</html>
Multiple ImageObjects which are part of a WebPageElement (up the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemid="#WebPageElement" itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop="isPartOf" href="#WebPageElement" />
</li>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop="isPartOf" href="#WebPageElement" />
</li>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop="isPartOf" href="#WebPageElement" />
</li>
</ul>
</div>
</main>
</body>
</html>
Multiple ImageObjects which are part of a WebPageElement (up the DOM, reverse relation)
<html>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main>
<div itemid="#WebPageElement" itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/WebPageElement">
<ul>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop-reverse="hasPart" href="#WebPageElement" />
</li>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop-reverse="hasPart" href="#WebPageElement" />
</li>
<li itemscope itemtype="http://schema.org/ImageObject">
[...]
<link itemprop-reverse="hasPart" href="#WebPageElement" />
</li>
</ul>
</div>
</main>
</body>
</html>
WebPage, WebSite
- WebPage > relation > WebSite (*Part*)
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
A WebPage which is part of a WebSite (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<header>
<section>
<div itemprop="isPartOf" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
</header>
</body>
</html>
A WebPage which is part of a WebSite (up the DOM, reverse relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<header>
<section>
<div itemid="#WebSite" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
</header>
<link itemprop-reverse="hasPart" href="#WebSite" />
</body>
</html>
WebPage, WPHeader, Website
- WebPage > ispartOf > WebSite
- WebPage > relation > WPHeader (*Part*)
- WPHeader > hasPart > WebSite
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
A WebPage which has a WPHeader part (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header itemprop="hasPart" itemscope itemtype="http://schema.org/WPHeader">
<section>
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
</header>
</body>
</html>
a WPHeader which is part of a WebPage (up the DOM, normal relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header itemscope itemtype="http://schema.org/WPHeader">
<section>
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
<link itemprop="isPartOf" href="https://example.com" />
</header>
</body>
</html>
a WPHeader which is part of a WebPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header itemscope itemtype="http://schema.org/WPHeader">
<section>
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
<link itemprop-reverse="hasPart" href="https://example.com" />
</header>
</body>
</html>
WebPage, WebPageElement, Website
- WebPage > isPartOf > WebSite
- WebPage > relation > WebPageElement (*Part*)
- WebPageElement > hasPart > WebSite
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
A WebPage which has a WebPageElement part (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header>
<section itemprop="hasPart" itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
</header>
</body>
</html>
A WebpageElement which is part of a WebPage (up the DOM, normal relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header>
<section itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
<link itemprop="isPartOf" href="https://example.com" />
</section>
</header>
</body>
</html>
A WebpageElement which is part of a WebPage (up the DOM, reverse relation)
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header>
<section itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
<link itemprop-reverse="hasPart" href="https://example.com" />
</section>
</header>
</body>
</html>
WebPage, WPHeader, WebPageElement, Website
- WebPage > isPartOf > WebSite
- WebPage > hasPart > WPHeader
- WPHeader > relation > WebPageElement (*Part*)
- WebPageElement > hasPart > WebSite
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
A WPHeader which has a WebPageElement part (down the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header itemprop="hasPart" itemscope itemtype="http://schema.org/WPHeader">
<section itemprop="hasPart" itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
</section>
</header>
</body>
</html>
A WebPageElement which is part of a WPHeader (up the DOM, normal relation)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<link itemprop="isPartOf" href="#WebSite">
<header itemid="#WPHeader" itemprop="hasPart" itemscope itemtype="http://schema.org/WPHeader">
<section itemscope itemtype="http://schema.org/WebPageElement">
<div itemid="#WebSite" itemprop="hasPart" itemscope itemtype="http://schema.org/WebSite">
<h1>
<a itemprop="url" href="https://example.com/some-page/">
<img itemprop="image" src="https://example.com/image.jpg">
<span itemprop="name">[website-name]</span>
</a>
</h1>
<div itemprop="description">
<p>[website-description]</p>
</div>
</div>
<link itemprop="isPartOf" href="#WPHeader" />
</section>
</header>
</body>
</html>
- WebPage > relation > SiteNavigationElement (*Part*)
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<nav itemprop="hasPart" itemscope itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li>
<a href="https://example.com">
<span>home</span>
</a>
</li>
<li>
<a href="https://example.com/products/">
<span>products</span>
</a>
<ul>
<li>
<a href="https://example.com/category-1/">
<span>product-category-1</span>
</a>
</li>
<li>
<a href="https://example.com/category-2/">
<span>product-category-2</span>
</a>
</li>
</ul>
</li>
<li>
<a href="https://example.com/about-us/">
<span>about us</span>
</a>
</li>
<li>
<a href="https://example.com/contact/">
<span>contact</span>
</a>
</li>
</ul>
</nav>
</body>
</html>
<html>
<body itemid="https://example.com" itemscope itemtype="http://schema.org/WebPage">
<nav itemscope itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li>
<a href="https://example.com">
<span>home</span>
</a>
</li>
<li>
<a href="https://example.com/products/">
<span>products</span>
</a>
<ul>
<li>
<a href="https://example.com/category-1/">
<span>product-category-1</span>
</a>
</li>
<li>
<a href="https://example.com/category-2/">
<span>product-category-2</span>
</a>
</li>
</ul>
</li>
<li>
<a href="https://example.com/about-us/">
<span>about us</span>
</a>
</li>
<li>
<a href="https://example.com/contact/">
<span>contact</span>
</a>
</li>
</ul>
<link itemprop-reverse="isPartOf" href="https://example.com" />
</nav>
</body>
</html>
- WebPage > hasPart > SiteNavigationElement
- SiteNavigationElement > relation > WebPage (*Part*)
These variants require 'hasPart' to be added as inverse of 'isPartOf'.
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<nav itemprop="hasPart" itemscope itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/WebPage">
<a itemprop="url" href="https://example.com">
<span itemprop="name">home</span>
</a>
</li>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://example.com/products/">
<span itemprop="name">products</span>
</a>
<ul>
<li>
<a href="https://example.com/category-1/">
<span>product-category-1</span>
</a>
</li>
<li>
<a href="https://example.com/category-2/">
<span>product-category-2</span>
</a>
</li>
</ul>
</li>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/AboutPage">
<a itemprop="url" href="https://example.com/about-us/">
<span itemprop="name">about us</span>
</a>
</li>
<li itemprop="hasPart" itemscope itemtype="http://schema.org/ContactPage">
<a itemprop="url" href="https://example.com/contact/">
<span itemprop="name">contact</span>
</a>
</li>
</ul>
</nav>
</body>
</html>
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<nav itemid="#SiteNavigationElement" itemprop="hasPart" itemscope itemtype="http://schema.org/SiteNavigationElement">
<ul>
<li itemscope itemtype="http://schema.org/WebPage">
<a itemprop="url" href="https://example.com">
<span itemprop="name">home</span>
</a>
<link itemprop-reverse="hasPart" href="#SiteNavigationElement" />
</li>
<li itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://example.com/products/">
<span itemprop="name">products</span>
</a>
<ul>
<li>
<a href="https://example.com/category-1/">
<span>product-category-1</span>
</a>
</li>
<li>
<a href="https://example.com/category-2/">
<span>product-category-2</span>
</a>
</li>
</ul>
<link itemprop-reverse="hasPart" href="#SiteNavigationElement" />
</li>
<li itemscope itemtype="http://schema.org/AboutPage">
<a itemprop="url" href="https://example.com/about-use/">
<span itemprop="name">about us</span>
</a>
</li>
<li itemscope itemtype="http://schema.org/ContactPage">
<a itemprop="url" href="https://example.com/contact/">
<span itemprop="name">contact</span>
</a>
<link itemprop-reverse="hasPart" href="#SiteNavigationElement" />
</li>
</ul>
</nav>
</body>
</html>
Possible solution for expressing WebPageElement order
Thing property
- introduce isContainedIn > WebPageElement
WebPageElement properties
- introduce contains > Thing
- introduce previousElement > IRI
- introduce nextElement > IRI
Note: Adding a property like 'elementPosition' would not help as WebPageElements can also be nested within each other. Making a top down order difficult to express with a numerated value.
WebPageElement order Example (requires @itemid)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<header itemid="#WPHeader" itemprop="hasPart" itemscope itemtype="http://schema.org/WPHeader">
<div itemprop="contains" itemscope itemtype="http://schema.org/WebPageElement">
[...]
</div>
<link itemprop="nextElement" href="#SiteNavigationElement">
</header>
<nav itemid="#SiteNavigationElement" itemprop="hasPart" itemscope itemtype="http://schema.org/SiteNavigationElement">
<div itemprop="contains" itemscope itemtype="http://schema.org/ItemList">
[...]
</div>
<link itemprop="previousElement" href="#WPHeader">
<link itemprop="nextElement" href="#Product">
</nav>
<main itemid="#Product" itemprop="mainContentOfPage" itemscope itemtype="http://schema.org/Product">
<link itemprop="previousElement" href="#SiteNavigationElement">
<link itemprop="nextElement" href="#WPSideBar">
<div itemprop="contains" itemscope itemtype="http://schema.org/WebPageElement">
[...]
</div>
</main>
<aside itemid="#WPSideBar" itemprop="hasPart" itemscope itemtype="http://schema.org/WPSideBar">
<section itemprop="contains" itemscope itemtype="http://schema.org/ItemList">
[...]
</section>
<link itemprop="previousElement" href="#Product">
<link itemprop="nextElement" href="#WPFooter">
</aside>
<footer itemid="#WPFooter" itemprop="hasPart" itemscope itemtype="http://schema.org/WPFooter">
<div itemprop="contains" itemscope itemtype="http://schema.org/ContactPoint">
[...]
</div>
<link itemprop="previousElement" href="#WPSideBar">
</footer>
</body>
</html>
Possible solutions for expressing ItemLists
ItemList properties
- itemListElement > Text, Thing, ListItem
- itemListOrder > Text, ItemListOrderType
- numberOfItems > Number
- ? introduce sortingValue > Text (for specifying the value used for sorting the ItemList)
itemListOrder values
- Acscending (implied by default) = http://schema.org/ItemListOrderAscending = <ol> = value is going up i.e. 1-10 / A-Z
- Descending = http://schema.org/ItemListOrderDescending = <ol reverse> = value is going down i.e. 10-1 / Z-A
- Unordered = http://schema.org/ItemListUnordered = <ul> = value of itemListOrder
Note: The references to HTML5 attributes, values and descriptions are not binding but are there to illustrate possible similarities.
ListItem properties
- item > Thing
- position > Text (or Integer or Number?) = <li value="7">
- previousItem > IRI = <ol start="[prevNum + 1]">
- nextItem > IRI = <ol> resolved by DOM
ItemList Examples
Breadcrumbs
A breadcrumb (without @itemid - Succeeds)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<div itemprop="breadcrumb" itemscope itemtype="http://schema.org/ItemList">
<ol>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://example.com/books/">
<span itemprop="name">Books</span>
</a>
</span>
<meta itemprop="position" content="1">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://www.example.com/books/authors/">
<span itemprop="name">Authors</span>
</a>
</span>
<meta itemprop="position" content="2">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/WebPage">
<a itemprop="url" href="https://www.example.com/books/authors/stephen-king/">
<span itemprop="name">Stephen King</span>
</a>
</span>
<meta itemprop="position" content="3">
</li>
</ol>
</div>
</body>
</html>
A breadcrumb (using @itemid in combination with nextItem/previousItem - Succeeds)
<html>
<body itemscope itemtype="http://schema.org/WebPage">
<div itemprop="breadcrumb" itemscope itemtype="http://schema.org/ItemList">
<ol>
<li itemid="#ListItem-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://example.com/books/">
<span itemprop="name">Books</span>
</a>
</span>
<link itemprop="nextItem" href="#ListItem-2">
</li>
<li itemid="#ListItem-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/CollectionPage">
<a itemprop="url" href="https://www.example.com/books/authors/">
<span itemprop="name">Authors</span>
</a>
</span>
<link itemprop="previousItem" href="#ListItem-1">
<link itemprop="nextItem" href="#ListItem-3">
</li>
<li itemid="#ListItem-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/WebPage">
<a itemprop="url" href="https://www.example.com/books/authors/stephen-king/">
<span itemprop="name">Stephen King</span>
</a>
</span>
<link itemprop="previousItem" href="#ListItem-2">
</li>
</ol>
</div>
</body>
</html>
Paginated Ordered ItemList
A paginated Ordered ItemList (without @itemid - Fails)
<!-- 1st page of a paginated Ordered ItemList -->
<html>
<head>
<link rel="canonical" href="https://www.example.com/article-listing/">
<link rel="next" href="https://www.example.com/article-listing/page/2/">
</head>
<body itemscope itemtype="http://schema.org/CollectionPage">
<!-- Without @itemid there's no way of indicating each ItemList is a piece of a bigger ItemList -->
<main itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListOrderAscending">
<meta itemprop="numberOfItems" content="6">
<!-- Note the use of 'sortingValue', this could express the value the ItemList is sorted by -->
<meta itemprop="sortingValue" content="date">
<h1 itemprop="name">News</h1>
<ol>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/january">[...]</a>
</span>
<meta itemprop="position" content="1">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/february">[...]</a>
</span>
<meta itemprop="position" content="2">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/march">[...]</a>
</span>
<meta itemprop="position" content="3">
</li>
</ol>
</main>
</body>
</html>
<!-- 2nd page of a paginated Ordered ItemList -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/article-listing/page/2/">
<link rel="prev" href="http://www.example.com/article-listing/page/">
</head>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListOrderAscending">
<meta itemprop="numberOfItems" content="6">
<meta itemprop="sortingValue" content="date">
<h1 itemprop="name">News</h1>
<ol start="4">
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/april">[...]</a>
</span>
<meta itemprop="position" content="4">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/may">[...]</a>
</span>
<meta itemprop="position" content="5">
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/june">[...]</a>
</span>
<meta itemprop="position" content="6">
</li>
</ol>
</main>
</body>
</html>
A paginated Ordered ItemList (using @itemid - Succeeds)
<!-- 1st page of a paginated Ordered ItemList -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/article-listing/">
<link rel="next" href="http://www.example.com/article-listing/page/2/">
</head>
<body itemscope itemtype="http://schema.org/CollectionPage">
<!-- Every ItemList's @itemid uses the same IRI, thus describing the same entity on -->
<!-- multiple pages, making it possible to coalesce all their graphs into one graph. -->
<main itemid="http://www.example.com/article-listing/#ItemList" itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListOrderAscending">
<meta itemprop="numberOfItems" content="6">
<!-- Note the use of 'sortingValue', this could express the value the ItemList is sorted by -->
<meta itemprop="sortingValue" content="date">
<h1 itemprop="name">News</h1>
<ol>
<li itemid="#ListItem-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/january">[...]</a>
</span>
<link itemprop="previousItem" href="http://schema.org/False">
<link itemprop="nextItem" href="#ListItem-2">
</li>
<li itemid="#ListItem-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/february">[...]</a>
</span>
<link itemprop="previousItem" href="#ListItem-1">
<link itemprop="nextItem" href="#ListItem-3">
</li>
<li itemid="#ListItem-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/march">[...]</a>
</span>
<link itemprop="previousItem" href="#ListItem-2">
<link itemprop="nextItem" href="#ListItem-4">
</li>
</ol>
</main>
</body>
</html>
<!-- 2nd page of a paginated Ordered ItemList -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/article-listing/page/2/">
<link rel="prev" href="http://www.example.com/article-listing/page/">
</head>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main itemid="http://www.example.com/article-listing/#ItemList" itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListOrderAscending">
<meta itemprop="numberOfItems" content="6">
<meta itemprop="sortingValue" content="date">
<h1 itemprop="name">News</h1>
<ol start="4">
<li itemid="#ListItem-4" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/april">[...]</a>
</span>
<link itemprop="previousItem" href="#ListItem-3">
<link itemprop="nextItem" href="#ListItem-5">
</li>
<li itemid="#ListItem-5" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/may">[...]</a>
</span>
<link itemprop="previousItem" href="#ListItem-4">
<link itemprop="nextItem" href="#ListItem-6">
</li>
<li itemid="#ListItem-6" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="item" itemscope itemtype="http://schema.org/Article">
<a itemprop="url" href="https://example.com/article/june">[...]</a>
</span>
<link itemprop="previousItem" href="#ListItem-5">
<link itemprop="nextItem" href="http://schema.org/False">
</li>
</ol>
</main>
</body>
</html>
Possible solutions for expressing Paginated WebPages
WebPage or Collection properties
- ? introduce previousPart > IRI
- ? introduce nextPart > IRI
Note: Downside to the 'previous/nextPart' being properties of WebPage is that once all multi-page graphs get merged into one, the 'previous/nextPart' properties have become obsolete. Creating the same issue as it did for ItemList and why ListItem was needed.
Maybe schema.org/Collection could be a solution for Webpage as ListItem is for ItemList, eg:
- ItemList > itemListElement > ListItem > nextItem > IRI
- WebPage > isPartOf > Collection > nextPart > IRI
Paginated CollectionPage Examples
A paginated CollectionPage (without @itemid - Fails)
<!-- 1st page of a paginated CollectionPage (which has an unordered ItemList) -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/category/">
<link rel="next" href="http://www.example.com/category/page/2/">
</head>
<!-- Without @itemid there's no way of indicating each CollectionPage is a piece of a bigger CollectionPage -->
<body itemscope itemtype="http://schema.org/CollectionPage">
<!-- Without @itemid there's no way of indicating each ItemList is a piece of a bigger ItemList -->
<main itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListUnordered">
<meta itemprop="numberOfItems" content="6">
<h1 itemprop="name">Products</h1>
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</main>
</body>
</html>
<!-- 2nd page of a paginated CollectionPage (which has an unordered ItemList) -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/category/2/">
<link rel="prev" href="http://www.example.com/category/">
</head>
<body itemscope itemtype="http://schema.org/CollectionPage">
<main itemscope itemtype="http://schema.org/ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListUnordered">
<meta itemprop="numberOfItems" content="6">
<h1 itemprop="name">Products</h1>
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</main>
</body>
</html>
A paginated CollectionPage (using @itemid - Succeeds)
<!-- 1st page of a paginated CollectionPage (which has an unordered ItemList) -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/category/">
<link rel="next" href="http://www.example.com/category/page/2/">
</head>
<body itemid="http://www.example.com/category/" itemscope itemtype="http://schema.org/CollectionPage">
<link itemprop="previousPart" href="http://schema.org/False">
<link itemprop="nextPart" href="http://www.example.com/category/page/2/">
<main itemid="http://www.example.com/category/#ItemList" itemscope itemtype="http://schema.org/ItemList">
<link itemprop="previousPart" href="http://schema.org/False">
<link itemprop="nextPart" href="http://www.example.com/category/page/2/#ItemList">
<link itemprop="itemListOrder" href="http://schema.org/ItemListUnordered">
<meta itemprop="numberOfItems" content="6">
<h1 itemprop="name">Products</h1>
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</main>
</body>
</html>
<!-- 2nd page of a paginated CollectionPage (which has an unordered ItemList) -->
<html>
<head>
<link rel="canonical" href="http://www.example.com/category/2/">
<link rel="prev" href="http://www.example.com/category/">
</head>
<body itemid="http://www.example.com/category/page/2/" itemscope itemtype="http://schema.org/CollectionPage">
<link itemprop="previousPart" href="http://www.example.com/category/">
<link itemprop="nextPart" href="http://schema.org/False">
<main itemid="#ItemList" itemscope itemtype="http://schema.org/ItemList">
<link itemprop="previousPart" href="http://www.example.com/category/page/#ItemList">
<link itemprop="nextPart" href="http://schema.org/False">
<link itemprop="itemListOrder" href="http://schema.org/ItemListUnordered">
<meta itemprop="numberOfItems" content="6">
<h1 itemprop="name">Products</h1>
<ul>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
<li itemprop="itemListElement" itemscope itemtype="http://schema.org/Product">
[...]
</li>
</ul>
</main>
</body>
</html>