はしくれエンジニアもどきのメモ

情報系技術・哲学・デザインなどの勉強メモ・備忘録です。

はてなブログに動的にschema.orgのWebSiteを埋め込む

はてなブログに動的にschema.orgのWebSiteを埋め込む

はてなブログJavaScriptで動的にschema.orgのWebSiteを埋め込むメモ.

以下の記事で,一般的なwebサイトにschema.orgWebSiteを埋め込むスクリプトを書いたので,今回ははてなブログ用のものを書く.

cartman0.hatenablog.com

はてなブログトップページにデフォで設定されている構造化データ

実は,Googleの構造化データテストツールをしてみるとわかるが,構造化データが設定してある.(JSON-LDでなくmicrodataを使用している)

  • Blog
  • Photogragh
  • ViewAction
  • hatom

注意

すでに shcma.orgのタイプBlogが設定してあるので, 今回のスクリプトを埋め込むとmicrodataでデフォで設定されたBlogJSON-LDのWebSiteが混在するので注意.

schma.orgのWebSiteについて

以下の記事で解説している.

cartman0.hatenablog.com

JavaScriptで生成した構造化データをGoogleが認識するのか

以下の記事で解説

cartman0.hatenablog.com

はてなブログトップのメタ情報

動的にJSON-LDを生成するために, はてなブログトップページのhtmlからメタ情報を取得する.

  • ブログ名:
    <html ..
    data-blog-name="はしくれエンジニアもどきのメモ"
    ...>
    
  • ブログ名
    <html ..
    data-blog-name="はしくれエンジニアもどきのメモ"
    ...>
    
  • ブログのURL
    <html ...
    data-blog-uri="http://cartman0.hatenablog.com/"
    ...
    
  • ブログの画像
    <meta itemprop="image" content="https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png"/>
    
  • ブログの説明
     <meta name="description" content="情報・IT・Web系技術・Englishについてのメモ・備忘録です。">
    
  • ブログのキーワード
     <meta name="keywords" content="エンジニア, engineer, 技術, Technology, ...">
    
  • charset
     <meta charset="utf-8"/>
    
  • ブログの最終更新日
    <div class="profile-activities">
            最終更新:
            <time datetime="2017-11-08T15:46:53Z" data-relative data-epoch="1510156013000" pubdate class="updated">2017-11-09 00:46</time>
    ...
    </div>
    
  • 利用している言語
    <html ...
    data-avail-langs="ja en"
    ...
    >
    
  • はてなブログの所属しているサークル
    <ul class="hatena-urllist circle-urllist">
    
           <li title="プログラミング" data-circle-id="11696248318754550880" data-circle-mtime="1510159726">
     <a href="http://hatenablog.com/g/11696248318754550880"><img class="circle-image" src="/images/circle/official-circle-icon/computers.gif" alt="プログラミング" title="プログラミング"></a>
     <a href="http://hatenablog.com/g/11696248318754550880">プログラミング</a>
    </li>
    
           <li title="インターネット" data-circle-id="11696248318754550876" data-circle-mtime="1510162357">
     <a href="http://hatenablog.com/g/11696248318754550876"><img class="circle-image" src="/images/circle/official-circle-icon/computers.gif" alt="インターネット" title="インターネット"></a>
     <a href="http://hatenablog.com/g/11696248318754550876">インターネット</a>
    </li>
    
           <li title="知識" data-circle-id="11696248318754550903" data-circle-mtime="1510207530">
     <a href="http://hatenablog.com/g/11696248318754550903"><img class="circle-image" src="/images/circle/official-circle-icon/learning-and-culture.gif" alt="知識" title="知識"></a>
     <a href="http://hatenablog.com/g/11696248318754550903">知識</a>
    </li>
    </ul>
    
  • ブログ投稿者のニックネーム (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>
    

JavaScriptコード

今回,WebSiteに設定するプロパティは,以下.

  • name: ブログ名
  • url: ブログのURL
  • mainEntityOfPageWebSiteは,ブログトップページのメインコンテンツより,ブログのURLを指定
  • description: ブログの説明
  • image:ブログの画像
  • thumbnailUrl: ブログ用のサムネイル画像(今回はimageと同じ)
  • keyword:ブログのキーワード
  • charset: htmlのcharset(つまりutf-8
  • "fileFormat": htmlページなので"text/html"
  • datePublished: はてなブログ開始日
  • dateModified: 更新日
  • inLanguage:利用言語
  • genre: ジャンル(今回は手入力+はてなブログに所属しているサークル名 ex.知識)
  • author: ブログの著者(ブログ発信者の名前とプロフィールアイコン,メールアドレス,アドレス)
  • publisher: ブログ発行者(今回はauthorと同じ)
  • isAccessibleForFree: 無料でアクセスできるのでtrue
  • copyrightHolder: ブログの著作権者(今回はauthorと同じ.)
  • copyrightYear: 著作権の年(今回はdatePublishedの年を指定)
  • sponsor: ブログのスポンサー(今回は試しにGoogleAdsenseを指定)
  • potentialAction: SearchActionを設定
<!-- website json-ld fetch だと動かない関数がある? -->
<script type="text/javascript">
(function(){
function create_schemaorg_website(){
function try_return(f){
    try{return f.call();}catch(e){}
}
/* setting */
var name = undefined || try_return(function(){return document.querySelector("[data-blog-name]").getAttribute("data-blog-name");});
var uri = undefined || try_return(function(){return document.querySelector("[data-blog-uri]").getAttribute("data-blog-uri");});
var search_uri = undefined || (uri ? uri + "search" : undefined);
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 keywords = undefined || try_return(function(){return document.querySelector('[name="keywords"]').getAttribute("content");});
var charset = undefined || try_return(function(){return document.querySelector('[charset]').getAttribute("charset");});
var datePublished = "2014-04-30";
var dateModified = undefined || try_return(function(){return document.querySelector('.profile-activities [datetime]').getAttribute("datetime");});
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 genre = ["Web", "Technology"];

var hatena_genre = undefined || try_return(function(){
    var arr = [];
    for(var e of document.querySelectorAll('[data-circle-id]')){
        arr.push(e.getAttribute("title"));
    }
    return arr;
});
if(hatena_genre && hatena_genre.length > 0) genre = genre.concat(hatena_genre);

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": "nabana.work@gmail.com"
};
if(person_name) person["name"] = person_name;
if(person_image) person["image"] = person_image;
var sponsor_organization = {
  "@type": "Organization",
  "name": "GoogleAdsense"
};
var search_action= !search_uri ? undefined : {
    "@type": "SearchAction",
    "target": search_uri + "?q={search_term_string}",
    "query-input": "required name=search_term_string" //google特有のプロパティ
};

var script = document.createElement("script");
script.setAttribute("type", "application/ld+json");

// create website_json
var website_obj = {
    "@context": "http://schema.org",
    "@type": "WebSite",
    "fileFormat": "text/html",
    "isAccessibleForFree": true
};
if(name) website_obj["name"] = name;
if(uri) website_obj["url"] = uri;
if(uri) website_obj["mainEntityOfPage"] = {"@type": "WebPage","@id": uri};
if(image) website_obj["image"] = image;
if(image) website_obj["thumbnailUrl"] = image;
if(description) website_obj["description"] = description;
if(keywords) website_obj["keywords"] = keywords;
if(charset) website_obj["encoding"] = {"@type": "MediaObject","encodingFormat": charset};
if(datePublished) website_obj["datePublished"] = datePublished;
if(dateModified) website_obj["dateModified"] = dateModified;
if(person) website_obj["author"] = person;
if(person) website_obj["publisher"] = person;
if(person) website_obj["copyrightHolder"] = person;
if(copyrightYear) website_obj["copyrightYear"] = copyrightYear;
if(inLanguage) website_obj["inLanguage"] = inLanguage;
if(genre) website_obj["genre"] = genre;
if(sponsor_organization) website_obj["sponsor"] = sponsor_organization;
if(search_action) website_obj["potentialAction"] = search_action;

script.innerText = JSON.stringify(website_obj);
document.head.appendChild(script);
}
window.addEventListener("load", create_schemaorg_website, false);
}());
</script>

上のスクリプトを埋め込んで,ブログトップページを「Googleの構造化データテストツール」と以下のように認識される.

テスト結果:

実際に埋め込まれたWebSite