Gatsby.jsでTwitter Cardが表示されなくて苦悩した件

gatsby.png (13.2 kB)

TOC

この記事が役に立つ可能性がある方

この記事をご覧になられているということは、Twitter CardやFacebook Shareが意図した表示にならずお困りになられている方かと思います。 本記事はエラーとなる原因を、全て網羅している記事ではありません。 以下の条件に合致された方は、これから書く内容を試していただくと解決する可能性がありますので、是非試してみてください。

  • Twitter Card validatorでNo card found (Card error)となってしまう
  • cssをjsからimportしてGatsbyアプリケーションのスタイリングを行っている

Twitter Card validatorでTwitter Cardが表示されない

react helmetを使用してmetaタグを正しく設置しているのに、Card validatorでエラーが発生していました。

image.png (39.2 kB)

Helmetタグ使用方法や、プラグインの見直しを行っても一向に表示されず、諦めかけていました・・・。

metaタグの上にinline styleが多数ある場合表示されない

でもどうしても納得がいかず永遠とGoogleさんとにらめっこをしていたところ、とあるGatsby公式リポジトリのIssueを見つけました。

https://github.com/gatsbyjs/gatsby/issues/22908

この中でやりとりされているコメントをみるとどうやら、<head>タグ内に多数のインラインスタイルがあり、その後にogpやtwitter:cardの<meta>タグが設定されていると、上手く表示されない模様。

Twitter CardやFacebookのシェアリンクは、パブリックサーバーでホスティングされているWebページをスクレイプし、その中の<meta>タグを検知し表示しているらしいく、そのスクレイピングが恐らく<head>タグ内の最初の数KBしか読み取らないため、エラーとなってしまうということでした。

このブログのスタイリングはtailwindやmarkdownなどのcssファイルをgatsby-browser.jsでimportしているため、<head>タグ内に大量のインラインスタイルが定義されていました。

image.png (282.0 kB)

この大量のインラインスタイルと、ogp関連の<meta>タグの順序を入れえれば、スクレイピング時<meta>タグ取得してくれて、上手く表示してくれそうです。

上記のIssueに修正の参考となるリンクが貼ってあったので、そのまま拝借したいと思います。

gatsby-ssr.jsはbuild時に実行したい処理を記述する事ができます。 詳しいAPIなどは公式ドキュメントに書かれているので割愛しますが、今回は<head>内のコンポーネントを取得するgetHeadComponentsと、<head> 内のコンポーネントを渡したオブジェクトに置換するreplaceHeadComponentsを使って、<head>内のタグの順番を入れ替えたいと思います。

getHeadComponentsで取得した中身を見てみると、配列の中に各コンポーネントのオブジェクトが格納されているのがわかります。

getHeadComponentsで取得した配列
[
  {
    '$$typeof': Symbol(react.element),
    type: 'style',
    key: null,
    ref: null,
    props: {
      'data-href': '/styles.a868d7354fa00a91b7b8.css',
      dangerouslySetInnerHTML: [Object]
    },
    _owner: null
  },
  {
    '$$typeof': Symbol(react.element),
    type: 'meta',
    key: 'generator-2.24.91',
    ref: null,
    props: { name: 'generator', content: 'Gatsby 2.24.91' },
    _owner: null
  },
  {
    '$$typeof': Symbol(react.element),
    type: 'title',
    key: 'Gatsby.jsでTwitter Cardが表示されなくて苦悩した件',
    ref: null,
    props: {
      'data-react-helmet': true,
      children: 'Gatsby.jsでTwitter Cardが表示されなくて苦悩した件'
    },
    _owner: null
  },
  .
  .
  .
]

このオブジェクト内のtype: 'style'に対しソートを実行し、<head>内タグ の順番を入れ替えます。

gatsby-ssr.js
exports.onPreRenderHTML = function onPreRenderHTML({
  getHeadComponents,
  replaceHeadComponents,
}) {
  const headComponents = getHeadComponents();
  headComponents.sort((a, b) => {
    if (a.type === b.type || (a.type !== 'style' && b.type !== 'style')) {
      return 0;
    }

    if (a.type === 'style') {
      return 1;
    } else if (b.type === 'style') {
      return -1;
    }

    return 0;
  });

  replaceHeadComponents(headComponents);
};

この記述を追記し、$ gatsby buildを実行すると、各<style>タグが<head>タグの後ろに来るようソートされます。

再度Card validatorを使い、正常に表示されるか確認してみましょう。

image.png (152.5 kB)

無事表示されるようになりました!

まとめ

今回エラーを吐き続けていた原因は、React Helmetやgatsby-plugin-react-helmetの設定ミスなどはなく、TwitterやFacebookのリンクを生成する仕組みに対しての理解が不足していた事でした。 SNSリンクなど業務で全く扱わない為、個人ブログを始めたおかげで知識が1つ増えました。 あまりいないとは思いますが、同様の事象でお困りの方は是非今一度<head>タグ内を見直してみてください。

CONTACT
© 2023, Kakkiii All Rights Reserved.