GatsbyでOGP設定が上手くいかない時に見直したい事
TL:DR
OGP設定の読み込みは静的なファイルに対して行われるみたいなので気をつけよう。
OGPの設定例
GatsbyでOGP設定をする時は、react-helmetを使ってこんな感じで設定すると思います。
<Helmet>
<meta property="og:image" content={thumbnail} /> <meta property="og:image:height" content="630" />
<meta property="og:image:width" content="1200" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={thumbnail} /> <meta name="twitter:title" content="タイトル" />
<meta name="twitter:description" content="詳細" />
</Helmet>
この時、thumbnail
に画像へのパスを フルパス
で与えると思うのですが、@reach/routerを使って設定してはいけません。
import { useLocation } from '@reach/router'
thumbnail = `${useLocation().origin}/ogp.png`
この状態で、gatsby develop
で動かして、ブラウザ検証ツールで見ると、一見上手く設定されているように見えるのですが、
content
には正しく値が設定されているのに、なぜかproperty="og:image"
だけ離れて表示されてしまってます。
何が起きているのか?
これはこういう事が起きてるのかと想像ができます。
Gatsbyでのレンダリングは、SSR→クライアントサイドでのレンダリングで行われているみたいなので、まずSSRでレンダリングできる範囲でレンダリングされます。
<meta data-react-helmet="true" property="og:image" content="undefined/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png" />
<meta data-react-helmet="true" property="og:image:height" content="630" />
<meta data-react-helmet="true" property="og:image:width" content="1200" />
<meta data-react-helmet="true" name="twitter:card" content="summary_large_image" />
<meta data-react-helmet="true" name="twitter:image" content="undefined/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png" />
<meta data-react-helmet="true" name="twitter:title" content="Creator of @what" />
<meta data-react-helmet="true" name="twitter:description" content="いつかBioに「Creator of ...」と書けるようなプログラマを目指している人のブログ" />
useLocation
がSSRで機能しないので、useLocation().origin
がundefined
を返した結果、og:image
のcontent
が undefined/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png
となってしまってます。
でこのファイルがブラウザで表示された時に、useLocation().origin
が解決されて、og:image
のmetaタグが再レンダリングされた結果、元のmetaタグは削除され、headタグの子要素として新しいmetaタグが挿入される。
<meta data-react-helmet="true" property="og:image:height" content="630" />
<meta data-react-helmet="true" property="og:image:width" content="1200" />
<meta data-react-helmet="true" name="twitter:card" content="summary_large_image" />
<meta data-react-helmet="true" name="twitter:title" content="Creator of @what" />
<meta data-react-helmet="true" name="twitter:description" content="いつかBioに「Creator of ...」と書けるようなプログラマを目指している人のブログ" />
<meta />
<meta /> <!-- SSRでレンダリングされた他のmetaタグたち-->
<meta />
<meta data-react-helmet="true" property="og:image" content="http://localhost:8888/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png" /> <meta data-react-helmet="true" name="twitter:image" content="http://localhost:8888/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png" />
だから離れて、正しく表示されてしまうのですね。
JavaScriptが介在して正しくメタタグが表示されてしまっているように見えるだけで、OGPの読み取りは失敗するという状態が 完成してしまうという事ですね。
OGPの読み取りは静的ファイルに対して行われるみたいなので、上手くいかない時はgatsby build
した結果のpublic/index.html
を見た時に画像のパスなどをはじめとして、正しく設定されているか確認する癖をつけましょう。
画像パスのオリジンの解決方法
では、どうやって画像パスを解決するかですが、SSR時にも正しい値が設定されるように環境変数を使うといいと思います。
私は、GATSBY_BASE_URL
という環境変数を使うようにしました。
<Helmet>
<meta property="og:image" content={`${process.env.GATSBY_BASE_URL}/static/ogp.png`} /> <meta property="og:image:height" content="630" />
<meta property="og:image:width" content="1200" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content={`${process.env.GATSBY_BASE_URL}/static/ogp.png`} /> <meta name="twitter:title" content="タイトル" />
<meta name="twitter:description" content="詳細" />
</Helmet>
まとめ
- OGP設定の読み込みは静的なファイルに対して行われるみたいなので気をつけよう。
-
@reach/router
のuseLocation().origin
とかで画像のパスのオリジンを解決しないようにしましょう。- 画像パスのオリジンの解決には環境変数を使ったが良さそうです。
- OGP設定が上手くいかない(画像が表示されないなど)の場合は、
gatsby build
した結果、生成されるpublic/index.html
を確認するようにしましょう。