TwitterでシェアするOGP画像を動的に書き換える

タイトルの通り、こんな要求があって何とか対応したので困ってる人のTipsになれば。。

※2019/07/31追記
ニッチな対応かと思いきや意外にも（少なくともSHIN_DEVELOPアカウントで一番）需要があるようなので
この記事はどんどんブラッシュアップしていきたい。

# ogpってなんよ
SNSでシェアするときに使うアレよね？
って認識しかなかったのでちゃんと調べました。
> OGPとは、Open Graph Protocolの略で、Facebookやmixi、Google+などのSNS上でWebページの内容を伝えるために定められたプロトコルです。
〜中略〜
OGPを使って画像やタイトル、説明文を適切に設定することで、共有されたユーザーへの訴求力が高まり、サイトへのアクセス数を増やし、より多くのユーザーに記事を見てもらうことが可能となります。

引用元：[ナイル株式会社様HPより](https://cont-hub.com/knowledge/glossary/ogp/)

まぁ大体合ってるので良しとしまして。

# 事の発端
とある投稿型のSPAを作成しまして、記事毎にogpの内容を切り替えたいという課題がありました。
ReactやらAjaxやらのjs周りに疎い私は
**「おう、動的に変えたらええやん」**
と、**出来るならやっちゃいなよスタンス**を取っておったわけですが、
よくよく話を聞いてみると、javascriptによる動的な切り替えはSNSを始めとしたクローラが解釈してくれないそうです。
つまりシェア時に、ogpで設定しておきたい画像やテキストが表示されないという
何ともみっともない事態が発生してしまうのですね。


これがどうやらバックエンド側なら解決出来るらしい、とのことなので
渋々色々調べたメモを残します（ここから本題）

# やったこと
構成として各記事のURLにはIDがついてるので、これを使って記事データを取得して
phpでmeta情報を出力すりゃーいいんじゃねーかという調査結果を得ました。
http\://onigiri-tabetai.jp/archives/<font color="MediumVioletRed">123</font> ←コレ

### 前準備
まずクローラがシェア用のデータを取りに来た時だけ正しいogpをお持ち帰り出来るよう、
記事データとは全く別の領域にリダイレクトするようにしました。
.htaccessを以下のように設定しておきます。

**※2019/07/31追記**
ぐぐたすことGoogle+は個人向けサービス終了とのことで省略。
LINEのUAはfacebookexternalhitということなのでFB対応が同時にLINE対応になります。

```Apache
RewriteCond %{HTTP_USER_AGENT} (facebookexternalhit/[0-9]|Twitterbot|Pinterest)
RewriteRule archives/(\d*)$ https://onigiri-tabetai.jp/head.php?id=$1 [L]
```
これによりシェア時にbotどもが来た際は全てhead.php?id=記事IDに誘導されます。

### 本体実装
head.phpは単純に出力処理を行っているだけです。
~~(フロントのソースコピペベースなので無駄が多いですが)~~
**2019/05/18** **結構閲覧されてるので大事なとこだけを整理しました。**

```php
<?php
$entry_id = ctype_digit($_GET['id']) ? $_GET['id'] : 0;
$ctrl = new dataController(); //この辺は省略

//個別に出力したい項目について定義
$data = [
            "title"        => "def_title",
            "main_caption" => "def_caption",
            "main_img"     => "def_img"
        ];
$data = $ctrl->getEntry($entry_id);
if ( count($data) <= 0 ){
	//entry_idに対応したデータが無かったらトップへ
	header('Location: http://onigiri-tabetai.jp/');
	exit());
}

createHead($data);

function createHead($data) {
?>
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>おにぎりブログ</title>
	<!-- Google / Search Engine Tags -->
	<meta itemprop="name" content="<?php echo $data["title"]; ?>">
	<meta itemprop="description" content="<?php echo $data["main_caption"]; ?>">
	<meta itemprop="image" content="<?php echo $data["main_img"]; ?>">
	<!-- Facebook Meta Tags -->
	<meta property="og:url" content="http://onigiri-tabetai.jp/archives/<?php echo $data["id"] ?>">
	<meta property="og:type" content="website">
	<meta property="og:title" content="<?php echo $data["title"]; ?>">
	<meta property="og:description" content="<?php echo $data["main_caption"]; ?>">
	<meta property="og:image" content="<?php echo $data["main_img"]; ?>">
	<!-- Twitter Meta Tags -->
	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="<?php echo $data["title"]; ?>">
	<meta name="twitter:description" content="<?php echo $data["main_caption"]; ?>">
	<meta name="twitter:image" content="<?php echo $data["main_img"]; ?>">
</head>
</html>

<?php
}
?>
```

連想配列に格納してforeachでkey,valueをぶん回したほうがスマートかもですねー。
これでどの記事をシェアしてもbotは記事IDを背負ってこのページに来るってスンポーです。
ここで出されたmeta情報をお持ち帰りしてまんまとシェア画像やテキストを作ることになります。