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で動かして、ブラウザ検証ツールで見ると、一見上手く設定されているように見えるのですが、

meta-ogp.png

contentには正しく値が設定されているのに、なぜかproperty="og:image" だけ離れて表示されてしまってます。

何が起きているのか?

これはこういう事が起きてるのかと想像ができます。

Gatsbyでのレンダリングは、SSR→クライアントサイドでのレンダリングで行われているみたいなので、まずSSRでレンダリングできる範囲でレンダリングされます。

public/index.html
  <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().originundefinedを返した結果、og:imagecontentundefined/static/51723dc79cfb65c71b7394d65f2bef95/73f08/blog-header.png となってしまってます。

でこのファイルがブラウザで表示された時に、useLocation().origin が解決されて、og:image のmetaタグが再レンダリングされた結果、元のmetaタグは削除され、headタグの子要素として新しいmetaタグが挿入される。

public/index.html
  <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/routeruseLocation().origin とかで画像のパスのオリジンを解決しないようにしましょう。

    • 画像パスのオリジンの解決には環境変数を使ったが良さそうです。
  • OGP設定が上手くいかない(画像が表示されないなど)の場合は、gatsby buildした結果、生成されるpublic/index.htmlを確認するようにしましょう。

参考

yukihirop

この記事を書いた人

フロントエンド兼バックエンドなWEBエンジニアです。 既存の考え方に囚われずに自由にツールを作るのが好きです。

いつかBioに「Creator of ...」と書けるようなプログラマを目指している人のブログ

関連記事