Adobe Experience Manager as a Cloud Service の SEO および URL 管理のベストプラクティス seo-and-url-management-best-practices-for-aem

検索エンジン最適化(SEO)は、多くのマーケターにとって重要な課題となっています。その結果、多くの Adobe Experience Manager(AEM)as a Cloud Service プロジェクトで SEO の懸念に対処する必要があります。

このドキュメントでは、まず、AEM as a Cloud Service の実装でこうした目的を達成するための SEO のベストプラクティスおよびレコメンデーションを説明します。その次に、最初の節で提示するより複雑な実装手順のいくつかについて詳しく説明していきます。

SEO のベストプラクティス seo-best-practices

このセクションでは、SEO の一般的なベストプラクティスを説明します。

URL urls

URL には、認められているベストプラクティスがいくつかあります。

AEM プロジェクトで URL を評価するときには、次のことを確認してください。

「ユーザーがこの URL を閲覧する際にページ上にコンテンツが何もない場合、このページの内容を説明できますか?」

答えが「はい」であれば、その URL は検索エンジンに効果があります。

SEO に対応した URL を作成する方法について、一般的なヒントを紹介します。

  • ハイフンを使用して単語を区切ります。

    • ページに名前を付けるときには、ハイフン(-)を区切り文字として使用します。
    • キャメルケース、アンダースコアおよびスペースの使用は避けます。
  • 可能な場合、クエリパラメーターの使用は避けます。必要な場合は、パラメーターを 2 つ以下に制限します。

    • 可能であればディレクトリ構造を使用して情報アーキテクチャを示します。
    • ディレクトリ構造を使用できない場合は、クエリ文字列の代わりに、Sling セレクターを URL で使用します。Sling セレクターを使用すると、提供される SEO 値に加えて、Dispatcher でページをキャッシュできるようになります。
  • ユーザーにとって URL がわかりやすいほど、効果的です。URL にキーワードを含めると、価値が高まります。

    • ページでセレクターを使用する場合は、セマンティック値を提供するセレクターが推奨されます。
    • 人間が理解できない URL は、検索エンジンでも理解できません。
    • 次に例を示します。
      mybrand.com/products/product-detail.product-category.product-name.html
      の方が mybrand.com/products/product-detail.1234.html より望ましい
  • 検索エンジンではサブドメインは異なるエンティティとして扱われ、サイトの SEO 値が分断されるので、可能な限りサブドメインの使用は避けてください。

    • 代わりに、第 1 レベルのサブパスを使用します。例えば、es.mybrand.com/home.html の代わりに、www.mybrand.com/es/home.html を使用します。

    • このガイドラインに従って、コンテンツの表示形態に合うようにコンテンツ階層を計画します。

  • URL が長く、キーワードの位置が後ろになるほど、URL におけるキーワードの効果は低下します。つまり、短い方が良いのです。

    • AEM で提供されている URL 短縮の手法や機能を使用して、不要な URL 部分を削除します。
    • 例えば、mybrand.com/content/my-brand/en/myPage.html より mybrand.com/en/myPage.html を選択します。
  • 正規 URL を使用します。

    • 複数のパスから、または複数のパラメーターやセレクターで 1 つの URL を提供できない場合は必ず、ページで rel=canonical タグを使用します。

    • これは、AEM テンプレートのコードに含めることができます。

  • 可能な限り、URL をページタイトルに一致させます。

    • この手法に従うように、コンテンツ作成者に勧めてください。
  • URL リクエストで大文字と小文字を区別しないことをサポートします。

    • すべての受信要求を小文字として書き換えるように Dispatcher を設定します。
    • 小文字を使用してすべてのページを作成するようにコンテンツ作成者をトレーニングします。
  • 各ページを 1 つのプロトコルで提供するようにします。

    • ユーザーがチェックアウトやログインフォームなどを使用してページに到達するまでは、サイトが http 経由で提供されることがありますが、到達した時点で https に切り替わります。このページからリンクするときに、ユーザーが http ページに戻り、https 経由でそれらのページにアクセスできる場合、検索エンジンは、2 つの異なるページとして追跡します。

    • Google では現在、https ページの方が http ページよりも推奨されています。そのため、多くの場合、サイト全体を https で配信する方が問題が少なくなります。

サーバーの設定 server-configuration

サーバーの設定に関しては、次の手段を講じることで、適切なコンテンツのみがクロールされるようにすることができます。

  • robots.txt ファイルを使用して、インデックスを作成する必要がないコンテンツのクローリングをブロックします。

    • テスト環境では​ すべて ​のクローリングをブロックします。
  • 更新した URL を使用して新しいサイトの運用を開始する場合は、既存の SEO ランキングが失われないように 301 リダイレクトを実装します。

  • サイトの favicon を含めます。

  • XML サイトマップを実装して、検索エンジンがコンテンツをより簡単にクロールできるようにします。モバイルサイトやレスポンシブサイトの場合は、必ずモバイルサイトマップを組み込みます。

AEM の設定 aem-configurations

ここでは、SEO に関する前述のレコメンデーションに従って AEM を設定するために必要な実装手順を説明します。

Sling セレクターの使用 using-sling-selectors

これまで、エンタープライズ web アプリケーションを構築する場合、クエリパラメーターを使用するのが認められた手法でした。

最近の傾向では、URL をより読みやすくするために、これらを削除するようになっています。 多くのプラットフォームでは、Web サーバーやコンテンツ配信ネットワーク(CDN)へのリダイレクトの実装などが行われますが、Sling を使用すると簡単です。Sling セレクター:

  • URL のわかりやすさが向上します。
  • Dispatcher でページをキャッシュでき、多くの場合、セキュリティが強化されます。
  • 汎用サーブレットを使用してコンテンツを取得する代わりに、コンテンツを直接アドレス指定できます。これにより、リポジトリに適用する ACL や、Dispatcher で適用するフィルターを活用できます。

サーブレットでのセレクターの使用 using-selectors-for-servlets

AEM では、サーブレットを作成するときに次の 2 つのオプションが用意されています。

  • bin サーブレット
  • Sling サーブレット

次に示す各例では、この両方のパターンに準拠したサーブレットを登録する方法とともに、Sling サーブレットを使用することによって得られる利点を説明します。

bin サーブレット(1 レベル下) bin-servlets-one-level-down

bin サーブレットは、多くの開発者が使い慣れている J2EE プログラミングのパターンに準拠しています。このサーブレットは、特定のパスに登録されます。AEM の場合は通常 /bin に登録され、必要な要求パラメーターをクエリ文字列から抽出します。

このタイプのサーブレットの SCR 注釈は、次のようになります。

@SlingServlet(paths = "/bin/myApp/myServlet", extensions = "json", methods = "GET")

続いて、SlingHttpServletRequest メソッドに含まれる doGet オブジェクトを使用して、クエリ文字列からパラメーターを抽出します。次に例を示します。

String myParam = req.getParameter("myParam");

使用される結果の URL は次のようになります。

https://www.mydomain.com/bin/myApp/myServlet.json?myParam=myValue

このアプローチで考慮すべき点は次のとおりです。

  • URL 自体から SEO 値が失われます。URL は、コンテンツ階層ではなく、プログラムにおけるパスを表すので、検索エンジンを含め、サイトにアクセスするユーザーが URL からセマンティック値を受け取ることはありません。
  • URL にクエリパラメーターが含まれていることは、Dispatcher で応答をキャッシュできないことを意味します。
  • このサーブレットを保護するには、独自のカスタムセキュリティロジックをサーブレットに実装する必要があります。
  • /bin/myApp/myServlet を公開するように Dispatcher を(慎重に)設定する必要があります。単に /bin を公開すると、サイト訪問者に公開してはいけない特定のサーブレットへのアクセスが許可されます。

Sling サーブレット(1 レベル下) sling-servlets-one-level-down

Sling サーブレットを使用すると、サーブレットを逆の方法で登録できます。サーブレットをアドレス指定し、クエリパラメーターに基づいてサーブレットでレンダリングするコンテンツを指定するのではなく、目的のコンテンツをアドレス指定し、Sling セレクターに基づいてコンテンツをレンダリングするサーブレットを指定します。

このタイプのサーブレットの SCR 注釈は、次のようになります。

@SlingServlet(resourceTypes = "myBrand/components/pages/myPageType", selectors = "myRenderer", extensions = "json", methods="GET")

この場合、URL によってアドレス指定されるリソース(myPageType リソースのインスタンス)にサーブレットで自動的にアクセスできます。アクセスするには、次を呼び出します。

Resource myPage = req.getResource();

使用される結果の URL は次のようになります。

https://www.mydomain.com/content/my-brand/my-page.myRenderer.json

このアプローチの利点は次のとおりです。

  • サイト階層とページ名に存在するセマンティクスで取得した SEO 値でベイク処理できます。
  • クエリパラメーターがないので、Dispatcher で応答をキャッシュできます。また、アドレス指定されたページが更新されていると、ページがアクティブ化されたときにこのキャッシュが無効になります。
  • ユーザーがこのサーブレットにアクセスしようとすると、/content/my-brand/my-page に適用されているすべての ACL が有効になります。
  • Dispatcher は、web サイトを提供する機能の 1 つとしてこのコンテンツを提供するようにあらかじめ設定されます。追加の設定は必要ありません。

URL の書き換え url-rewriting

AEM では、すべての Web ページが /content/my-brand/my-content に保存されます。これは、リポジトリーデータ管理の観点では便利な場合がありますが、必ずしもこの方法で顧客にサイトを表示するわけではなく、URL をできるだけ短くするという SEO のガイダンスと矛盾する可能性があります。また、同じ AEM インスタンスや異なるドメイン名から複数の web サイトを提供している場合もあります。

この節では、これらの URL を管理し、よりわかりやすく、SEO に適した方法で URL をユーザーに表示するために AEM で使用可能なオプションを説明します。

バニティ URL vanity-urls

作成者が、プロモーション目的で別の場所からアクセス可能なページを作成する場合、ページごとに定義される AEM のバニティー URL が役立つことがあります。ページのバニティー URL を追加するには、 Sites コンソールで該当するページに移動し、ページのプロパティを編集します。「基本」タブの下部に、バニティー URL を追加できるセクションが表示されます。複数の URL を使用してページにアクセスできるようにすると、ページの SEO 値が分断されるので、正規 URL タグをページに追加して、この問題を回避する必要があることに留意してください。

ページ名のローカライズ localized-page-names

翻訳されたコンテンツのユーザーには、ローカライズされたページ名を表示した方がよい場合があります。次に例を示します。

  • スペイン語を話すユーザーが次のページにアクセスするとします。
    www.mydomain.com/es/home.html

  • この場合、URL を次のように表示した方が効果的です。
    www.mydomain.com/es/casa.html

ページ名をローカライズする際の課題は、AEM プラットフォームで利用できるローカライズツールの多くが、コンテンツの同期を保つためにロケール間でページ名を一致させる必要があることです。

sling:alias プロパティを使用すると、両方を同時に実現できます。sling:alias を任意のリソースにプロパティとして追加すると、リソースのエイリアス名を使用することができます。前述の例では、次のようになります。

  • JCR の次の場所にページがあるとします。
    …/es/home

  • プロパティを追加します。
    sling:alias = casa

これにより、マルチサイトマネージャーなどの AEM 翻訳ツールでは、次のページ間の関係を引き続き維持できます。

  • /en/home

  • /es/home

また、エンドユーザーもページ名を母国語で操作できます。

NOTE
sling:alias プロパティは、ページプロパティ編集時のエイリアスプロパティを使用して設定できます。

/etc/map etc-map

標準 AEM インストールでは、

  • OSGi 設定には
    Apache Sling Resource Resolver Factory
    ( org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl)

  • プロパティ
    マッピング場所resource.resolver.map.location

  • デフォルト /etc/map に設定。

AEM で受信要求のマッピングまたはページ上の URL の書き換え、あるいはその両方を行うために、この場所にマッピング定義を追加できます。

マッピングを作成するには、この場所の /http または /https の下に新しい sling:Mapping ノードを作成します。このノードで設定された sling:match および sling:internalRedirect プロパティに基づいて、AEM は、一致した URL のすべてのトラフィックを internalRedirect プロパティで指定された値にリダイレクトします。

これは、AEM および Sling の正式なドキュメントに記載されているアプローチですが、この実装で提供される正規表現のサポートは、SlingResourceResolver を直接使用することによって利用可能なオプションと比べると、範囲が限られています。また、この方法でマッピングを実装すると、Dispatcher のキャッシュの無効化に関する問題が生じることがあります。

次に、この問題がどのように生じるかについて例を示します。

  1. ユーザーが Web サイトを訪問し、https://www.mydomain.com/my-page.html を要求します。

  2. Dispatcher が、このリクエストを公開サーバーに転送します。

  3. 公開サーバーが /etc/map を使用して、このリクエストを /content/my-brand/my-page に解決し、ページをレンダリングします。

  4. Dispatcher が /my-page.html に応答をキャッシュし、応答をユーザーに返します。

  5. コンテンツ作成者がこのページを変更し、アクティブ化します。

  6. Dispatcher フラッシュエージェントが /content/my-brand/my-pageの無効化リクエストを送信します。 Dispatcher はこのパスにページをキャッシュしていないので、古いコンテンツがキャッシュされたままになり、更新されません。

キャッシュの無効化のために、短い URL を長い URL にマッピングするカスタムのディスパッチフラッシュルールを設定する方法があります。

ただし、これをより簡単に管理する次のような方法もあります。

  1. SlingResourceResolver ルール

    Web コンソール(localhost:4502/system/console/configMgr など)を使用して、Sling Resource Resolver を設定できます。

    • Apache Sling Resource Resolver Factory
      (org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl)

    URL を短縮するために必要なマッピングを正規表現として構築した後、ビルドに含まれている OsgiConfignode の config.publish でこれらの設定を定義することをお勧めします。

    /etc/mapマッピングを定義する代わりに、プロパティ URL Mappingsresource.resolver.mapping)に直接割り当てることができます。

    code language-xml
    resource.resolver.mapping="[/content/my-brand/(.*)</$1]"
    

    この簡単な例では、URL に /content/my-brand/ が存在する場合、URL の先頭から削除されます。

    これにより、URL は次のように変換されます。

    • /content/my-brand/my-page.html から
    • ただの /my-page.html

    これは、URL をできるだけ短く維持するという推奨事項に準拠しています。

  2. ページに出力される URL のマッピング

    Apache Sling Resource Resolver でマッピングを定義したら、ページに出力する URL が短く、適切になるように、それらのマッピングをコンポーネントで使用する必要があります。そのためには、ResourceResolver のマッピング関数を使用します。

    例えば、現在のページの子をリストアウトするカスタムナビゲーションコンポーネントを実装している場合、次のようなマッピングメソッドを使用できます。

    code language-none
    for (Page child : children) {
      String childUrl = resourceResolver.map(request, child.getPath());
      //Output the childUrl on the page here
    }
    

Apache HTTP サーバーの mod_rewrite apache-http-server-mod-rewrite

これまでに、URL をページに出力するときに、定義したマッピングを使用するために、マッピングをロジックとともにコンポーネントに実装しました。

最後の手順は、短縮された URL の Dispatcher での処理です。ここでは、mod_rewrite を使用します。mod_rewrite を使用する最大の利点は、URL が Dispatcher モジュールに送信される​ ​に長い形式に再びマッピングされる点です。つまり、Dispatcher は公開サーバーに長い URL をリクエストし、それに応じて URL をキャッシュします。したがって、公開サーバーからの Dispatcher フラッシュはすべて、そのコンテンツを正常に無効にすることができます。

このようなルールを実装するには、Apache HTTP Server の設定で仮想ホストに RewriteRule 要素を追加します。前述の例の短縮された URL を拡張する場合は、次のようなルールを実装できます。

<VirtualHost *:80>
  ServerName www.mydomain.com
  RewriteEngine on
  RewriteRule ^/(.*)$ /content/my-brand/$1 [PT,L]
  …
</VirtualHost>

正規 URL タグ canonical-url-tags

正規 URL タグは、コンテンツのインデックス作成時に検索エンジンでページがどのように処理されるかを明確にするために、HTML ドキュメントの先頭に配置されるリンクタグです。このタグを使用すると、ページの URL に異なる部分が含まれていても、同じものとしてページ(の様々なバージョン)のインデックスが作成されるという利点があります。

例えば、ページのプリンターフレンドリーなバージョンをサイトで提供する場合、検索エンジンでは、通常のバージョンのページとは別に、このページのインデックスが作成される可能性があります。正規タグを使用すると、同じページであることが検索エンジンで認識されます。

例:

  • <https://www.mydomain.com/my-brand/my-page.html>
  • <https://www.mydomain.com/my-brand/my-page.print.html>

両方について、ページの先頭に次のタグを適用します。

<link rel="canonical" href="my-brand/my-page.html"/>

href は、相対パスとして指定することも、絶対パスとして指定することもできます。ページの正規 URL を確認し、このタグを出力するには、このコードをページマークアップに挿入する必要があります。

大文字と小文字を区別しないための Dispatcher の設定 configuring-the-dispatcher-for-case-insensitivity

すべてのページを小文字で提供することがベストプラクティスです。ただし、ユーザーが URL に大文字を使用して web サイトにアクセスしたときに、404 エラーが表示されるのは望ましくありません。こうした理由から、すべての受信 URL を小文字にマッピングするように、Apache HTTP Server の設定に書き換えルールを追加することをお勧めします。また、小文字の名前を使用してページを作成するようコンテンツの作成者をトレーニングする必要があります。

すべての受信トラフィックを強制的に小文字に変換するように Apache を設定するには、次のコードを vhost の設定に追加します。

RewriteEngine On
RewriteMap lowercase int:tolower

また、次のコードを htaccess ファイルの最上部に追加します。

RewriteCond $1 [A-Z]
RewriteRule ^(.*)$ /${lowercase:$1} [R=301,L]

開発環境を保護するための robots.txt の実装 implementing-robots-txt-to-protect-development-environments

検索エンジンは、サイトをクロールする前に、サイトのルートに ファイルがあるかどうかをチェック ​するはずですrobots.txt。ただし、Google、Yahoo、Bing などの主要な検索エンジンではすべてこの点が考慮されるのに対し、なじみのない検索エンジンの中には、この点が考慮されないものもあります。

サイト全体へのアクセスをブロックするための最も簡単な方法は、robots.txt というファイルに次の内容を指定して、サイトのルートに配置することです。

User-agent: *
Disallow: /

また、実稼働環境では、インデックスが作成されないように特定のパスを禁止することもできます。

ただし、robots.txt ファイルをサイトルートに配置すると、Dispatcher フラッシュリクエストによって、このファイルが除去されることがあり、URL マッピングによって、サイトルートが Apache HTTP Server 設定で定義された DOCROOT とは異なる場所に配置される可能性があります。こうした理由から、このファイルをオーサーインスタンスのサイトのルートに配置し、パブリッシュインスタンスにレプリケートするのが一般的です。

AEM での XML サイトマップの作成 building-an-xml-sitemap-on-aem

クローラーでは、web サイトの構造をより的確に把握するために XML サイトマップが使用されます。サイトマップを提供すれば SEO ランキングが上がるという保証はありませんが、ベストプラクティスの 1 つとして認められています。サイトマップとして使用する XML ファイルを web サーバーで手動で管理することもできますが、作成者がコンテンツを作成すると、変更内容がサイトマップに自動的に反映されるように、プログラムによってサイトマップを生成することをお勧めします。

AEM では、Apache Sling Sitemap モジュールを使用して XML サイトマップを生成し、開発者と編集担当者がサイトの XML サイトマップを最新の状態に保つための様々なオプションを提供します。

Apache Sling Sitemap モジュールは、最上位のサイトマップとネストされたサイトマップを区別します。どちらも、sling:sitemapRoot プロパティが true に設定されているリソースについて生成されます。一般に、サイトマップは、ツリーの最上位のサイトマップ(他にサイトマップの上位要素を持たないリソース)のパスにあるセレクターを使用してレンダリングされます。また、この最上位のサイトマップルートはサイトマップのインデックスも公開します。このインデックスは通常、サイト所有者が検索エンジンの設定ポータルで設定したり、サイトの robots.txt に追加したりするものです。

例えば、最上位のサイトマップルートを my-page に定義し、ネストされたサイトマップルートを my-page/news に定義するサイトで、ニュースサブツリーのページ専用のサイトマップを生成するとします。これに、関連する URL は次のようになります。

  • <https://www.mydomain.com/my-brand/my-page.sitemap-index.xml>
  • <https://www.mydomain.com/my-brand/my-page.sitemap.xml>
  • <https://www.mydomain.com/my-brand/my-page.sitemap.news-sitemap.html>
NOTE
セレクター sitemap および sitemap-index は、カスタム実装と干渉する可能性があります。製品機能を使用しない場合は、これらのセレクターを提供する独自のサーブレットを 0 より大きい service.ranking で設定します。

デフォルトの設定では、ページのプロパティダイアログには、ページをサイトマップルートとしてマークオプションがあり、前述したように、ページ自体とその下位要素のサイトマップを生成します。この動作は SitemapGenerator インターフェイスの実装によって実装されており、代替実装を追加することで拡張することができます。ただし、XML サイトマップを再生成する頻度は、コンテンツオーサリングワークフローとワークロードに大きく依存するので、製品には SitemapScheduler 設定は含まれていません。これにより、機能が効果的にオプトインします。

XML サイトマップを生成するバックグラウンドジョブを有効にするには、SitemapScheduler を設定する必要があります。それには、PID org.apache.sling.sitemap.impl.SitemapScheduler の OSGi 設定を作成します。スケジューラー式 0 0 0 * * ? は、1 日 1 回午前 0 時にすべての XML サイトマップを再生成するための開始点として使用できます。

Apache Sling Sitemap - スケジューラー

サイトマップ生成ジョブは、オーサー層のインスタンスとパブリッシュ層のインスタンスの両方で実行できます。ほとんどの場合、適切な正規 URL を生成できるのはパブリッシュ層インスタンスだけなので、パブリッシュ層インスタンスで生成を実行することをお勧めします(Sling リソースマッピングルールは一般にパブリッシュ層インスタンスにのみ存在するため)。ただし、SitemapLinkExternalizer インターフェイスを実装することにより、正規 URL の生成に使用される外部化メカニズムのカスタム実装をプラグインすることは可能です。カスタム実装により、オーサー層インスタンスでサイトマップの正規 URL を生成できる場合は、SitemapScheduler をオーサー実行モードに設定して、XML サイトマップ生成ワークロードをオーサーサービスクラスターのインスタンス全体に分散させることができます。このシナリオでは、未公開のコンテンツ、変更済みのコンテンツ、限られたユーザーグループにのみ表示されるコンテンツの取り扱いには、特に注意が必要です。

AEM Sites には、ページのツリーをトラバースしてサイトマップを生成する SitemapGenerator のデフォルトの実装が含まれています。サイトの正規 URL と(使用可能な場合は)代替言語のみを出力するように事前設定されています。また、必要に応じて、ページの最終変更日を含めるように設定することもできます。その場合は、Adobe AEM SEO - Page Tree Sitemap Generator 設定の「最終変更日を追加」オプションを有効にし、「最終変更ソース」を選択します。サイトマップがパブリッシュ層で生成される場合は、cq:lastModified の日付を使用することをお勧めします。

Adobe AEM SEO - Page Tree Sitemap Generator 設定

サイトマップのコンテンツを制限するには、必要に応じて次のサービスインターフェイスを実装します。

  • SitemapPageFilter を実装することで、AEM Sites 固有のサイトマップジェネレーターで生成された XML サイトマップからページを非表示にすることができます。
  • SitemapProductFilter または SitemapCategoryFilter を実装して、Commerce Integration Frameworks 固有のサイトマップジェネレーターで生成される XML サイトマップから製品やカテゴリをフィルタリングできます。

デフォルトの実装が特定のユースケースで機能しない場合、または拡張ポイントが十分に柔軟性を持たない場合、カスタム SitemapGenerator を実装して、生成されるサイトマップのコンテンツを完全に制御できます。次の例では、AEM Sites のデフォルトの実装ロジックを利用してこれを行う方法を示しています。ResourceTreeSitemapGenerator を開始点として使用して、ページのツリーをトラバースします。

import java.util.Optional;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.sitemap.SitemapException;
import org.apache.sling.sitemap.builder.Sitemap;
import org.apache.sling.sitemap.builder.Url;
import org.apache.sling.sitemap.spi.common.SitemapLinkExternalizer;
import org.apache.sling.sitemap.spi.generator.ResourceTreeSitemapGenerator;
import org.apache.sling.sitemap.spi.generator.SitemapGenerator;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.aem.wcm.seo.sitemap.PageTreeSitemapGenerator;
import com.day.cq.wcm.api.Page;

@Component(
    service = SitemapGenerator.class,
    property = { "service.ranking:Integer=20" }
)
public class SitemapGeneratorImpl extends ResourceTreeSitemapGenerator {

    private static final Logger LOG = LoggerFactory.getLogger(SitemapGeneratorImpl.class);

    @Reference
    private SitemapLinkExternalizer externalizer;
    @Reference
    private PageTreeSitemapGenerator defaultGenerator;

    @Override
    protected void addResource(@NotNull String name, @NotNull Sitemap sitemap, Resource resource) throws SitemapException {
        Page page = resource.adaptTo(Page.class);
        if (page == null) {
            LOG.debug("Skipping resource at {}: not a page", resource.getPath());
            return;
        }
        String location = externalizer.externalize(resource);
        Url url = sitemap.addUrl(location + ".html");
        // add any additional content to the Url like lastmod, change frequency, and so on
    }

    @Override
    protected final boolean shouldFollow(@NotNull Resource resource) {
        return super.shouldFollow(resource)
            && Optional.ofNullable(resource.adaptTo(Page.class)).map(this::shouldFollow).orElse(Boolean.TRUE);
    }

    private boolean shouldFollow(Page page) {
        // add additional conditions to stop traversing some pages
        return !defaultGenerator.isProtected(page);
    }

    @Override
    protected final boolean shouldInclude(@NotNull Resource resource) {
        return super.shouldInclude(resource)
            && Optional.ofNullable(resource.adaptTo(Page.class)).map(this::shouldInclude).orElse(Boolean.FALSE);
    }

    private boolean shouldInclude(Page page) {
        // add additional conditions to stop including some pages
        return defaultGenerator.isPublished(page)
            && !defaultGenerator.isNoIndex(page)
            && !defaultGenerator.isRedirect(page)
            && !defaultGenerator.isProtected(page);
    }
}

さらに、XML サイトマップ用に実装された機能は、例えば、正規リンクや代替言語をページの先頭に追加する場合など、様々なユースケースでも使用できます。詳しくは、SEO タグのインターフェイスを参照してください。

レガシー URL の 301 リダイレクトの作成 creating-redirects-for-legacy-urls

新しい構造でサイトの運用を開始するときには、次の 2 つの理由から、Apache HTTP Server で 301 リダイレクトを実装し、テストすることが重要です。

  • レガシー URL は、時間をかけて SEO の価値を積み上げてきました。リダイレクトを実装すれば、検索エンジンはこの価値を新しい URL に適用できます。
  • サイトのユーザーが、これらのページへのブックマークを作成している場合があります。リダイレクトを実装すると、古いサイトでアクセスしようとしていたページに最も近い、新しいサイトのページにユーザーをリダイレクトできます。

301 リダイレクトの実装に関する説明や、リダイレクトが正しく機能していることをテストするためのツールについては、その他のリソースの節を参照してください。

その他のリソース additional-resources

詳しくは、次のその他のリソースを参照してください。

recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab