Twitterカードは、XにURLを貼ったときに「タイトル・説明・画像」を見やすく表示してくれる仕組みです。カードの代表的な形式は次の2つ。
-
summary:小さいサムネイル+テキスト(左に小画像、右にタイトル等)

-
summary_large_image:大きな画像+テキスト(画像を目立たせたいときに有効)

今回は視認性重視で summary_large_image を採用しました。
更新日:
投稿日:
X(旧Twitter)にアプリのURLを投稿した際に「サムネイル画像やタイトルが思うように表示されない」という問題に直面しました。 最初は タグに og:image を設定していたのですが、なぜか画像が出なかったり、小さいカードになってしまったり…。調べていくと 画像URLが絶対パスでないと表示されない という落とし穴がありました。 そこで今回は、「Twitterカードを正しく設定する方法」と「絶対パスをテンプレートに渡す工夫」についてまとめてみます。
Twitterカードは、XにURLを貼ったときに「タイトル・説明・画像」を見やすく表示してくれる仕組みです。カードの代表的な形式は次の2つ。
summary:小さいサムネイル+テキスト(左に小画像、右にタイトル等)

summary_large_image:大きな画像+テキスト(画像を目立たせたいときに有効)

今回は視認性重視で summary_large_image を採用しました。
最初は Open Graph(og:)だけを <head> に入れていました。多くのSNSではこれで十分です。
<!-- OGP(初期) -->
<meta property="og:title" content="{{ topic.title }} - KakuhanApp | スト6雑談・攻略掲示板">
<meta property="og:description" content="誰でも気軽に交流できる雑談・攻略掲示板です。">
<meta property="og:image" content="{% static 'images/default_thumbnail.png' %}">
<meta property="og:type" content="website">
この状態だとX で画像が表示されませんでした。

X は twitter: 系のタグも見るため、確実に表示させたい場合は twitter: タグも追加します。私は次のように追加しました。
<!-- Twitter Card(追加) -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@KakuhanApp">
<meta name="twitter:title" content="{{ topic.title }} - KakuhanApp | スト6雑談・攻略掲示板">
<meta name="twitter:description" content="誰でも気軽に交流できる雑談・攻略掲示板です。">
<meta property="twitter:image" content="{% static 'images/default_thumbnail.png' %}">
しかしこの状態でも X で画像が出ず、原因は画像のパスを 相対パスのまま渡していたこと だと判明しました。
私が確認した主な原因は次の通りです:
相対パスで指定している
X(Twitter)のクローラーは外部から画像を取得するため、https://... で始まる 絶対URL が必要です。相対パス(/static/...、{% static ... %} のみ)ではクロールできない/正しく解釈されないことがあり、結果として画像が表示されません。
キャッシュ
X 側は OGP 情報をキャッシュします。meta を修正してもすぐ反映されないことがあるため、Card Validator(検証ツール)で再取得したり、画像URLに ?v=2 のようなバージョンパラメータを付けてキャッシュバスターを使うことがよくあります。
今回の主原因は(1)の 相対パス でした。
テンプレート内で request.build_absolute_uri() を関数呼び出しのように直接書こうとすると構文上エラーになったり扱いにくかったので、コンテキストプロセッサを作って全ページに絶対パスを注入しました。以下のように実装しました。
# config/context_processors.py
from django.templatetags.static import static
def default_thumbnail(request):
""" すべてのテンプレートに 'default_thumbnail_url(絶対パス)' を渡す """
url = request.build_absolute_uri(static("images/default_thumbnail.png"))
return {"default_thumbnail_url": url}
これを settings.py の TEMPLATES 内 OPTIONS['context_processors'] に追加します。
テンプレート側ではこう使います:
<meta property="og:image" content="{{ default_thumbnail_url }}">
<meta property="twitter:image" content="{{ default_thumbnail_url }}">
これにより、すべてのテンプレートで {{ default_thumbnail_url }}(サムネ画像の絶対パス) を呼び出せるようになり、Twitterカードにサムネイルが表示されるようになりました。

ポイントまとめ
Twitterカードには「summary」と「summary_large_image」があり、今回は大きな画像が目立つ summary_large_image を採用。
画像が表示されない原因は 相対パス指定 と キャッシュ が多い。
Djangoでは request.build_absolute_uri() をコンテキストプロセッサ経由で使うと便利。
OGP + Twitterカードを正しく設定すれば、SNSでのシェア時に見栄えが格段に良くなる。
自分はDjangoでアプリを作っているので、絶対パスのURLをテンプレートに渡す処理を追加しましたが、
フレームワークを使っていない方でも HTMLに正しくmetaタグを書けばOK です。