ReactのサイトにOGPを追加する方法

どうも洋梨🍐です。

Firebaseと接続し、Cloud FireStoreのデータを表示するWebアプリを開発することになったのですが、まず環境に悩みました。

Node.js + Expressなどでサーバー側で実装するのか(Server Side Rendering)、それともJavaScript(JQueryとか)クライアント側で表示するようにするのか、、、

で結論が「とりま触ってみたいしReactでやってみるか」となったわけです👼

ですがここで問題が発生。

まず視野に入れていた問題の「SEO的なGoogleのクローラー問題」

これはGoogleのボットさんは有能なのでJavaScriptも読み込んでくれるよう。

ありがたき~

だが視野にあまり入れてなかった(入れてなかったわけじゃないよ?🥺

「OGP」

という問題にあたりました☻

SSR(Single Page Application)であるReactさん、ぴえんだね🥺

.

ReactでOGPに対応する方法

ReactをOGPに対応させる方法としておそらく先に考え付くのがキャッシュを取っておく作戦だと思います。

しかし、今回はFirebase Cloud Functionsを既に使っていたという背景から

「OGPを取得するAPIを作り、PHPでOGPを出力させる」

という方法を用いました。

※「効率悪くね」とか言わないでね?意外とやってみたらよかったんす😢

図に書くとこんな感じ

OGP結果を返すAPIを作る

まずはFirebase functionでOGP結果を返すAPIを作成します。

[example]
export const getOgp = functions.https.onRequest(async(req,res)=>{
    const id = req.query.idas string | undefined;
    const imageUrl = example(id); // id を元に画像URL等を生成する
    
    res.json({
      image: imageUrl
    })
})

このように結果をJson形式で返しています。

当初Firestoreだけを使う予定だったのですが便利過ぎて、ほぼFirebase上に置くことになりそうです🥺

.

API結果をPHPで受け取る

その次はAPIの結果をPHPで受け取り、HTMLを書き換えます。

[example *実際使うときはnullチェックとか色々書きなおしてね-q-]
<?php
$json = getOgp("https://example.com/");

function getOgp($uri){
    $opts = array('http' =>
      array(
          'method'  => 'GET'
      )
    );
    $context = stream_context_create($opts);
    $response = file_get_contents($uri, false, $context);
    return $response ? json_decode($response, true) : null;
}
?>

....
<head>
    <meta property="og:image" content="<?php echo $json["image"]?>" />
    ....

このようにAPI結果をもとにOGPを書き込みます。

ここまで出来たらサーバーにファイルを配置し、いざ実行。

するとあら不思議

TwitterでのOGP
LINEでのOGP

このようにOGPに対応しちゃってるではありませんか~^

これで一件落着。。。。

の前にちょっと待って。このサイト、、、

「「遅くね??」」

.

クローラの時だけタグ作成で高速化

そうです。このサイト実は遅いのです。

なぜならOGPタグ生成の時、APIサーバーにリクエスト、API結果を待機、その後取得した結果をもとにHTMLを作成、その後React(JavaScript)で画面を生成、、、とながーい道のりを歩んでいるのです。

「激おそ」とは言いませんが、「おそ」くらいです。

ではどうやって解決しよう、、、

「クローラの時だけOGPタグ作ればよくね?」

という結論に達しました。

つまり、UserAgentを用いそのアクセスがクローラか判定し、クローラの時だけOGPのMetaタグをプレゼントという事です。

リンクを各プラットフォームに貼るとこんな感じでクローラがいっぱい来るよ。嬉しいね☻

やり方はいたって簡単。

事前に予測できるクローラ名を挙げておき、判定するのです☻

function isCrawler(){
      $user_agent = $_SERVER['HTTP_USER_AGENT']; 
      return preg_match('/facebook|Twitterbot|Discordbot|Slackbot|SkypeUriPreview/ui', $user_agent) != 0; 
}

PHPで書くとこんな感じでしょうか。

LINEのクローラも「facebookexternalhit」なのは中々興味深いものでした。

この判定結果をもとにそれ以外の時はこの処理をスキップすればいい感じなサイトができるのではないでしょうか!

.

今回はここまで!読んでくれて、あざまる水産!

.


ホームページでは他にも

・様々な記事や作った作品および過程
・ソースコード、素材ファイル
・あらゆる”モノ”の作り方

などなど随時、記事や作品を新規公開・更新していますので是非見ていってくださいね!見ていただけると本当に嬉しいです!