Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tags to JSON metadata #151

Merged
merged 37 commits into from Apr 6, 2017
Merged

Add tags to JSON metadata #151

merged 37 commits into from Apr 6, 2017

Conversation

aav7fl
Copy link
Contributor

@aav7fl aav7fl commented Jan 16, 2017

  • Add Feature
  • Add Docs
  • Add Tests

This is just to add in the Author field (which is helpful for blog posts/articles when searching for articles + rich text formatting from Google).

This also allows the Google Structured Data Testing Tool to pass without any errors for the type BlogPosting (now there are only warnings).

BlogPosting was chosen instead of WebSite because of Google will treat this content type differently when it displays Rich Cards.

Fixes missing author and name in blogPosting types with organization.
@@ -221,6 +228,9 @@
{% if seo_site_logo %}
"publisher": {
"@type": "Organization",
{% if seo_author_name %}
"Name": {{ seo_author_name | jsonify }},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It should. I'll change that shortly.

@pathawks
Copy link
Member

Does this fix #96?

/cc: @renshuki

Copy link
Contributor Author

@aav7fl aav7fl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed casing.

@aav7fl
Copy link
Contributor Author

aav7fl commented Jan 16, 2017

It does not fix #96. I can get around to that soon. It's something I would like to add as well. This only adds the proper JSON tags to pass the errors (but not the warnings).

@pathawks
Copy link
Member

I can get around to that soon. It's something I would like to add as well.

I was just curious. We've got a PR for that in #103 👍

@aav7fl aav7fl changed the title Add Author/Name tags in JSON metadata Add tags to JSON metadata Jan 17, 2017
This adds the rest of the JSON fields to pass all errors and blog postings.

- Adds page.image.url for the image url. (Will default to image if not present). 
- Add page.image.height and page.image.width for an image object (Will default back to image url if not present). 
- Add dateModified (will capture from yaml if present, if not it will use datePublished)
  - (I feel there should be a manual option for this as I sometimes save parts of my blog that shouldn't update the modified field, but still 
change the file timestamp).

This should create JSON that will pass all warnings/strong recommendations/errors from [Google's Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool).
Copy link
Contributor Author

@aav7fl aav7fl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proposing a few changes following the already present code styling. I would love to have these feature implemented as they clear all warnings/errors in the JSON; leaving it properly formatted.

@@ -89,7 +92,7 @@
{% endif %}

{% if page.image %}
{% assign seo_page_image = page.image.path | default: page.image.facebook | default: page.image %}
{% assign seo_page_image = page.image.path | default: page.image.url | default: page.image.facebook | default: page.image %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow for page.image.url here, else there will be a mess of if interpreting the yaml object when it encounters this unknown yaml field.

@@ -62,6 +62,9 @@
{% endif %}
{% endif %}
{% assign seo_author_twitter = seo_author_twitter | replace:"@","" %}
{% if seo_author.name %}
{% assign seo_author_name = seo_author.name %}
{% endif %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Author Name

{% if seo_author_name %}
"author": {{ seo_author_name | jsonify }},
{% endif %}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Author Name

},
{% else %}
"image": {{ seo_page_image | jsonify }},
{% endif %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create image object (as it needs). Height and width are probably required now for some future thinking. Think AMP where they require this information in the markup.

Will default back if either no width/height are present, or if no image url is present.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a future iteration, it'd be great if we could calculate the height and width for local images (assuming we can do so safely without adding something like imagemagic).

{% elseif page.date %}
"dateModified": {{ page.date | date_to_xmlschema | jsonify }},
{% endif %}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a date modified field. Useful when wanting to control this manually. Like when I make a change to the markup file, but I want to override the timestamp given.

Will default to page.date if never "modified". Will not exist if neither field present.

{% if seo_description %}
"description": {{ seo_description | jsonify }},
{% endif %}

{% if seo_site_logo %}
"publisher": {
"@type": "Organization",
{% if seo_author_name %}
"name": {{ seo_author_name | jsonify }},
{% endif %}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Author Name.

"@id": {{ page.url | replace:'/index.html','/' | absolute_url | jsonify }}
},
{% endif %}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add mainEntityOfPage when BlogPosting type is chosen.
Better explained in this StackOverflow post.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried read that post 6 six times, studied Schema.org and still couldn't understand this until I saw your example. 😂 Given Schema.org says all webpages are implicitly of Type WebPage (if not defined) this makes sense. Given this tag also applies to "CreativeWork", it would be useful to add that here while we're making this change as it will help with Structured Data validation for that common type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've added this to my local branch, along with a test.

@aav7fl
Copy link
Contributor Author

aav7fl commented Jan 17, 2017

Whoops. Wrong language. Left an 'e' in my elsif.
Fixed.

Well.... looks like I added an 'e'. Whoops.
Copy link
Contributor Author

@aav7fl aav7fl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed a silly letter ('e').

Adds documentation on new image behavior, dateModified, and author field.
@aav7fl
Copy link
Contributor Author

aav7fl commented Jan 17, 2017

Added updated documentation for changes. Working on tests next. Also noticed a small change I needed to make. It will be in a new pull eventually.

@aav7fl
Copy link
Contributor Author

aav7fl commented Jan 18, 2017

This makes changes to the JSON-LD information. Fixes warning/errors reported by Google Structured Data Testing Tool.

Travis didn't like my date/dateModified tests because of time-zone issues. I had to pull those specific ones. Fixed up the rubocop styling.

Looks like everything is good for an inspection.

{% if seo_author %}
<meta name="author" content="{{ seo_author }}" />
{% endif %}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in content of PR #103 along with tests (because it made sense to add the author meta field when I was already doing it in the JSON).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still 👎 on this with out a clear use case

Copy link
Member

@DirtyF DirtyF Jan 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meta author is not recognized by Google (https://support.google.com/webmasters/answer/79812?hl=en) et was deprecated in favor of Rich Snippets. What is the intent in adding this if it is ignored by search engines?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's ignored by Google but not by Facebook. The purpose of this change is to show up the author name of an article when you share it on Facebook. If the meta name="author" is not set the author name will not be displayed when you share a jekyll blog article on Facebook (Issue #96). If the author of the article has a Facebook account you can use the meta property="article:author" which his ID / profile URL instead but it's not always the case.

If someone have any other suggestion to resolve this problem it would be greatly appreciated 😃

Copy link
Contributor Author

@aav7fl aav7fl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write explanations for code changes.

{% if seo_author %}
<meta name="author" content="{{ seo_author }}" />
{% endif %}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still 👎 on this with out a clear use case

@aav7fl
Copy link
Contributor Author

aav7fl commented Jan 25, 2017

Ok. Yea. I guess I'm stuck in the past. I can't find any good documentation that clearly states that it is used anymore. Even for markup. Most places with use JSON-LD or OG tags. Removing author meta tag & test.

@aav7fl
Copy link
Contributor Author

aav7fl commented Apr 3, 2017

@benbalter @jhabdas Removed image changes from this PR. #174 is handling image changes. Should be more straight forward if it's ok having these changes in a single PR. If not, I can continue pulling these out, but they seem to go together.

Additions in this PR exist to appease Google Structured Data Testing Tool.

README.md Outdated
@@ -78,6 +78,8 @@ The SEO tag will respect any of the following if included in your site's `_confi
* `social` - For [specifying social profiles](https://developers.google.com/structured-data/customize/social-profiles). The following properties are available:
* `name` - If the user or organization name differs from the site's name
* `links` - An array of links to social media profiles.
* `date_modified` - (YYYY-MM-DD hh:mm) A manual override for the `dateModified` field in the JSON-LD output. This field will take **first priority** for the `dateModified` output. This is useful when the file timestamp does not match the true time that the content was modified.
Copy link

@ghost ghost Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, I feel we should mention what's being overridden. Also, given Jekyll supports use of ISO 8601 dates, perhaps it's best if we left any formatting out of the example so as not to lead implementations (which might otherwise choose to include the Timezone offset). Also, and now I'm being persnickety, it would be great if this and the next bullet could be condensed into one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On it.

Copy link
Contributor Author

@aav7fl aav7fl Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this:

  • date_modified - Manually specify the dateModified field in the JSON-LD output to override Jekyll's own dateModified. This field will take first priority for the dateModified JSON-LD output. This is useful when the file timestamp does not match the true time that the content was modified. A user may also install Last Modified At which will offer an alternative way of providing for the dateModified field.

@@ -237,11 +237,49 @@
end

context "with absolute site.logo" do
let(:site) { make_site("logo" => "http://cdn.example.invalid/logo.png", "url" => "http://example.invalid") }
let(:site) { make_site("logo" => "http://cdn.example.invalid/logo.png", "url" => "http://example.invalid", "author" => "Mr. Foo") }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like this should be broken into a different context so we're not conflating test logic between existing and new features. Does that make sense?

Copy link
Contributor Author

@aav7fl aav7fl Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess. But it feels like there are unnecessary LOC when the actual test is given with context in line 246.

Mostly because I remember a talk about refactoring to shrink things down; wondered if this would be part of that example.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll defer this one. I don't have the experience with tests to make a good judgement here. Just wafting around code smell. 💨

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we'll save it for when we refactor the tests to bring our coverage back up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand the connection between author and logo.
If we're adding something new, we should add new tests, not modify existing tests.

@ghost
Copy link

ghost commented Apr 3, 2017

This is looking great! Much easier to grok now. Just one small question/comment about the test logic and I'm a :shipit: personally.

@aav7fl
Copy link
Contributor Author

aav7fl commented Apr 3, 2017

Alright. It should be ready now.

Copy link
Member

@pathawks pathawks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve requested a few clarifications.

Overall, I’m excited for this and think it will improve our plugin 👍

@@ -237,11 +237,49 @@
end

context "with absolute site.logo" do
let(:site) { make_site("logo" => "http://cdn.example.invalid/logo.png", "url" => "http://example.invalid") }
let(:site) { make_site("logo" => "http://cdn.example.invalid/logo.png", "url" => "http://example.invalid", "author" => "Mr. Foo") }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand the connection between author and logo.
If we're adding something new, we should add new tests, not modify existing tests.

end

context "with page author" do
let(:site) { make_site("logo" => "/logo.png", "url" => "http://example.invalid") }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary here? Context is "with page author" says nothing about logo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. The lovely Google Structured Data Testing Tool complains when the publisher object (required to pass..) does not have a name. For the purposes of a blog (What Jekyll is), the name is the author.

http://i.imgur.com/xnu0JG7.png

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I was referring to the logo bits. Is that necessary here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of. I think I understand what you are asking;

If I have the publisher object

"publisher": {"@type": "Organization",
"name": "Kyle Niewiada",
"logo": {"@type": "ImageObject",
"url": "https://www.kyleniewiada.org/assets/img/logo.png"}},

I need to have both logo and author together. If I remove just the author, it's an error. If I remove just the logo, it's an error. So they need to be both implemented together. That means when I make the site in the test, I need the logo and the author together.

@@ -65,6 +65,10 @@
{% assign seo_author_twitter = seo_author_twitter | replace:"@","" %}
{% endif %}

{% if page.date_modified or page.last_modified_at or page.date %}
{% assign seo_date_modified = page.seo.date_modified | default: page.last_modified_at | default: page.date %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if we want to set seo_date_modified at all if all we have is page.date. What is the motivation?

Copy link
Contributor Author

@aav7fl aav7fl Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google will complain if there is no "dateModified", even if it is the exact same.

The dateModified field is recommended. Please provide a value if available.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would seem that if date_modified or similar is not set, we do not have a value available.

Copy link
Contributor Author

@aav7fl aav7fl Apr 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would hope so, but the warning from their tool gives no indication if missing this field is a 'include it if you use it, ignore it if you don't", I can leave it out. But I wanted to remove all warnings in case it had an impact. I would like to keep it because of the warning, but I will take it out if you request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addition: When I check out websites that already use JSON-LD, I note that they use dateModified even if it is the same as the publish date.

view-source:http://www.theverge.com/2017/4/3/15123170/bmw-520i-2017-5-series-review

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between this plugin and The Verge is that they control every aspect of their site, and this plugin has to serve a more general use case. We have no way of knowing that a document’s date is the same as (or even a good approximation of) its updated date. I assert that the absence of data is better than made up daya.

When you say “Google will complain,” do you mean validation fails, or Google complains loudly? If validation fails, I guess we'll do what's needed to fix that. If it's merely a warning, that seems like A Good Thing! Publishers should be made aware that including modified information is an important thing to do, and we can't just hand-wave over that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's merely a warning.

That is a valid point that the document's date is not the same as its upload date.

I will pull that last default snippet to exclude the page.date.

Copy link
Collaborator

@benbalter benbalter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Thanks for working through the feedback.

@benbalter benbalter mentioned this pull request Apr 4, 2017
@aav7fl
Copy link
Contributor Author

aav7fl commented Apr 4, 2017

Thanks for working with me on this!

@aav7fl
Copy link
Contributor Author

aav7fl commented Apr 4, 2017

@pathawks Date handling complete. Thanks for pointing out that the file date may not properly represent the publish date; and all of the other valid points that I missed along the way!

@benbalter
Copy link
Collaborator

Think this can be merged now?

@aav7fl
Copy link
Contributor Author

aav7fl commented Apr 6, 2017

It looks good to me. 😃

@benbalter benbalter merged commit 11cd72c into jekyll:master Apr 6, 2017
@pathawks
Copy link
Member

pathawks commented Apr 6, 2017

@benbalter Yes, LGTM. Sorry; I didn't realize that I was the one holding things up.

@aav7fl Thanks for making those changes, and for your patience. This will be a great addition to the plugin 👍🎉

@benbalter
Copy link
Collaborator

Thanks @aav7fl! 🥇 🌵 🍰

@benbalter
Copy link
Collaborator

Going to get a new release out right now with this in it.

@ghost
Copy link

ghost commented Apr 6, 2017

\o/

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants