Headless CMSのSEO

Headless CMSのSEOは、フロントエンドがどのようにレンダリングするかにかかっています。SSG/SSRとCSR、メタデータ、canonical、サイトマップ、ISRの落とし穴、AIクローラー、移行を解説します。

初回公開:2026年6月25日 · 最終更新:2026年8月21日 · Advanced
言語
このページには証拠シグナルが1件あります

Headless CMSはSEOに良いとも悪いとも限りません。フロントエンドが使うレンダリング方式がすべてを決めます。SSGとSSRは安全な選択肢で、CSRはリスクがあり、ISRには古いコンテンツの落とし穴があります。WordPressプラグインが自動で行っていたメタデータ、サイトマップ、canonical、robots.txtは、明示的に構築する必要があります。レンダリングを正しくし、プレビュー環境をインデックスから外し、放置されたWordPressサイトをHeadless CMSで上回れる状態にします。

要点 — ヘッドレスSEOでは、アーキテクチャそのものがプロダクトです。CMSバックエンドはSEOにほぼ中立であり、すべてを決めるのはフロントエンドのレンダリング方式です。SSGとSSRは完成済みのHTMLを配信する安全な選択肢で、CSRは最もリスクが高く、ISRには再検証後の最初のリクエストで古い内容を返す落とし穴があります。Yoastが自動処理していたメタデータ、canonical、サイトマップ、robots.txtは明示的に実装する必要があります。canonicalのロジックはCMS → フレームワーク → コンポーネントに分散しやすいため、単一のSITE_URLを使ってレンダリング層で設定します。同じ役割分担はロケールルーティング/hreflangやプレビューへのアクセスにも当てはまります(まず認証し、noindexはアクセス制御ではなく二次的な防御とする)。Googleは動的レンダリングを非推奨とし、SSR/SSG/ハイドレーションを推奨しています。AIクローラーのレンダリング能力はプロバイダーごとに異なり、公開/非公開イベントではタイマーではなくWebhookでキャッシュをパージする必要があります。

アーキテクチャがプロダクトを決める

ヘッドレスCMSは、コンテンツの保存、コンテンツモデル、編集UI、APIを備えたバックエンドにすぎません。Next.js、Nuxt、Gatsby、Astro、SvelteKit、Remixなどのフロントエンドは別のアプリケーションで、RESTまたはGraphQL経由でコンテンツを取得し、レンダリングします。ここで最も役立つ考え方は、選んだCMSがSEOに直接与える影響はほとんどなく、すべてを決めるのはフロントエンドのレンダリング判断であるということです。ヘッドレスSEOの議論は、常に「フロントエンドはこのコンテンツをどのようにレンダリングしているか」という問いから始めるべきです。 Evidence for this claim A headless CMS supplies content through APIs while a separate frontend controls how pages are rendered. Scope: Contentful as a representative headless CMS architecture. Confidence: high · Verified: Contentful: What is a headless CMS?

したがって、「ヘッドレスはSEOに悪い」という捉え方は適切ではありません。ヘッドレス自体は中立です。SSRまたはSSGを使い、メタデータを厳密に管理したヘッドレスサイトは、放置されたWordPressサイトより高い成果を出せます。一方、クライアントサイドレンダリングを初期設定のまま使い、メタデータ層を再実装しなかったサイトは、気づかないうちに崩れていきます。私のJavaScript SEOガイド でも述べているとおり、WebはプレーンHTMLだけの世界から移行しました。SEO担当者はその変化に抗うのではなく、受け入れて活用できます。

CMS、API、フロントエンドの担当範囲

「CMSはSEOにほぼ中立」という理解は正しいものの、担当範囲を明確にしなくてよいという意味ではありません。コンテンツモデルが保存するのは、構造化されたタイプとフィールドだけです。それだけでは、タイトル、canonical、schema、リンクが実際に出力される保証にはなりません。フロントエンドが役割を果たして初めて出力されます。 Evidence for this claim A headless CMS content model defines structured types and fields, but the consuming frontend owns URL routing and the rendered HTML that titles, canonicals, schema, and links depend on. Scope: Contentful content-model docs plus Next.js metadata docs as representative frontend evidence. Confidence: high · Verified: Contentful: Data model Next.js: Metadata and OG images 責任を明示的に分ければ、私が最もよく目にする2つの失敗を避けられます。1つは誰も担当せず、必要なものが黙って実装されないこと。もう1つは3つの層すべてが自分の担当だと考え、後述するcanonicalのようにロジックが分断されることです。

レイヤー担当するもの担当しないもの
CMSコンテンツモデルタイトル、ディスクリプション、スラッグ、OG画像、robotsの上書きなどを生データとして保持する構造化フィールドフィールドをHTMLへどう出力するか、そもそも出力するかどうか
Delivery API(公開済みコンテンツ)公開済みで本番利用可能なコンテンツだけをライブサイトへ提供することプレビュー/未公開コンテンツ(それらには別のAPIを使う)
Preview/Management API独自のトークン/ホストで保護された未公開コンテンツと下書き本番フロントエンドが参照すべきもの
フロントエンド/ビルド/デプロイ最終的にレンダリングされるHTML:<head>タグ、canonical、サイトマップ、robots.txt、JSON-LD、内部リンク、ロケールルーティングコンテンツの保存(APIを利用する側であり、モデルを定義する側ではない)

呼び出すAPIの種類も区別する必要があります。Delivery、Management、Previewの各APIでは、公開状態と認可の意味が異なります。本番レンダリングでは公開済みコンテンツ用APIだけを使用し、Management APIやPreview APIのトークン/エンドポイントは決して使用しないでください。未公開コンテンツや書き込み権限が公開レスポンスに漏れるおそれがあります。 Evidence for this claim Delivery, management, and preview APIs have different publication and authorization semantics; production rendering must use the published-content API and must not expose management or preview tokens. Scope: Contentful API basics and Preview API docs as representative headless-API evidence. Confidence: high · Verified: Contentful: API basics Contentful: Content Preview API overview

GoogleがJavaScriptページを処理する流れ

GoogleはJavaScriptページを、クロール、レンダリング、インデックス登録の順に処理します。クライアントレンダリングに依存するページでは、最初のHTMLレスポンスに最終的なコンテンツが含まれません。一方、SSRとSSGはブラウザーが実行される前のレスポンスにコンテンツを含めます。 Evidence for this claim Google crawls, renders, and indexes JavaScript pages, while server-side or pre-rendered HTML exposes content in the initial response. Scope: Google Search JavaScript processing; indexing is not guaranteed. Confidence: high · Verified: Google: JavaScript SEO basics

大規模サイトでは、関連する2つの事実が重要です。Googleはブロックされたファイル内のJavaScriptをレンダリングできないため、必要な.js.cssリソースはクロール可能にしておく必要があります。また、JavaScriptのレンダリングには実際に大きなコストがかかります。Ahrefsでは1日に数十億ページをクロールしていますが、JavaScriptページのレンダリングはインフラの相当な部分を消費します。「Googlebotはレンダリングできる」と「Googlebotにレンダリングさせるべき」は同じではありません。

AIクローラーの実情

これは、ヘッドレスSEOの助言で見落とされがちな2026年の論点です。ChatGPT、Perplexityなどの背後で動く取得ボットを含め、ほとんどのAIクローラーはJavaScriptを実行しません。Vercelの調査は、いずれもクライアントサイドのコンテンツをレンダリングしないと端的に示しています。重要なページがJavaScript依存のSPAとして配信されている場合、AI検索からは実質的に見えません。Googleのレンダリングチームは、ほぼすべてのHTMLページをレンダリングすると述べていますが、それはGoogleの話です。AIでの可視性を得るうえで、SSR/SSGは「あればよい」ものではなく、参加条件です。

4つのレンダリング方式

SSG — Static Site Generation。 ビルド時にHTMLを生成し、CDNから静的ファイルとして配信します。最初のリクエストで完成済みのHTMLを返し、TTFBも非常に短いため、SEOでは最良の状態です。代償は更新性で、新規または変更されたコンテンツには再ビルドが必要になり、大規模サイトではビルドに時間がかかります(ISRはこの問題を一部解決します)。GatsbyとAstroはSSG中心で、Next.jsはルートごとに対応し、Hugoは代表的な例です。

SSR — Server-Side Rendering。 リクエストごとに、サーバーまたはエッジ関数でHTMLをレンダリングします。常に最新で完成済みのHTMLを最初のリクエストに返すため、SEOに非常に適しています。静的ファイルよりインフラコストが高く、TTFBがやや長くなる点が代償です。Next.js、Nuxt、SvelteKit、Remixはいずれも対応しています。

ISR — Incremental Static Regeneration。 再検証間隔を過ぎた後、バックグラウンドで静的ページを再生成します。通常はSEOに適していますが、次のセクションで説明する重要な落とし穴が1つあります。主にNext.jsの機能で、Nuxtにも類似機能があります。

CSR — Client-Side Rendering。 最小限のHTMLシェルを配信し、その後ブラウザーのJavaScriptがコンテンツを取得してDOMを構築します。SEOでは最も不利な選択肢です。Googlebotはページをレンダリング待ちのキューに入れる必要があり、処理時期を予測できません。AIクローラーや多くのボットには空のシェルしか見えません。CSRが適しているのは、ログインで保護され、そもそもインデックス登録すべきでない高度にインタラクティブなダッシュボードや認証専用ページです。見つけてほしいコンテンツには適していません。Next.js/Nuxtを使わない素のReactまたはVueのSPAは、初期状態ではここに該当します。

ISRで古いコンテンツが返る落とし穴

ISRの仕組みには、独立したセクションで扱う価値がある特有の問題があります。再検証期間が切れると、次のように動作します。

  1. 次に届いたリクエストがバックグラウンドでの再生成を開始する。
  2. そのリクエスト(Googlebotかもしれない)には、古いキャッシュページが返される
  3. 新しいバージョンが配信されるのは、そののリクエストからである。

クロール頻度の高いページでは、Googlebotが常に1回分の再検証サイクルだけ古いコンテンツを見る可能性があります。価格や在庫数など、本当に変動が激しいデータにはSSRのほうが安全です。ISRは、秒単位ではなく数時間または数日単位で変わるコンテンツに適した中間案です。

動的レンダリングは非推奨

数年前、私が2019年ごろに行った講演を含め、PuppeteerやRendertronのような仕組みでボットに事前レンダリング版を返す動的レンダリングは、妥当な回避策でした。しかし、Googleはその後この方針を変更しました。 公式文言は、“dynamic rendering was a workaround and not a long-term solution,” (翻訳) 「動的レンダリングは回避策であり、長期的な解決策ではなかった」、また*“creates additional complexities and resource requirements.”* (翻訳) 「複雑さとリソース要件をさらに増やす」です。Googleは現在、代わりにサーバーサイドレンダリング、静的レンダリング、またはハイドレーションを推奨しています。ここには注意点があります。動的レンダリングは自動的にクローキングとみなされるわけではなく、存在するだけでGoogleからペナルティを受けることもありません。ユーザーとクローラーにまったく異なるコンテンツを返した場合に初めてクローキングになります。「クローキングではない」と「公式に非推奨」は同時に成り立ちます。新規構築では採用しないでください。

メタデータ:プラグインが行っていた処理を再実装する

WordPressでは、YoastやRank Mathが各ページのタイトルとディスクリプションを自動生成していました。ヘッドレスにはプラグイン層がないため、次の作業を明示的に行います。

  1. CMSのコンテンツモデルにSEOフィールドを追加する — タイトル、ディスクリプション、robotsの上書き、canonicalの上書き、Open Graphフィールド。
  2. 各ページテンプレートの<head>へフィールドを割り当てる — APIレスポンスから値を取得して出力します。
  3. フレームワーク標準のhead管理を使う — Next.jsのgenerateMetadata(App Router)またはmetadataエクスポート、NuxtのuseSeoMeta、Gatsbyの<Seo>コンポーネント/react-helmet、Astroのレイアウトファイル内の<head>

よくある不具合には、クライアントサイドで挿入したメタデータが最初ではなくレンダリング後に認識されること、共有レイアウトのcanonicalがページごとに更新されず、すべてがホームページをcanonicalにしてしまうこと、Next.js App RouterでmetadataBaseがなく相対canonical URLが壊れることがあります。信頼性の原則は単純です。HTMLに含まれるメタデータは、Googleが最初の取得時に認識できるため、JavaScriptで挿入するメタデータより確実です。HelmetやHeadのようなモジュールを使っても構いませんが、重要なタグはサーバーでレンダリングしたHTMLに含めてください。

コンテンツモデルには、単にフィールドを用意するだけでなく規則も必要です。そうしないと、前述のマッピング処理が気づかないうちに壊れます。

  • フィールドごとに必須/任意を決める。 タイトルとcanonicalの上書きは必須(または自動導出)にし、空の<title>で公開されないようにします。ディスクリプションとOGフィールドは、フロントエンドのフォールバックを用意したうえで任意にできます。
  • フォールバックの順序を定義する。 SEOフィールドが空の場合に何を代入するか(ディスクリプションには本文抜粋、タイトルにはH1など)を事前に決め、テンプレートごとに場当たり的に処理せず、マッピング層で実装します。
  • ロケールのフォールバックとフィールドのフォールバックを分ける。 翻訳がない場合、コンテンツAPIは既定ロケールの値を代入できます。本文では便利ですが、SEOフィールドが別ロケールのタイトル/ディスクリプションへ黙ってフォールバックするのは通常誤りであり、別途警告すべきです。
  • マッピング時にエスケープする。 CMSのテキストフィールドではHTMLやリッチテキストを許可することがよくあります。<title><meta>、JSON-LD文字列へ入れる前に除去またはエスケープしないと、マークアップが壊れ、悪い場合はスクリプトが挿入されます。
  • ルート種別ごとに受け入れテストを行う。 公開前に、通常のエントリ、任意フィールドが空のエントリ、指定ロケールの翻訳がないエントリについて、レンダリングされた<head>を確認します。正常系だけのテストでは捉えられない3つの異なるコードパスです。

ヘッドレス特有のリスク:canonicalの分断

WordPressではcanonicalは1か所にあります。ヘッドレスでは、CMSがスラッグを保存し、フレームワークがスラッグと環境設定から完全なURLを組み立て、コンポーネント<link rel="canonical">タグを出力するという3つの層に分かれます。スラッグの変更、ルートパターンの変更、コンポーネントのリファクタリングなどでどれかの層がずれると、canonicalが存在しないURLを指すことがあります。以前のGoogleはJavaScriptで挿入したcanonicalを認識しませんでした。現在は一部で緩和されていますが、HTMLに含まれるcanonicalのほうがはるかに確実であり、競合するタグが複数あるとGoogleに選択を委ねることになります。

修正方法: canonicalのロジックはCMS内ではなくレンダリング層(フレームワーク)で一元管理し、単一のSITE_URL環境変数から絶対URLを生成します。信頼できる情報源は1つにし、常に絶対URLを使い、相対URLは使いません。

ロケールの担当範囲:APIフォールバックとフロントエンドルーティング

複数ロケールのヘッドレスサイトでも、canonicalと同様に担当範囲が混乱しがちです。コンテンツAPIのロケール選択とフォールバックは、リクエストされたロケールのコンテンツ、または設定済みの代替値を返すというフィールド値の置換を行えます。しかし、これはデータ置換機能であってSEO機能ではありません。 Evidence for this claim Content API locale selection and fallback can substitute field values, but the frontend still owns locale URLs, canonicals, hreflang, x-default, and language negotiation. Scope: Contentful localization docs plus Google rendering/canonical guidance. Confidence: high · Verified: Contentful: Localization Google: JavaScript SEO basics 検索に関わる次の要素は、引き続きフロントエンドが担当します。

  • ロケール別URL。 ロケールをパス(/es/page)、サブドメイン、別ドメインのどこに置くかはフロントエンドのルーティング判断です。APIはURLを生成しません。
  • ロケールごとのcanonical。 各ロケール版は、すべて既定ロケールを指すのではなく、それぞれ自分自身をcanonicalにします。
  • hreflangx-default フロントエンドが把握するロケールルートから代替言語リンク一式を生成し、該当しない言語向けのx-defaultも含めます。APIにはhreflangの概念がありません。
  • コンテンツネゴシエーションとステータスの挙動。 あるエントリに存在しないロケールがリクエストされた場合、既定ロケールへリダイレクトする、そのロケールのURLでフォールバックコンテンツを返す、実際の404を返す、のいずれかを意図的に決め、一貫して適用します。Googleにとって「APIが英語テキストを黙って代入した」と「このロケール版は存在しない」は異なる状況であり、必要なHTTPステータスコードも異なります。

実務上の落とし穴は、APIレベルのフォールバックによって、翻訳が欠けていてもCMSプレビューでは問題がないように見えることです。常に何らかのコンテンツが表示され、空のフィールドが見えないため、ロケールの欠落は編集上の警告より先にSEO問題として表面化しがちです。たとえば、誤った言語のタイトルが不適切なhreflangの下でインデックス登録されたり、ロケール間の重複コンテンツが発生したりします。

サイトマップとrobots.txt

Yoastがなければ、サイトマップも自動では作られません。プログラムで生成してください。Next.js App Routerでは、/sitemap.xmlを、ビルド時またはリクエスト時にCMSへ問い合わせるsitemap.tsファイルから生成できます。Nuxtにはサイトマップモジュール、Gatsbyにはgatsby-plugin-sitemap、Astroには@astrojs/sitemapがあります。公開頻度の高いサイトでは、ビルド時に生成した静的サイトマップが古くなる点が落とし穴です。コンテンツタイプ別に分割し、ISRで再生成するサイトマップを使います。

robots.txtも明示的に用意する必要があります。/public内の静的ファイル、または生成ルート(Next.jsのrobots.ts)として作成します。絶対に誤ってはいけない原則は、.js.cssをdisallowしないことです。ブロックするとレンダリングそのものができなくなります。

公開状態との同期を保つ

キャッシュと再検証は、パフォーマンスだけでなく編集内容の正確性に関わる問題です。時間、タグ、パスに基づく無効化は、設計どおりであっても古いコンテンツを配信することがあります。そのため、公開操作はCMSだけでなく、コピーをキャッシュしたすべての層へ届く必要があります。 Evidence for this claim Time-, tag-, and path-based cache invalidation can serve stale content by design, so publish, unpublish, rename, and locale changes need webhook-triggered purge and rollback handling, not a fixed timer. Scope: Next.js current cache/revalidation model. Confidence: high · Verified: Next.js: Revalidating 公開前に、公開、非公開化、名前/スラッグ変更、ロケール更新という4つのイベントで次の各項目がどう動くかを書き出し、テストしてください。

  • 対象エントリのAPI/CDNキャッシュ
  • フレームワークのページキャッシュ(ISR/オンデマンド再検証、タグまたはパス単位)。
  • フロントエンド手前のCDNエッジキャッシュ
  • サイトマップ — エントリの追加、削除、新URLでの再掲載。
  • メタデータ — 古いcanonical/URLを完全に廃止し、新URLと並行して解決可能なまま残さない。
  • ロールバック — 公開を取り消した場合、前方向だけでなく逆方向にもパージが動くことを確認する。

トリガーには固定タイマーではなく、CMSの公開/非公開イベントから送るWebhookを使い、フレームワークのタグまたはパス単位の再検証(revalidateTagrevalidatePath、または同等機能)を呼び出します。タイマー方式では、4つのイベントすべてが即時反映されず、次の周期まで待つことになります。

内部リンクと構造化データ

内部リンクは実際の<a href>タグでなければなりません。JavaScriptで遷移する<div onClick><span>クロールできません。Googlebotがたどるのは本物のアンカーだけです。また、JavaScriptでレンダリングされるリンクはレンダリング段階まで発見されず、遅延が生じます。API駆動のコンテンツは、それだけではリンク構造を作りません。関連記事、パンくずリスト、本文内リンクはすべてコンポーネント層で実装する必要があります。

構造化データは、WordPressよりヘッドレスのほうが簡単になり得る珍しい領域です。JSON-LDをサーバーでレンダリングした<head>へ直接入れれば、クライアントバンドルの負荷はなく、コードでバージョン管理でき、プラグイン同士の競合もありません。コンテンツサイトで一般的なArticle/BlogPosting、BreadcrumbList、FAQPage、Organizationはいずれも利用できます。JavaScriptの挿入タイミングでテスト結果が変わる可能性があるため、レンダリングを変更した後はリッチリザルトテストで確認してください。

プレビュー環境とステージング環境

ヘッドレス構成では、プレビューURLやブランチデプロイURL(Vercel/Netlifyのプレビューデプロイ、CMSの下書きエンドポイント)が生成され、それらが公開アクセス可能なことも少なくありません。Googleにインデックス登録されると、別ホスト上にサイト全体の重複コピーがあるように見えます。対策は、ホストレベルでnoindex HTTPヘッダーを適用すること(CSRページが後から挿入するメタタグだけに頼らず、環境設定で行う)、署名付きトークンでプレビューを保護すること、ステージングが自己参照canonicalを出さないよう環境別canonicalを設定すること、短命なプレビューホストを使うことです。Search Consoleで予期しないドメインが現れていないか監視すると、早期警告になります。

防御の順序を正しくしてください。最初にnoindexを設定して終わりにしがちですが、noindexが機能するには、Googleがページをクロールしてタグを確認できる必要があります。これはインデックス登録に関する依頼であり、アクセス制御ではありません。ページが公開アクセス可能なら、執拗なクローラーや漏えいしたリンクへの対策にはなりません。 Evidence for this claim A noindex rule is not access control and requires Google to crawl the page to see it; private headless previews should be authenticated first, with noindex as a secondary indexing safeguard. Scope: Google noindex documentation plus Contentful/Sanity preview-token separation as representative platform evidence. Confidence: high · Verified: Google: Block Search indexing with noindex Sanity: Presenting and previewing content 本当の境界は、さらに上流に置く必要があります。

  1. まず認証する。 プレビュー環境は、何かを返す前に署名付きトークンまたはログインを要求すべきです。noindexは、どうしてもアクセス可能にする必要があるページ向けの二次的な安全策であり、主要な制御ではありません。
  2. 環境ごとにトークンとホストを分ける。 プレビューと本番でAPIトークンやホスト名を共有してはいけません。未公開コンテンツを参照できるのはプレビュー用トークンだけであり、本番ビルドに混入させてはいけません。
  3. 正しいコンテンツ視点を問い合わせる。 本番コードは公開済みコンテンツだけを問い合わせ、下書き/プレビュー視点を使うのはプレビュー環境だけにします。逆にすると、認証とnoindexの両方があっても、本番から未公開エントリが漏れる可能性があります。

BingとIndexNow

Bingbotは現在、Googlebotと同じWebプラットフォーム技術であるMicrosoft Edge(Chromium)を使ってJavaScriptをレンダリングします。ただし、Googleほど一貫していません。Screaming Frogのテストでは、BingのJavaScriptインデックス登録は*“far from reliable,”* (翻訳) 「信頼できる状態にはほど遠い」とされ、結論も率直です。“if you care about SEO and sleeping at night, don’t rely on client-side rendering.” (翻訳) 「SEOと安心して眠ることを大切にするなら、クライアントサイドレンダリングに頼らないこと」。Bingからのトラフィックが重要なら、SSR/SSGはさらに重要です。

Bingはプッシュ型モデルも重視しています。ヘッドレスのコンテンツ更新はAPIを通るため、WordPressプラグインのようにBingへ通知しません。そこでIndexNowが特に役立ちます。CMSの公開WebhookにIndexNowのトリガーを接続し、変更URLを即時通知してください。Fabrice Canelが示すクロール効率の考え方も重要です。URLは少なく、整理されているほうがよいため、API駆動のファセットナビゲーションによってcanonicalのないパラメーターURLを何千件も生成しないようにします。

トラフィックを失わずにヘッドレスへ移行する

ヘッドレスSEOが実際に失敗しやすいのは移行時です。業界分析では、WordPressからヘッドレスへの移行で大幅なトラフィック減少と長期の回復が頻繁に報告されています。約50%の減少や約523日の回復といった数値は、正確な予測値ではなく、失敗した移行がどれほど深刻になり得るかを示す方向性のある警告として扱ってください。根本原因は予測できます。壊れた301(特に忘れられがちなカテゴリ、タグ、ページ分割されたアーカイブ)、引き継がれなかったメタデータ、気づかないうちにCSRになったレンダリング方式です。投稿だけでなくすべてのURLを棚卸しし、公開前に完全な301マップを作成し、新フロントエンドのメタデータとcanonicalを確認します。公開前後にScreaming Frogのクロールを比較し、GSCとBing Webmaster Toolsの両方へサイトマップを再送信し、IndexNowを導入してください。完全な一覧は移行チェックリストタブを参照してください。

関連資料はJavaScript SEOレンダリングのトピックにあります。ヘッドレスSEOは、実質的にはこの2つを特定用途へ応用したものです。

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.