Back in October last year I blogged about the schema markup I was using on this site. This was a mistake because I simply hadn’t researched schema enough at the time. I now have and I believe I have a much better idea of how the various schema on a web page should fit together.

One of the main things I’ve discovered is that schema should be linked together as much as possible. Part of its remit is to define the relationships between the elements of a web page.

What I’ve ended up with is something that can be diagrammatically represented as follows:

My schema markup diagram.
How I mark-up schema on my blog.

I make the distinction between the physical structure of a website and its logical structure.

Physical Structure

The physical structure is fairly simple. At the top level you have a WebSite and every page on that website is a WebPage. They way I set up that relationship is via isPartOf as follows:

{
    "@context": "https://schema.org",
    "@type": “WebSite”,
    "@id" : "https://gordonansell.com"
    "name": "Gordy's Discourse",
    .
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “WebPage”,
    "@id" : "https://gordonansell.com/page-slug"
    "name": "Title of whatever webpage.",
    "isPartOf": { "@id": "https://gordonansell.com" }
    .
    .
    .
}

Most parts of the logical structure ultimately link back to a WebPage (with only Blog linking back directly to the WebSite, as we'll see).

Logical Structure

On this site I have two distinct types of content: blog posts, which are the dated posts that form the majority of the site (it is after all primarily a blog), and then I have the content that makes up my ‘about’ page, my ‘contact’ page and similar non-blog content.

The Blog and Its Content

The Blog is a part of the WebSite (but not the whole of the website) so it gets related via the isPartOf relationship.

Each single BlogPosting is a part of the Blog, and hence gets related to it via isPartOf, and it also forms the main element of the physical WebPage (the other elements being headers, footers, menus etc.), so it relates to that as the mainContentOfPage.

So the start of the logical side of things looks like this:

{
    "@context": "https://schema.org",
    "@type": “Blog”,
    "@id" : "https://gordonansell.com/#blog"
    "name": "Gordy's Discourse Blog",
    "isPartOf": { "@id": "https://gordonansell.com" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “BlogPosting”,
    "@id" : "https://gordonansell.com/page-slug/#blogpost"
    "name": "Title of whatever blog post.",
    "isPartOf": { "@id": "https://gordonansell.com/#blog" }
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug" }
    .
    .
}

Sub-Logic

There may also be sub-logic elements. You might, for example, be writing a Review of a Product and need to define how those schema elements relate to your BlogPosting.

The way I do it is to define the Review as the ‘main entity’ of the BlogPosting , and thus use mainEntityOfPage, and the Product as the itemReviewed in the Review. So the sub-logic would look like this:

{
    "@context": "https://schema.org",
    "@type": “Review”,
    "name": "Gordy's Review Title",
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug/#blogpost" }
    "itemReviewed": { "@id": "https://gordonansell.com/page-slug/#product" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “Product”,
    "@id" : "https://gordonansell.com/page-slug/#product"
    "name": "Name of product reviewed.",
    .
    .
}

Technically you could make the Review the mainEntityOfPage for the physical WebPage and skip the BlogPosting altogether, but I like to keep it to a standard (because I obviously have blog posts that are not reviews). It also covers me if I go off at a tangent during a review (which I can sometimes); the review is undoubtedly the ‘main entity’ of my blog post in this case but it may not always be the only entity in the blog post.

Non-Blog Content

The pages that are not blog posts are defined via Article schema on my site and are linked directly to the WebPage as its main content:

{
    "@context": "https://schema.org",
    "@type": “Article”,
    "name": "Title of whatever article.",
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug" }
    .
    .
}

The Whole Thing

Putting all the code together, we get this for a blog page with a review:

{
    "@context": "https://schema.org",
    "@type": “WebSite”,
    "@id" : "https://gordonansell.com"
    "name": "Gordy's Discourse",
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “WebPage”,
    "@id" : "https://gordonansell.com/page-slug"
    "name": "Title of whatever webpage.",
    "isPartOf": { "@id": "https://gordonansell.com" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “Blog”,
    "@id" : "https://gordonansell.com/#blog"
    "name": "Gordy's Discourse Blog",
    "isPartOf": { "@id": "https://gordonansell.com" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “BlogPosting”,
    "@id" : "https://gordonansell.com/page-slug/#blogpost"
    "name": "Title of whatever blog post.",
    "isPartOf": { "@id": "https://gordonansell.com/#blog" }
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “Review”,
    "name": "Gordy's Review Title",
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug/#blogpost" }
    "itemReviewed": { "@id": "https://gordonansell.com/page-slug/#product" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “Product”,
    "@id" : "https://gordonansell.com/page-slug/#product"
    "name": "Name of product reviewed.",
    .
    .
}

And this for a non-blog page:

{   
    "@context": "https://schema.org",
    "@type": “WebSite”,
    "@id" : "https://gordonansell.com"
    "name": "Gordy's Discourse",
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “WebPage”,
    "@id" : "https://gordonansell.com/page-slug"
    "name": "Title of whatever webpage.",
    "isPartOf": { "@id": "https://gordonansell.com" }
    .
    .
},
{
    "@context": "https://schema.org",
    "@type": “Article”,
    "name": "Title of whatever article.",
    "mainEntityOfPage": { "@id": "https://gordonansell.com/page-slug" }
    .
    .
}

This is of course just one way to do it. There are others but the important thing is to define the relationships between schema objects as well as the properties attributed to each schema object.

Additional Schema

I make use of the breadcrumbs element in WebPage to indicate the (simple) hierarchy of my site, which is another form of relationship. This is a simple example:

{
    "@context": "https://schema.org",
    "@type": “WebPage”,
    "@id" : "https://gordonansell.com/page-slug"
    "name": "Title of whatever webpage.",
    "isPartOf": { "@id": "https://gordonansell.com" },
    "breadcrumbs": {
        "@context": "https://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement":       
        [
            {
                "@context": "http://schema.org",
                "@type": "ListItem",
                "item": "https://gordonansell.com",
                "name": "Gordy's Discourse",
                "position": "1"
             },
             {
                "@context": "http://schema.org",
                "@type": "ListItem",
                "item": "https://gordonansell.com/my-blog-post",
                "name": "The title of my blog post.",
                "position": "2"
             }
        ]       
    }
    .
    .
}

I try to relate everything to something: images, videos, everything.

Considerations