【Memo】MovableTypeでJSON-LDの対応したメモ


既存ページのJSON-LD対応や新規ページのJSON-LD対応が最近あったのでメモとして書きたいと思います。

# JSON-LDとは？

JSON-LDとは、JSON形式で構造化データを記述するものになります。
詳しい内容は、以下のサイトを参照してもえればよいと思います。

* [JSON-LDでschema.orgの構造化データ導入をより簡単に](https://w3g.jp/blog/schema-org_and_json-ld)


# 本題

今回は、MovableTypeでJSON-LDの対応をする際に自分が行った手法になります。
もっと良い方法などあればコメント頂きたく。。(；・∀・) m(_ _)m

## ページ構成

案件ではブログ構成などが複雑だったりで説明がわかりにくくなってしまうので、シンプルな構成で説明したいと思います。

基本的な階層は3階層をベースに考えましたが、階層が深くなっても対応できるような形で考えました。

### ブログ構成

* インデックステンプレート（http://example.com/BlogName/index.html）
* カテゴリテンプレート（http://example.com/BlogName/CategoryName/index.html）
* エントリーテンプレート（http://example.com/BlogName/CategoryName/entry_id.html）

## JSON-LD用のテンプレートモジュールを作成

* テンプレートモジュールを新規で作成
* SetVarTemplate（_JSON_LD）でラッピング
* itemListElement：ListItemの1階層目を`mt:For`の外に出して定義（1階層目はどのテンプレートでも使うため）
* 2階層目以降は、`mt:For`のループ回数で各テンプレートごとに出力結果を変えれるようにする

`<mt:Var name="JSON_LD_Id{$x}" />`・`<mt:Var name="JSON_LD_Name{$x}" />`は、各テンプレートごとに定義している`mt:SetVarHash`を取りにいきます。

```
<mt:ignore>
========================================
Template Name : json_ld
Template Type : Module / WebSite
Template Note : JSON-LD Template
========================================
</mt:ignore>

<mt:SetVarTemplate name="_JSON_LD_Format" key="JSON_LD_Format" />
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [{
          "@type": "ListItem",
          "position": 1,
          "item": {
            "@id": "http://example.com/",
            "name": "HOME"
          }
        }<mt:for var="x" from="1" to="$jsonldCnt">,{
          "@type": "ListItem",
          "position": <mt:Var name="x" value="1" op="+" />,
          "item": {
            "@id": "http://example.com/<mt:Var name="JSON_LD_Id{$x}" />",
            "name": "<mt:Var name="JSON_LD_Name{$x}" />"
          }
        }<mt:If name="__last__">]</mt:If></mt:for><mt:Unless name="jsonldCnt">]</mt:Unless>
      }
    </script>
</mt:SetVarTemplate>

<mt:ignore>** 表示部分 **</mt:ignore>
<mt:Var name="_JSON_LD_Format" key="JSON_LD_Format" />

```

## 各テンプレートに必要の値を記述

* jsonldCntにカウント数を入れる
* 配列に定義しているJSON_LD_Idにループ回数ごとのパスを入力
* 配列に定義しているJSON_LD_Nameにループ回数ごとのブログ名・カテゴリ名・エントリー名を入力

変数を各テンプレートごとによってブログやカテゴリの階層が他と違う場合に柔軟に対応できるようにしました。
jsonldCntのカウント数を各テンプレートで定義したSetVarHashと比較し出力させています。


```
<mt:ignore>** ローカル変数 **</mt:ignore>
<mt:SetVars>
jsonldCnt=1
</mt:SetVars>

<mt:Ignore>JSON_LDのID定義：IDを入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Id" note="初期化" />
<mt:SetHashVar name="JSON_LD_Id">
  <mt:SetVar name="1" value="BlogName/" />
</mt:SetHashVar>

<mt:Ignore>JSON_LDのNmae定義：名前を入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Name" note="初期化" />
<mt:SetHashVar name="JSON_LD_Name">
  <mt:SetVar name="1" value="ブログ名" />
</mt:SetHashVar>
```

## 最終コード

最終的に出来上がったサンプルソースは、以下のような形になります。

* configテンプレートモジュール
* json_ldテンプレートモジュール
* 各ブログ：インデックステンプレート
* 各ブログ：カテゴリテンプレート
* 各ブログ：エントリーテンプレート

### ウェブサイト：configテンプレート

基本ですが、各設定の値などをconfigテンプレートに定義します。

```
<mt:ignore>
========================================
Template Name : config
Template Type : Module / WebSite
Template Note : 各種設定
========================================
</mt:ignore>

<mt:SetVars>
base_sitedomain=http://example.com/
blog_path=<mt:BlogURL />
category_title=<mt:Unless name="main_index"><mt:CategoryLabel /></mt:Unless>
category_path=<mt:Unless name="main_index"><mt:CategoryArchiveLink /></mt:Unless>
entry_title=<mt:If name="entry_archive"><mt:EntryTitle escape="html" /></mt:If>
entry_path=<mt:If name="entry_archive"><mt:EntryPermalink /></mt:If>
</mt:SetVars>
```

### ウェブサイト：json_ldテンプレート

JSON_LDのテンプレートモジュールを新規作成します。

```
<mt:ignore>
========================================
Template Name : json_ld
Template Type : Module / WebSite
Template Note : JSON-LD Template
========================================
</mt:ignore>

<mt:SetVarTemplate name="_JSON_LD_Format" key="JSON_LD_Format" />
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [{
          "@type": "ListItem",
          "position": 1,
          "item": {
            "@id": "<mt:Var name="base_sitedomain">",
            "name": "HOME"
          }
        }<mt:for var="x" from="1" to="$jsonldCnt">,{
          "@type": "ListItem",
          "position": <mt:Var name="x" value="1" op="+" />,
          "item": {
            "@id": "<mt:Var name="base_sitedomain" /><mt:Var name="JSON_LD_Id{$x}" regex_replace='$regex_replace',"/" />",
            "name": "<mt:Var name="JSON_LD_Name{$x}" />"
          }
        }<mt:If name="__last__">]</mt:If></mt:for><mt:Unless name="jsonldCnt">]</mt:Unless>
      }
    </script>
</mt:SetVarTemplate>

<mt:ignore>** 表示部分 **</mt:ignore>
<mt:Var name="_JSON_LD_Format" key="JSON_LD_Format" />
```

### ブログ：インデックステンプレート

```
<mt:ignore>
========================================
Template Name : index.html
Template Type : main index template
Template Note : トップページ出力用
========================================
</mt:ignore>

<mt:ignore>** ローカル変数 **</mt:ignore>
<mt:SetVars>
jsonldCnt=1
</mt:SetVars>

<mt:Ignore>JSON_LDのID定義：IDを入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Id" note="初期化" />
<mt:SetHashVar name="JSON_LD_Id">
  <mt:SetVar name="1" value="$blog_path" />
</mt:SetHashVar>

<mt:Ignore>JSON_LDのNmae定義：名前を入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Name" note="初期化" />
<mt:SetHashVar name="JSON_LD_Name">
  <mt:SetVar name="1" value="ブログ名" />
</mt:SetHashVar>

<mt:ignore>** 表示部分 **</mt:ignore>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-LDに対応してみた</title>
<mt:Include module="json_ld" parent="1" />
</head>
<body>
インデックステンプレート
</body>
</html>
```

### ブログ：カテゴリテンプレート

```
<mt:ignore>
========================================
Template Name : category.html
Template Type : category template
Template Note : カテゴリ出力用
========================================
</mt:ignore>

<mt:ignore>** ローカル変数 **</mt:ignore>
<mt:SetVars>
jsonldCnt=2
</mt:SetVars>

<mt:Ignore>JSON_LDのID定義：IDを入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Id" note="初期化" />
<mt:SetHashVar name="JSON_LD_Id">
  <mt:SetVar name="1" value="$blog_path" />
  <mt:SetVar name="2" value="$category_path" />
</mt:SetHashVar>

<mt:Ignore>JSON_LDのNmae定義：名前を入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Name" note="初期化" />
<mt:SetHashVar name="JSON_LD_Name">
  <mt:SetVar name="1" value="ブログ名" />
  <mt:SetVar name="2" value="$category_title" />
</mt:SetHashVar>

<mt:ignore>** 表示部分 **</mt:ignore>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-LDに対応してみた</title>
<mt:Include module="json_ld" parent="1" />
</head>
<body>
カテゴリテンプレート
</body>
</html>
```

### ブログ：エントリーテンプレート

```
<mt:ignore>
========================================
Template Name : detail.html
Template Type : detail template
Template Note : 記事出力用
========================================
</mt:ignore>

<mt:ignore>** ローカル変数 **</mt:ignore>
<mt:SetVars>
jsonldCnt=3
</mt:SetVars>

<mt:Ignore>JSON_LDのID定義：IDを入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Id" note="初期化" />
<mt:SetHashVar name="JSON_LD_Id">
  <mt:SetVar name="1" value="$blog_path" />
  <mt:SetVar name="2" value="$category_path" />
  <mt:SetVar name="3" value="$entry_path" />
</mt:SetHashVar>

<mt:Ignore>JSON_LDのNmae定義：名前を入力</mt:Ignore>
<mt:SetVar name="JSON_LD_Name" note="初期化" />
<mt:SetHashVar name="JSON_LD_Name">
  <mt:SetVar name="1" value="ブログ名" />
  <mt:SetVar name="2" value="$category_title" />
  <mt:SetVar name="3" value="$entry_title" />
</mt:SetHashVar>

<mt:ignore>** 表示部分 **</mt:ignore>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-LDに対応してみた</title>
<mt:Include module="json_ld" parent="1" />
</head>
<body>
エントリーテンプレート
</body>
</html>
```

一つのテンプレートにまとめblog_idやテンプレートの条件分岐でも対応可能だったりします。
経験上、モジュールにまとめすぎてしまうと可読性が悪くなったり修正があった際に場所を特定するのに時間がかかるので、今回のような形で対応してみました。

to_jsonという方法もあるかも！？と考えたのですが、こういったテンプレート系の階層構造を作れるのかな？という疑問がありました。知見がないのでもう少し調べて改良できる部分を改修していければと思いました。