技術
X は og: ではなく twitter: を読む —— Next.js のメタデータで踏んだ2つ
「共有したときのカードが、どのページを貼っても同じ文言になる」。原因は2つあって、どちらも黙って起きます。ページは正しく表示され、エラーも出ません。
X は og: ではなく twitter: を読む
openGraph だけを書いたページは、画像だけ差し替わってタイトルと説明がルートレイアウトの値のまま残ります。X が twitter:* を優先して読むためです。
このサイトでは、更新ログの個別ページ5件が実際にその状態でした。og:title は記事の見出しなのに、twitter:title はサイト全体のキャッチコピーのまま。貼るまで気づけません。
Next.js のメタデータは、親を丸ごと置き換える
もう1つがこちらです。Next.js のメタデータは浅くマージされます。子のセグメントが openGraph を定義すると、親の openGraph はまるごと置き換わります。中の images や siteName だけが残る、ということはありません。
// app/<slug>/layout.tsx
export const metadata = {
openGraph: { title: 'スグイコ' }, // ← 親の openGraph を丸ごと置き換える
} // images も siteName も消えるこれで og:image が消え、共有カードが画像なしになりました。og:site_name にいたっては、メタデータを組み立てる関数を通す13ページすべてで出ていませんでした。ルートレイアウトが持っていても、子が上書きしていたためです。
対策 —— 別々に書ける口を作らない
個別に気をつける、では必ず漏れます。2つを同時に生成する関数を1つ置いて、そこからしか書けないようにしました。
openGraphとtwitterを、同じ引数から一緒に組み立てるsiteNameもその関数が持つ(親から降ってこないので)- ページ側は文言だけを渡す。片方だけ書く手段が無い
「気をつける」を仕組みに変える、というだけの話ですが、これが唯一効きました。
同じことが alternates でも起きる
後日、RSS フィードのリンクを足そうとして同じ穴に落ちかけました。alternates も同じように丸ごと置き換わります。
つまり、alternates.canonical を返す関数を通るページでは、ルートレイアウトに書いた alternates.types が丸ごと消えます。キーが違うだけで、openGraph のときとまったく同じ現象です。
フィードのリンクも、canonical と同じ関数の中に入れました。置き換わるものは、置き換える側が全部持つ。 これが結論です。