独り言形式で綴る「OGP & SSR」
OGP画像を表示させたい
「よし、Webサービスを作ったぞ」
「プログラミングに関する記事を投稿できるWebサービスだ」
「このサイトの記事をTwitterとかでシェアしてもらって、人気が出るといいな」
「シェアしてもらったときに、やっぱりOGP画像が表示された方がいいよな」
「よくあるような、記事のタイトルとかサイト名が入ったサムネ画像みたいなのを表示したいな」
「よし、そのためには、HTMLのmeta
タグに、OGPの情報が入るようにしないとな」
Next.jsでheadタグの中をいじる
「今回のWebサービスでは、フロント部分をNext.js[1]で実装したから」
「Next.jsでhead
タグの中をいじって、meta
タグにOGP情報を埋め込もう」
<Head>
<meta property="og:title" content="記事タイトル" />
<meta property="og:description" content="記事の説明" />
<meta property="og:image" content="OGP画像のURL" />
<meta name="twitter:card" content="summary_large_image" />
</Head>
「よし、meta
タグはこんな感じだな」
「記事タイトルやOGP画像のURLは、APIから取得した文字列を入れるようにしておこう」
「各記事ごとに、動的に変えたいからな」
「SWR
でAPIから取得したデータは、apiData
という名前の変数に入っているから・・・」
<Head>
<meta property="og:title" content={apiData.title} />
<meta property="og:description" content={apiData.description} />
<meta property="og:image" content={apiData.thumbnailUrl} />
<meta name="twitter:card" content="summary_large_image" />
</Head>
「↑こんな感じだな」
「よし、それじゃあサイトをデプロイし直して・・・」
「試しにTwitterで記事をシェアしてみよう」
表示されない
「あれ、OGPのためのmeta
タグを書いたはずなのに、OGP画像が表示されないぞ」
「ネットで原因を調べてみるか・・・」
Twitterのクローラーは、SPAを解釈できないらしい
「ふむふむ、どうやら」
「SWR
を使ってAPIから取得した記事の情報を、meta
タグに入れる・・・」
「これではダメみたいだ」
Twitter「お、URLを含んだツイートがされたぞ」
Twitter「じゃあ、そのサイトを見に行って、OGP画像があったら、ツイート上に表示しよう」
Twitter「お、このサイトだな」
Twitter「うーん・・・なんだろう、難しいJavaScriptやめてもらっていいっすか?」
Twitter「ええと、OGP情報は・・・無し!」
※イメージです
「↑こんな感じになってしまうみたいだ」
「Twitterのクローラーは、JavaScriptを完璧に解釈できる訳ではないから」
「SPA的なクライアントサイドの手法でmeta
タグを埋め込んでも、うまく表示されないらしい」
SSR(Server-Side Rendering)をしないといけない
「クローラーがHTMLを読み込んでから、JavaScriptでmeta
タグをいじるのではダメってことだな」
「クローラーがHTMLを読み込んだ時点で、meta
タグに情報が入っていないとダメってことか」
「つまりmeta
タグは、サーバサイドで書き込んでおく必要があるんだな」
「だから、サーバサイド・レンダリングというんだな」
getServerSideProps
を使う
Next.jsの場合、「どうやら、記事ページのjsx
ファイル内に」
「getServerSideProps
という関数を書いて、export
すればいいみたいだ」
export async function getServerSideProps({ query }) {
// APIからデータを取得
const res = await fetch(`https://.../api/ogp/articles/${query.id}`)
const ogpData = await res.json()
// それをpropsに入れて、オブジェクトとして返す
return { props: { ogpData } }
}
「よし、こうだな」
「meta
タグの方は...」
<Head>
<meta property="og:title" content={ogpData.title} />
<meta property="og:description" content={ogpData.description} />
<meta property="og:image" content={ogpData.thumbnailUrl} />
<meta name="twitter:card" content="summary_large_image" />
</Head>
「↑こうだな」
「よし、もう一度デプロイし直して」
「試しに記事をシェアしてみよう」
表示された
「よし、OGP画像が表示されたぞ」
「目的達成だ!」
※確認できない場合は、Twitterカードのキャッシュをクリアしてみましょう。
※というか、TwitterのCard Validator上で確認すればいいみたいです。
まとめ
- Twitterのクローラーは、SPAを解釈できない
- クライアントサイドで
meta
タグを書いてもダメ
- クライアントサイドで
- クローラーがHTMLを取得した時点で、metaタグにOGP情報が書いてないとダメ
- 各記事ごとに動的にOGP情報を埋め込みたい場合には、サーバ側での処理が必要
- Next.jsでは
getServerSideProps
を使用して実装する
注意点
- サーバ側での処理が必要なため、ホスティングサービスの選定時に注意が必要
- ホスティング先をVercelやAWS Amplify Consoleにしておくとやりやすい
- Serverless Next.js Componentを使用しても可能
- どちらも内部的にはAWSのLambda@Edgeを使用しているらしい
他のやり方
- SG(静的生成)
- デプロイ前にhtmlファイルを静的生成するタイミングで、APIと通信して
meta
タグを書いておければ、SSRする必要はありません。要件によりけりですね。
- デプロイ前にhtmlファイルを静的生成するタイミングで、APIと通信して
-
React製のフレームワークです。 ↩︎
Discussion