はてなブログに動的にschema.orgのArticleを埋め込む
はてなブログに動的にschema.orgのArticleを埋め込む
はてなブログにJavaScriptで動的にschema.orgのWebSiteを埋め込むメモ.形式は,JSON-LDである.
以下の記事で,
一般的なwebサイトにschema.orgのArticle
を埋め込むスクリプトを書いたので,今回ははてなブログ用のものを書く.
はてなブログ記事にデフォで設定されている構造化データ
Googleの構造化データテストツールをしてみるとわかるが,WebSite
同様,記事にも構造化データ(形式はmicrodata)が設定してある.
プロパティの'name'と'image'は設定されているが他は設定されていない.
- name
- image
- author(必須)
- datePublished(必須)
- headline(必須)
- publisher(必須)
- dateModified(推奨)
- mainEntityOfPage(推奨)
注意
はてなブログでは,すでに schema.orgのタイプArticle
が設定してある.なので,今回のスクリプトを埋め込むと,microdataでデフォで設定されたArticle
とJSON-LDのArticle
が混在するので注意.
schma.orgのArticle
について
以下の記事で解説している.
JavaScriptで生成した構造化データをGoogleが認識するのか
以下の記事で解説
はてなブログ記事のメタ情報
動的にJSON-LDを生成するために, はてなブログ記事ページのhtmlから各メタ情報を抽出する. ソースから確認できる.
- ブログ名:
<html .. data-blog-name="はしくれエンジニアもどきのメモ" ...>
- 記事名
<h1 class="entry-title"> <a href="http://..." class="entry-title-link bookmark">はてなブログに動的にschema.orgのWebSiteを埋め込む</a> </h1>
- 記事のURL
<a href="http://cartman0.hatenablog.com/entry/2017/11/09/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0%E3%81%AB%E5%8B%95%E7%9A%84%E3%81%ABschema.org%E3%81%AEWebSite%E3%82%92%E5%9F%8B%E3%82%81%E8%BE%BC%E3%82%80" class="entry-title-link bookmark">はてなブログに動的にschema.orgのWebSiteを埋め込む</a>
- 記事の画像
<meta itemprop="image" content="https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png"/>
- 記事の説明
<meta name="description" content="はてなブログに動的にschema.orgのWebSiteを埋め込む はてなブログにJavaScriptで動的にschema.orgのWebSiteを埋め込むメモ. …" />
- 記事の発行日
<time pubdate datetime="2017-11-09T13:54:29Z" title="2017-11-09T13:54:29Z">
- 記事の最終更新日
はてなブログではデフォで取得できないので,
独自に設定したものを取得する.
詳細は,以下の記事に書いている.
cartman0.hatenablog.com
(JavaScript実行後に取得)
<span>(LastModified: <time itemprop="dateModified" title="2017-11-09" datetime="2017-11-09">2017-11-09</time>)</span>
- charset
<meta charset="utf-8"/>
- 利用している言語
<html ... data-avail-langs="ja en" ... >
- 記事のカテゴリ
<div class="entry-categories categories"> <a href="http://cartman0.hatenablog.com/archive/category/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0" class="entry-category-link category-はてなブログ">はてなブログ</a> <a href="http://cartman0.hatenablog.com/archive/category/StructuredData" class="entry-category-link category-StructuredData">StructuredData</a> <a href="http://cartman0.hatenablog.com/archive/category/schema.org" class="entry-category-link category-schema.org">schema.org</a> </div>
-
ブログ投稿者のニックネーム
(JavaScript実行後)
<span data-load-nickname="1" data-user-name="cartman0"><span class="user-name-nickname">Cartman</span> <span class="user-name-paren">(</span><span class="user-name-hatena-id">id:cartman0</span><span class="user-name-paren">)</span></span>
-
ブログ投稿者のアイコン(プロフィールアイコン)
<a href="http://cartman0.hatenablog.com/about" class="profile-icon-link"> <img src="https://cdn1.www.st-hatena.com/users/ca/cartman0/profile.gif?1428245168" alt="id:cartman0" class="profile-icon" /> </a>
- ブログ名
<html .. data-blog-name="はしくれエンジニアもどきのメモ" ...>
- ブログのURL
<html ... data-blog-uri="http://cartman0.hatenablog.com/" ...
- ブログのロゴ画像
今回は,ブログのロゴ画像は直接指定
https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png"
JavaScriptコード
今回,Article
に設定するプロパティは,以下とする.
name
: 記事名url
: 記事のURLmainEntityOfPage
:Article
は,記事ページのメインコンテンツより,記事のURLを指定description
: 記事の説明image
:記事の画像thumbnailUrl
: 記事用のサムネイル画像(今回はimage
と同じ)keyword
:記事のキーワード(今回はカテゴリ)charset
: htmlのcharset(つまりutf-8)- "fileFormat": htmlページなので"text/html"
datePublished
: 記事発行日dateModified
: 記事最終更新日(今回は事前に独自で設定したものを使用)inLanguage
:利用言語genre
: ジャンル(今回は記事のカテゴリを指定)author
: 記事の著者(ブログ発信者の名前とプロフィールアイコン,メールアドレス,アドレス)publisher
: 記事の発行者,今回はOrganizationとしてブログを指定(ブログのタイトル,URL,ロゴ画像を指定).isAccessibleForFree
: 無料でアクセスできるのでtruecopyrightHolder
: 記事の著作権者(今回はauthor
と同じ.)copyrightYear
: 著作権の年(今回はdatePublished
の年を指定)sponsor
: 記事のスポンサー(今回は試しにGoogleAdsenseを指定)
<!-- Article JSON-LD --> <script type="text/javascript"> (function(){ function create_schemaorg_article(){ function try_return(f){ try{ return f.call(); }catch(e){ } } /* setting */ var name = undefined || try_return(function(){return document.querySelector(".entry-title-link").innerText;}); var headline = undefined || name.substr(0,109); // [0, 110]まで var uri = undefined|| try_return(function(){return document.querySelector(".entry-title-link").getAttribute("href") || document.querySelector('[property="og:url"]').getAttribute("content");}); var image = undefined || try_return(function(){return document.querySelector('[itemprop="image"]').getAttribute("content");}); var description = undefined || try_return(function(){return document.querySelector('[name="description"]').getAttribute("content");}); var datePublished = undefined || try_return(function(){return document.querySelector('[pubdate]').getAttribute("datetime");}); var dateModified = undefined || try_return(function(){return document.querySelector("time[itemprop]").getAttribute("datetime");}); var person_name = "nabana" || try_return(function(){return document.querySelector('.user-name-nickname').innerText;}); var person_image = undefined || try_return(function(){return document.querySelector('.profile-icon').getAttribute("src");}); var person = { "@type": "Person", "address": "Japan", "email": "@mail.com" }; if(person_name) person["name"] = person_name; if(person_image) person["image"] = person_image; var publisher_name = undefined || try_return(function(){return document.querySelector("[data-blog-name]").getAttribute("data-blog-name");}); var publisher_url = undefined || try_return(function(){return document.querySelector("[data-blog-uri]").getAttribute("data-blog-uri");}); var publisher_logo_image_url = "https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png"; var publisher = { "@type": "Organization" }; if(publisher_name) publisher["name"] = publisher_name; if(publisher_url) publisher["url"] = publisher_url; if(publisher_logo_image_url) publisher["logo"] = { "@type": "ImageObject", "url": publisher_logo_image_url }; var keywords = undefined || try_return(function(){ var arr = []; for(var e of document.querySelectorAll(".entry-category-link")){ arr.push(e.innerText); } return arr; }); var genre = keywords; var charset = undefined || try_return(function(){return document.querySelector('[charset]').getAttribute("charset");}); var copyrightYear = undefined || try_return(function(){return datePublished.match(/^(\d{4})-/)[1];}); var inLanguage = undefined || try_return(function(){return document.querySelector('[data-avail-langs]').getAttribute("data-avail-langs").split(" ");}); var sponsor_organization = { "@type": "Organization", "name": "GoogleAdsense" }; var script = document.createElement("script"); script.setAttribute("type", "application/ld+json"); // create article_json var article_obj = { "@context": "http://schema.org", "@type": "Article", "fileFormat": "text/html", "isAccessibleForFree": true, }; if(name) article_obj["name"] = name; if(headline) article_obj["headline"] = headline; if(uri) article_obj["url"] = uri; if(uri) article_obj["mainEntityOfPage"] = {"@type": "WebPage","@id": uri}; if(image) article_obj["image"] = image; if(image) article_obj["thumbnailUrl"] = image; if(description) article_obj["description"] = description; if(keywords) article_obj["keywords"] = keywords; if(charset) article_obj["encoding"] = {"@type": "MediaObject","encodingFormat": charset}; if(person) article_obj["author"] = person; if(publisher) article_obj["publisher"] = publisher; if(person) article_obj["copyrightHolder"] = person; if(copyrightYear) article_obj["copyrightYear"] = copyrightYear; if(datePublished) article_obj["datePublished"] = datePublished; if(dateModified) article_obj["dateModified"] = dateModified; if(inLanguage) article_obj["inLanguage"] = inLanguage; if(genre) article_obj["genre"] = genre; if(sponsor_organization) article_obj["sponsor"] = sponsor_organization; script.innerText = JSON.stringify(article_obj); document.querySelector("article").appendChild(script); } window.addEventListener("load", create_schemaorg_article, false) }()); </script>
上のスクリプトをはてなブログの「記事上」または「記事下」に埋め込んで,記事ページを「Googleの構造化データテストツール」にかけると以下のように認識される.