デフォルトではaタグ(リンク)で貼り付ければ可能ですが、タグ毎に関連する書籍等を表示したい場合、テーマを拡張する必要があります

環境

Ghost v1.25.2
CasperTheme Version 2.3.3

目的

投稿記事に設定されたタグに該当するAmazonの商品を列挙して表示する
ただしGhostのプラグインとしては実装せず、単純なjsonpとすることで他プラットフォームへ容易に移植できるように実装する

背景

お勧めの書籍等をタグ毎にまとめたい
コンテンツと広告をできるだけ別として管理したい
将来的にGhostから移行しても楽にしておきたいからGhostに依存するコードは書きたくない

解決策

Ghostに依存しないように実装するため、今回は単純なjsonpのモデルとjqueryによるレンダリングで実装する
やることは、投稿を表示する際に投稿タグに紐付いたamazon商品を表示するだけ

1. テーマのダウンロード

[Design]から対象のテーマをダウンロードする
デフォルトのcasperテーマは管理画面上からは上書きできないため、カスタムのテーマを所有してない場合はcasperをダウンロードして、それを改変後、別名にしてアップロードする

2. モデル(jsonp)の作成

jsonで実装してもよいですが、ローカルデバッグが面倒なのでjsonpで実装
jsonpといってますが実態はjsです
下記はfusion360のタグに対して表示するモデルのサンプルの抜粋

assets/js/amazon.jsonp

var _amazon = {
    'ads':{
        'fusion360':[
             {category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/480071141X/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=480071141X&linkCode=as2&tag=zync-22&linkId=02a0fd8f666e910b35309f4470f6f2e9"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=480071141X&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=480071141X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
            ,{category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4800712157/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4800712157&linkCode=as2&tag=zync-22&linkId=ab97ea8d0e29effa061bc4352ef3b798"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4800712157&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=4800712157" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
            ,{category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4877834168/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4877834168&linkCode=as2&tag=zync-22&linkId=056d8702f59a1305edd870e8cddd2f27"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4877834168&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=4877834168" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
            ,{category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4877833900/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4877833900&linkCode=as2&tag=zync-22&linkId=5d7c44a6a03359de9f4f4a69f0f1dd31"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4877833900&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=4877833900" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
            ,{category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4877834311/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4877834311&linkCode=as2&tag=zync-22&linkId=1252d402b79bb64fcfd1a7258e53f781"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4877834311&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=4877834311" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
            ,{category:'book', element:'<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4774193984/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4774193984&linkCode=as2&tag=zync-22&linkId=bf52f068781ac8e672cceaa16aade636"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4774193984&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=zync-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=zync-22&l=am2&o=9&a=4774193984" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />'}
        ]
    }
}

3. cssの作成

広告を表示する領域のスタイルを作成する
今回はcasperテーマからの派生なので、元々あるスタイルを踏襲しますが必ずしもcasperテーマであるとは限らないので、別のcssファイルとして定義した

assets/css/extension.css

.post-full-ads {
    margin: 0 auto;
    max-width: 840px;
}

.post-ads {
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    margin: 0 -20px;
    padding: 40px 0 0;
    display: flex;
}

.post-ad {
    -ms-flex: 1 1 200px;
    flex: 1 1 200px;
    -ms-flex-direction: column;
    flex-direction: column;
    overflow: hidden;
    margin: 0 20px 40px;
    min-height: 300px;
    background: #fff 50%;
    background-size: cover;
    border-radius: 5px;
    box-shadow: 8px 14px 38px rgba(39,44,49,.06), 1px 3px 8px rgba(39,44,49,.03);
    transition: all .5s ease;
    display: flex;
    justify-content: center;
    align-items: center;
}

4. default.hbsの修正

上記のjsonpとcssを読み込むように修正する

default.hbs

    {{!-- Styles'n'Scripts --}}
    <link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" />
    <link rel="stylesheet" type="text/css" href="{{asset "css/extension.css"}}" />
    <script type="text/javascript" src="{{asset "js/amazon.js"}}"></script>

5. post.hbsの修正

投稿タグを取得して必要があれば広告枠のルートDOMを生成させ、DOM準備が出来たタイミングでjQueryでレンダリングする

下記の広告枠DOMの生成処理を、

{{#if tags}}
<section class="post-full-ads">
    <div class="inner">
        {{#foreach tags}}
        <div class="post-ads {{name}}">
        </div>
        {{/foreach}}
    </div>
</section>
{{/if}}
<footer class="post-full-footer">
    ...
</footer>    

の下に追加する

さらに下記の広告表示処理を、

    $('.post-ads').each(function(){
		var target = $(this);
        var target_class = $(this).attr("class");
        var classes = target_class.split(" ");
        for(var i = 0; i < classes.length; i++) {
            if(!_amazon || !_amazon['ads'])
                continue;
            var amazon_ads = _amazon.ads[classes[i]];
            if(amazon_ads) {
                for (var l = amazon_ads.length - 1; l >= 0; l--) {
                    var rand = Math.floor( Math.random() * ( l + 1 ) );
                    [amazon_ads[l], amazon_ads[rand]] = [amazon_ads[rand], amazon_ads[l]]
                }
                amazon_ads.forEach(function(amazon_ad) {
                    target.append('<article class="post-ad">' + amazon_ad.element + '</article>');
                });
            }
        }
    });

post.hbsの下の方にある、

// NOTE: Scroll performance is poor in Safari
// - this appears to be due to the events firing much more slowly in Safari.
//   Dropping the scroll event and using only a raf loop results in smoother
//   scrolling but continuous processing even when not scrolling
$(document).ready(function () {
....

の下に追加する

6. zip圧縮する

アーカイブして、フィル名をテーマ名に変更し、管理画面の[Design]->[upload]で上書きして適用する

確認

サイトにアクセスしてamazonの商品が表示されたらOK

課題

今回はてっとりばやくテーマに組み込んで実装してしまった
そのため、外部からモデルの更新ができない(しづらい)
次回はモデルamazon.jsをテーマから切り離して実装するように変更したい