SSI(Server Side Include)でTwitterのメッセージを出し分ける
PHPやRubyなどのサーバサイドの言語でWebサイトを構築している場合は楽勝なのだが、静的なHTMLをサーバにホストしているだけの簡素なWebサイトでは動的にHTMLを生成して返すにはどうすればよいか?
その方法の一つがSSI(Server Side Include)という技術を使う方法である。本ページではクエリーパラメータに応じてSSIの応答を分岐させ、TweetのImageを変更してみる。
パソコン購入の推薦結果をTwitter上に表示したい
今回は私のサイトパソコン選び方・購入ガイドを題材とする。
このサイトではパソコンのスペックやメーカーをユーザがアンケートを入力することで教えてくれるのだが、結果をTweetできるようにしている。
Tweet時にサイトカードを表示して、そのTitleを"パソコン選び方・購入ガイド"ではなく、"パソコン選び方・購入ガイド 診断結果"というように変更するのが今回のタスクとなる。
具体的にHTMLのソースコードで言うと
<meta property="og:title" content="<%= data.title %>" />
という記述を
<meta property="og:title" content="パソコン選び方・購入ガイド 診断結果" />
に変更したいのである。
診断結果のURLは特定のクエリーパラメータがq=1akeoaakeia..のように付いているので、クエリーパラムの有無でこれらを出し分けていきたい。
SSIの記述 (Server Side)
Apache チュートリアル: Server Side Includes 入門を参考に作業を進めて行く。
SSIはApacheでサポートされているため、その設定をまずは有効にする必要がある。
拡張子を.shtmlに変更してSSIを有効にするという方法もあるが、HTML側のファイルを改変したくないためより簡単な方法であるxBitHackディレクティブを使用する方向で行きたい。SSIを許可するOptions +Includes
の記述と共に下記のように記述する。
<VirtualHost>
# ....
# for server side includes
<Directory /var/www/html/pcrecommend/dist>
Options +Includes
XBitHack on
</Directory>
</VirtualHost>
XBitHackのXというのはLinuxの実行権限のことを意味する。すなわちSSLを記述するHTMLに実行権限を与える必要がある。
$ chmod +x index.html
SSIの記述 (Client Side)
次にHTML側の記述。全体を最初に表示する。
<meta property="og:description" content="<%= data.description %>" />
<!--#if expr="%{QUERY_STRING} =~ /^q=v1[a-z1-9]{18,23}$/" -->
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:url" content="https://<!--#echo var='HTTP_HOST' -->?<!--#echo var='QUERY_STRING' -->" />
<meta property="og:title" content="パソコン選び方・購入ガイド 診断結果" />
<!--#exec cmd="node ./../tools/create-images.js" -->
<!--#else -->
<meta property="og:title" content="<%= data.title %>" />
<meta property="og:url" content="<%= url %>" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:image" content="<%= `${baseUrl}${data.image}` %>" />
<!--#endif -->
重要なのは正規表現でQueryStringのマッチングをして場合分けをしている点である。
<!--#if expr="%{QUERY_STRING} =~ /^q=v1[a-z1-9]{18,23}$/" -->
基本的にこれだけで場合分けをすることができる。
さらに踏み込み画像を生成して呟いてみる
更に、本サイトで動的に推薦の画像を生成して返すということをやっている。
<!--#exec cmd="node ./../tools/create-images.js" -->
を実行すると、例えば次のような結果が返ってくる。
<meta property="og:image" content="https://pcrecommend.com/tweet-images/v1imrmaaambgeafabfaa1.png">
create-images.js
はconsole.logで標準出力のアウトプットを吐いて、それをSSIが汲み取り、HTMLとしてブラウザへ返すという動きをしている。また、その前段でnode-canvasを用いて画像を生成しファイルに保存している。一部抜粋するとこんな感じ。
const buffer = canvas.toBuffer('image/png');
fs.writeFileSync(imagePath, buffer);
console.log(`<meta property="og:image" content="https://${host}/${imagePath}" />`);
CGIしかSSIで実行できないと勘違いしている人もいるが、これはSSIが現在あまり使われていない古い技術であり、良く使われていた時代にCGIで書いていた人が多かったというだけの話である。
別にnodeだろうがCだろうが、標準出力を同期的に返す事さえできれば言語は何でも構わない。
結果
こんな感じでいらすとやのキャラクターが話しているような結果が出力されます。
時には園児にパソコンの指導をされることも。
リョーマ君もいるよ
100種類程度キャラクターを作ったのだが、新規に作成した画像がプレビューですぐには反映されず、どの画像で呟かれるのか分からないというTwitter側の問題もあり、いらすとやのキャラによってはツイート発信者のブランドイメージを毀損するリスクが発信者にはあった。
数種類の画像ならばTwitter側のキャッシュに取り込まれ、プレビューでもすぐに表示できるようになると思うが、如何せん推薦の組み合わせと画像の組み合わせを合わせると天文学的な数になってしまうので、キャッシュ作戦は不可能である。
よく占い結果を表示するツイートを目にするが、あれとか画像の種類は多くて10種類といったところ。ここは完全に予定外ではあった。
その結果以前よりTweetされる回数が心なしか減ってしまったので泣く泣く元に戻すことにする。
ともあれ、こんな感じでSSIは条件分岐や、プログラミングを実行して結果を返すという事が簡単にできるため、今の時代も結構使えたりします。