Fix errors in JSON-LD output

refs #6534

- don't output publisher for the 'People' type on the author page
- change publisher to a full 'Organisation' for the 'Article' type on posts

Note:
Google's structured data validator also wants image & publisher.logo inside of Article to be full 'ImageObject's.
Currently, it output's an error for them: 'The attribute itemtype has an invalid value.'
However, the spec on Schema.org says a url is valid: https://schema.org/Article,
which is slightly different to Google's spec here: https://developers.google.com/structured-data/rich-snippets/articles#article_markup_properties

Ideally, we would output a full 'ImageObject', however we don't currently have the width & height info required.
Therefore, I think what we have is valid strictly speaking, but we should aim to fix this when we have better image tools.
This commit is contained in:
Hannah Wolfe 2016-05-13 14:09:32 +02:00
parent 59e5e10e85
commit c4d3bd7cd2
4 changed files with 34 additions and 12 deletions

View File

@ -41,6 +41,9 @@ function getMetaData(data, root) {
blog: blog
};
metaData.blog.logo = metaData.blog.logo ?
config.urlFor('image', {image: metaData.blog.logo}, true) : config.urlFor({relativeUrl: '/ghost/img/ghosticon.jpg'}, {}, true);
// TODO: cleanup these if statements
if (data.post && data.post.html) {
metaData.excerpt = getExcerpt(data.post.html, {words: 50});

View File

@ -51,7 +51,11 @@ function getPostSchema(metaData, data) {
schema = {
'@context': 'http://schema.org',
'@type': 'Article',
publisher: metaData.blog.title,
publisher: {
'@type': 'Organization',
name: escapeExpression(metaData.blog.title),
logo: metaData.blog.logo || null
},
author: {
'@type': 'Person',
name: escapeExpression(data.post.author.name),
@ -110,7 +114,6 @@ function getAuthorSchema(metaData, data) {
'@context': 'http://schema.org',
'@type': 'Person',
sameAs: trimSameAs(data, 'author'),
publisher: escapeExpression(metaData.blog.title),
name: escapeExpression(data.author.name),
url: metaData.authorUrl,
image: metaData.coverImage,

View File

@ -6,7 +6,8 @@ describe('getSchema', function () {
it('should return post schema if context starts with post', function () {
var metadata = {
blog: {
title: 'Blog Title'
title: 'Blog Title',
logo: 'http://mysite.com/author/image/url/logo.jpg'
},
authorImage: 'http://mysite.com/author/image/url/me.jpg',
authorFacebook: 'https://facebook.com/testuser',
@ -53,7 +54,11 @@ describe('getSchema', function () {
headline: 'Post Title',
image: 'http://mysite.com/content/image/mypostcoverimage.jpg',
keywords: 'one, two, tag',
publisher: 'Blog Title',
publisher: {
'@type': 'Organization',
name: 'Blog Title',
logo: 'http://mysite.com/author/image/url/logo.jpg'
},
url: 'http://mysite.com/post/my-post-slug/'
});
});
@ -100,7 +105,11 @@ describe('getSchema', function () {
datePublished: '2015-12-25T05:35:01.234Z',
description: 'Post meta description',
headline: 'Post Title',
publisher: 'Blog Title',
publisher: {
'@type': 'Organization',
name: 'Blog Title',
logo: null
},
url: 'http://mysite.com/post/my-post-slug/'
});
});
@ -175,7 +184,6 @@ describe('getSchema', function () {
'@type': 'Person',
description: 'This is the author description!',
name: 'Author Name',
publisher: 'Blog Title',
sameAs: [
'http://myblogsite.com/',
'https://twitter.com/testuser'

View File

@ -155,7 +155,9 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/<script type=\"application\/ld\+json\">/);
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Article"/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"publisher": {/);
rendered.string.should.match(/"@type": "Organization"/);
rendered.string.should.match(/"name": "Ghost"/);
rendered.string.should.match(/"url": "http:\/\/testurl.com\/about\/"/);
rendered.string.should.match(/"sameAs": \[\n "http:\/\/authorwebsite.com",\n "https:\/\/www.facebook.com\/testuser",\n "https:\/\/twitter.com\/testuser"\n \]/);
rendered.string.should.match(/"image": "http:\/\/testurl.com\/content\/images\/test-image-about.png"/);
@ -327,7 +329,6 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Person"/);
rendered.string.should.match(/"sameAs": \[\n "http:\/\/authorwebsite.com",\n "https:\/\/www.facebook.com\/testuser",\n "https:\/\/twitter.com\/testuser"\n \]/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"url": "http:\/\/testurl.com\/author\/AuthorName\/"/);
rendered.string.should.match(/"image": "http:\/\/testurl.com\/content\/images\/author-cover-image.png"/);
rendered.string.should.match(/"name": "Author name"/);
@ -427,7 +428,9 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/<meta name="twitter:creator" content="@testuser" \/>/);
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Article"/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"publisher": {/);
rendered.string.should.match(/"@type": "Organization"/);
rendered.string.should.match(/"name": "Ghost"/);
rendered.string.should.match(/"author": {/);
rendered.string.should.match(/"@type": "Person"/);
rendered.string.should.match(/"name": "Author name"/);
@ -504,7 +507,9 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/<script type=\"application\/ld\+json\">/);
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Article"/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"publisher": {/);
rendered.string.should.match(/"@type": "Organization"/);
rendered.string.should.match(/"name": "Ghost"/);
rendered.string.should.match(/"author": {/);
rendered.string.should.match(/"@type": "Person"/);
rendered.string.should.match(/"name": "Author name"/);
@ -575,7 +580,8 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/<script type=\"application\/ld\+json\">/);
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Article"/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"publisher": {/);
rendered.string.should.match(/"@type": "Organization"/);
rendered.string.should.match(/"author": {/);
rendered.string.should.match(/"@type": "Person"/);
rendered.string.should.match(/"name": "Author name"/);
@ -649,7 +655,9 @@ describe('{{ghost_head}} helper', function () {
rendered.string.should.match(/<script type=\"application\/ld\+json\">/);
rendered.string.should.match(/"@context": "http:\/\/schema.org"/);
rendered.string.should.match(/"@type": "Article"/);
rendered.string.should.match(/"publisher": "Ghost"/);
rendered.string.should.match(/"publisher": {/);
rendered.string.should.match(/"@type": "Organization"/);
rendered.string.should.match(/"name": "Ghost"/);
rendered.string.should.match(/"author": {/);
rendered.string.should.match(/"@type": "Person"/);
rendered.string.should.match(/"name": "Author name"/);