【JavaScript】動的にJSON-LDで構造化マークアップしてみる

JavaScript

【JavaScript】動的にJSON-LDで構造化マークアップしてみる

さて、前回に引き続きWebぺージネタ。
より効率よくクローラにWebぺージを理解してもらうためには構造化マークアップが有効である。
GoogleがおすすめするのはJSON-LDでの埋め込みであるとのこと。

HTMLの中にJSONのコードを書くだけ。なのだが、
トップぺージはいいとしても動的に内容が変化するようなページに直にJSON-LDを埋め込むのは骨が折れる。
ということで、JSON-LDでの構造化マークアップをJavaScriptで動的に作成しようというわけである。

今回は当サイトにJSON-LDを追加してみる。


対象のぺージを選定

以下の3ぺージでいいかと思われ。
コーポレートサイト等になればもっと力を入れますが、趣味サイトですからね。
・TOPぺージ
・BLOGトップぺージ
・BLOG記事ぺージ

TOPぺージ

まずはトップぺージ。
ここは動的ぺージではないので、Googleタグマネージャーでもいけるかと。
それでもせっかくヤル気になったので、JavaScriptで作成することにする。

コード
  let jsonData = [];

  let searchData = {};
  searchData["@context"] = "https://schema.org";
  searchData["@type"] = "WebSite";
  searchData["url"] = "https://life-is-game.n-izm.net/";
  searchData["potentialAction"] = {};
  searchData["potentialAction"]["@type"] = "SearchAction";
  searchData["potentialAction"]["target"] = "https://life-is-game.n-izm.net/search/query:{search_term_string}";
  searchData["potentialAction"]["query-input"] = "required name=search_term_string";

  jsonData.push(searchData);

  let siteData = {};
  siteData["@context"] = "https://schema.org";
  siteData["@type"] = "Organization";
  siteData["url"] = "https://life-is-game.n-izm.net";
  siteData["logo"] = "https://life-is-game.n-izm.net/user/themes/quark/images/logo/title_svg.svg";
  jsonData.push(siteData);

  jsonData = JSON.stringify(jsonData);

  let jsonElement = document.createElement("script");
  jsonElement.type = "application\/ld+json";
  jsonElement.innerText = jsonData;

  document.body.appendChild(jsonElement);

ま、動的ぺージではないので、こんなもんかと。

上記コードで、bodyの最下部に以下の内容が追加されます。

出力結果
<script type="application/ld+json">
[
    {
        "@context": "https://schema.org",
        "@type": "WebSite",
        "url": "https://life-is-game.n-izm.net/",
        "potentialAction": {
            "@type": "SearchAction",
            "target": "https://life-is-game.n-izm.net/search/query:{search_term_string}",
            "query-input": "required name=search_term_string"
        }
    },
    {
        "@context": "https://schema.org",
        "@type": "Organization",
        "url": "https://life-is-game.n-izm.net",
        "logo": "https://life-is-game.n-izm.net/user/themes/quark/images/logo/title_svg.svg"
    }
]
</script>

BLOGトップぺージ

次にブログトップぺージ。
このぺージは10件ほどの最近のぺージのサムネイルが表示されています。
それを読み取りJSON-LDを作成します。

コード

  // 記事ブロック
  let articleBlock = document.getElementById("item");

  let cardBlockList = articleBlock.querySelectorAll(".card");

  let jsonData = [];

  for ( let cardCnt = 0; cardCnt < cardBlockList.length; cardCnt++ ) {

    let = blogItem = {};

    // タイトル
    let titleAtag = cardBlockList[cardCnt].querySelector(".u-url");

    // 画像
    let imgTag = cardBlockList[cardCnt].querySelector("img");
    let imgSource = "";
    if ( imgTag === null) {
      imgSource = "";
    } else {
      imgSource = imgTag.src;
    }

    // 日付
    let timeTag = cardBlockList[cardCnt].querySelector(".dt-published");

    // 説明
    let cardBody = cardBlockList[cardCnt].querySelector(".card-body");
    let cardPTag = cardBody.querySelector("p");

    blogItem["@context"] = "http://schema.org";
    blogItem["@type"] = "BlogPosting";
    blogItem["headline"] = titleAtag.innerHTML;
    blogItem["image"] = [];
    blogItem["image"].push(imgSource);
    blogItem["datePublished"] = timeTag.dateTime;
    jsonData.push(blogItem);

  }

  jsonData = JSON.stringify(jsonData);

  let jsonElement = document.createElement("script");
  jsonElement.type = "application\/ld+json";
  jsonElement.innerText = jsonData;

  document.body.appendChild(jsonElement);

記事の読み取り部分が動的な処理になっている。
あとは、まんま。
必要な項目を集めて配列に追加。JSON化している。

上記コードでの結果。

出力結果
<script type="application/ld+json">

[
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【JavaScript】ブログ記事の目次を自動で作成してみる",
        "image": [
            "https://life-is-game.n-izm.net/images/6/1/8/b/d/618bdab773eba629fa80abe2ccc8f4217e5d5589-2021030101.jpg"
        ],
        "datePublished": "2021-03-02T09:14:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【PC】グラボをアップグレードする",
        "image": [
            "https://life-is-game.n-izm.net/images/6/e/c/5/7/6ec57e97c334cd87b6b06bf2822677fd985aad42-2021022301.jpg"
        ],
        "datePublished": "2021-02-23T18:56:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【PC】テレビと液晶ディスプレイでマルチディスプレイ",
        "image": [
            "https://life-is-game.n-izm.net/images/2/f/f/e/c/2ffec4ff11dbcd399042d1742a42cf84a29b8f79-2021022001.jpg"
        ],
        "datePublished": "2021-02-21T21:03:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【プログラミング】trixエディタの使い勝手を検証",
        "image": [
            "https://life-is-game.n-izm.net/images/a/8/8/c/9/a88c963ac01b71f618077c8fc514f6036afaf1bf-2021021201.gif"
        ],
        "datePublished": "2021-02-12T12:33:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【勉強】自学のすすめ",
        "image": [
            "https://life-is-game.n-izm.net/images/e/b/4/0/c/eb40c4d4bf157b9aaea4bb55818d6e8b48c4ca7b-2021020301.gif"
        ],
        "datePublished": "2021-02-10T18:04:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【ゲーム】グラボを変えたので旧作ゲームを高画質でプレイする",
        "image": [
            "https://life-is-game.n-izm.net/images/0/3/3/d/f/033dfe26d867eb7f14ce468c71ab878eb4e9376e-2021022401.jpg"
        ],
        "datePublished": "2021-02-24T22:22:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【Web】Googleの検索履歴を削除する方法",
        "image": [
            "https://life-is-game.n-izm.net/images/e/a/c/d/1/eacd1942b887f73507beff8cb32d5a78dc3b459e-2021022201.jpg"
        ],
        "datePublished": "2021-02-22T13:19:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【勉強】自学用のサイトを立ち上げた",
        "image": [
            "https://life-is-game.n-izm.net/images/5/a/0/a/7/5a0a7ea1dc4223abc3dc7da81e65bc27d3de2622-2021021901.jpg"
        ],
        "datePublished": "2021-02-19T12:31:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【プログラミング】見やすいフォントのすすめ",
        "image": [
            "https://life-is-game.n-izm.net/images/1/6/8/c/8/168c8943b966bb6436d8063debecd0c35d48a1ec-2021021101.gif"
        ],
        "datePublished": "2021-02-11T13:34:00+09:00"
    },
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "【楽器】アコギのメンテナンス②",
        "image": [
            "https://life-is-game.n-izm.net/images/1/7/7/a/6/177a6d225d85f7675bd02116f1c613dbc1857f84-2021020801.jpg"
        ],
        "datePublished": "2021-02-08T09:14:00+09:00"
    }
]

</script>

BLOG記事ぺージ

次にブログ記事ぺージ。
ブログの内容なので、画像もすべて収集する。

コード

  // meta
  let metaDescription = document.getElementsByName("description")[0].content;

  // heroイメージ
  let heroElement = document.getElementById("blog-hero");
  let heroimage = heroElement.style.backgroundImage;
  heroimage = location.origin + heroimage.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');

  let title = heroElement.querySelector("h1").innerHTML;

  // blog-date
  let publishDate = heroElement.querySelector(".dt-published").dateTime;

  // 記事内容
  let articleElement = document.querySelector(".e-content");

  // 画像
  let images = articleElement.querySelectorAll("img");

  // 
  let jsonData = {};
  jsonData["@context"] = "https://schema.org";
  jsonData["@type"] = "BlogPosting";
  jsonData["headline"] = title;
  jsonData["image"] = [];
  jsonData["image"].push(heroimage);

  for ( let imgCnt = 0; imgCnt < images.length; imgCnt++ ) {
    jsonData["image"].push(images[imgCnt].src);
  }

  jsonData["datePublished"] = publishDate;

  jsonData["author"] = {};
  jsonData["author"]["@type"] = "Person";
  jsonData["author"]["name"] = "ふだんぎアングラー";
  jsonData["publisher"] = {};
  jsonData["publisher"]["@type"] = "Organization";
  jsonData["publisher"]["name"] = "n-izm.net";
  jsonData["publisher"]["logo"] = {};
  jsonData["publisher"]["logo"]["@type"] = "ImageObject";
  jsonData["publisher"]["logo"]["url"] = "https://life-is-game.n-izm.net/user/themes/quark/images/logo/title_svg.svg";
  jsonData["publisher"]["logo"]["width"] = 100;
  jsonData["publisher"]["logo"]["height"] = 100;
  jsonData["description"] = metaDescription;

  jsonData = JSON.stringify(jsonData);

  let jsonElement = document.createElement("script");
  jsonElement.type = "application\/ld+json";
  jsonElement.innerText = jsonData;

  document.body.appendChild(jsonElement);

hero画像、タイトル、公開日、記事内の画像を収集。
あとは他と同様にJSON-LDに変換。

作成されたのが以下となる。

出力結果
<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "headline": "【JavaScript】ブログ記事の目次を自動で作成してみる",
    "image": [
        "https://life-is-game.n-izm.net/user/pages/02.blog/20210302_01/20210301_01.jpg",
        "https://life-is-game.n-izm.net/user/pages/02.blog/20210302_01/20210301_02.jpg",
        "https://life-is-game.n-izm.net/user/pages/02.blog/20210302_01/20210301_03.jpg"
    ],
    "datePublished": "2021-03-02T09:14:00+09:00",
    "author": {
        "@type": "Person",
        "name": "ふだんぎアングラー"
    },
    "publisher": {
        "@type": "Organization",
        "name": "n-izm.net",
        "logo": {
            "@type": "ImageObject",
            "url": "https://life-is-game.n-izm.net/user/themes/quark/images/logo/title_svg.svg",
            "width": 100,
            "height": 100
        }
    },
    "description": "【JavaScript】ブログ記事の目次を自動で作成してみる. さて、タイトル通り。. 当ブログにも一度目次にアンカーリンクを付けたものを配置したが、なんといっても作るのが面倒なのである。. 2箇所に細工をしなくてはならないのだ。とに�"
}
</script>

画像が多ければ多いほどimageの中身が増える。


確認方法

リッチリザルトテストを行えば作成したJSON-LDが正しくできているか確認できます。
リッチリザルトテスト


その他の種類

他にも構造化タグの種類はたくさんあります。
検索ギャラリー

schema.org。これを読めばバッチリでしょ。
schema.org


まとめ

これで構造化マークアップ対応は完了しました。
自前でJSON-LDを埋め込むのもよし、Googleタグマネージャを使用するのもよし。
どちらの方法にしても手間は増えますが、検索結果をよりリッチにすることができます。
検索順位には影響はないとのことですが、目に止まる検索結果を作成すれば入場する割合が増えるかもしれません。

外部のサービスに依存したくない場合は次前で埋め込み、それ以外はGoogleタグマネージャーを使う。というような切り分けも必要になってくるかもしれませんね。

ひと昔前はメタキーワードでなんとかなっていたが、今はこんなこともしなきゃならんのか。時代は変わったな。
ま、ワタクシのぺージは内容がペラペラなので、検索結果は変化がないように思いますがwwww

前の記事 次の記事