OGP(Open Graph Protocol)とは、WebページのURLがX(旧Twitter)やFacebookなどのSNSに投稿されたときに、タイトルや画像、説明文などの補足情報を表示するための仕組みです。

以下のページでは[現在時刻を X にポストする]をクリックするとこのような現在時刻を含む画像がポストされます。

前提

まずページ内にボタンを設置してクリックするとXに投稿されるようにするだけなら以下の方法でOKです。

index.html

ただこの方法だと投稿ボタンを最初は非表示にしておき、動的に表示させようとするとうまく動いてくれません。以下のHTMLでは3秒後に文字は表示されるのですが、肝心のボタンが表示されません。

動的に表示させたい場合は以下のようにします。

OGPを設定するときは以下のようにします。この部分はJavaScriptではできないのでHTMLに直接書きます。headタグ内に以下を追加します。これでXに投稿したときに画像等もいっしょに投稿されるようになります。

JavaScriptでOGPを書き換えても意味無し

ではJavaScriptでOGPを書き換えることは可能でしょうか? これが可能になれば公開しているゲームを任意のタイミングでキャプチャしたものを解散させたいときに使えそうです。

JavaScriptでOGPを書き換える | cly7796.net ではまさにそれをやろうとしているのですが、結論は「JavaScriptでOGPの書き換えや追加を行っても、facebook・twitter共に認識できない」です。

自分でもあれこれやってみたのですが、やっぱりうまくいきません。

実は https://twitter.com/intent/tweet? のパラメーターに追加する url の部分、これは投稿ボタンを設置したページではなくそれ以外のページであっても機能します。そしてOGPを機能させるためには自分のページではなく対象のページに上記のmetaタグが入っていなければならないのです。そのため対象のページにアクセスした段階ですでに上記のmetaタグが存在する状態でなければなりません。JavaScriptでOGPを書き換えたとしても認識されるはずがないのです。

打開策

ではどうするか? PHPでそのようなページをつくることにします。

canvasに描画されている画像を保存する

これは現在時刻をcanvasに表示するためのHTMLとJavaScriptです。

index.html

app.js

ボタンがクリックされたらcanvasをキャプチャしてこれをPHP側にPOSTします。サーバー側でPNGファイルが生成され、この画像を用いたOGPが設定されたページが生成されます。あとはこのページをXにポストすることでOGPに動的に画像が設定されたことにしてしまおうというわけです。

app.js

POSTされるDataURL文字列は ‘data:image/png;base64,iVBORw0KGgoAAAANS..’ のように ‘data:image/png;base64,’からはじまるのでそれ以降をデコードして画像ファイルに変換します。ただこれだと危険なスクリプトのような悪意のあるデータが送りつけられるかもしれないので、画像ファイルに変換可能なものであることを確認し、そうでないものはサーバー内には保存されないようにしています。

png.php

OGPが設定されたページを表示させる

page.php?time=’ + (JavaScript内のDate.now()が返した値)にアクセスすると上記で生成したPNGファイルを用いたOGPが設定されたページを表示させる処理を示します。og:image は相対urlではなく絶対urlでなければならないので最初にサーバー上に生成されたPNGファイルのurlを求める処理をしています。

これでこのurlをXにポストすれば投稿文とともに画像も表示されるようになります。またユーザーがXの投稿をクリックしたときもこのページが表示されます。この場合は 0.5秒後に見てほしいページにリダイレクトされるようにしています。

page.php

不要になったファイルを削除する

処理を繰り返すたびにPNGファイルがサーバー上に生成されていきます。処理が終わったらこのファイルはいらないので削除したいです。PNGファイルを削除する処理を示します。

ここでも悪意あるデータが送りつけられて意図しないファイルが消えてしまわないように $_POST[‘now’] で取得された文字列がすべて数字であることを確認してからファイル削除の処理をおこなっています。

delete.php

完成させる

上記の処理をまとめます。[現在時刻を X にポストする]ボタンがクリックされたときに処理を示します。

window.openで生成されたウィンドウが消滅したら投稿の処理は確実に完了したか途中でキャンセルされたことになります。そこでこのタイミングでサーバー上のPNGファイルを削除します。

app.js