検索エンジン最適化(SEO)は、多くのマーケターにとって重要な課題となっています。その結果、多くの Adobe Experience Manager(AEM)as a Cloud Service プロジェクトで SEO の懸念に対処する必要があります。
このドキュメントでは、まず、AEM as a Cloud Service の実装でこうした目的を達成するための SEO のベストプラクティスおよびレコメンデーションを説明します。その次に、最初の節で提示するより複雑な実装手順のいくつかについて詳しく説明していきます。
このセクションでは、SEO の一般的なベストプラクティスを説明します。
URL には、認められているベストプラクティスがいくつかあります。
AEM プロジェクトで URL を評価するときには、次のことを確認してください。
「ユーザーがこの URL を閲覧する際にページ上にコンテンツが何もない場合、このページの内容を説明できますか?」
答えが「はい」であれば、その URL は検索エンジンに効果があります。
SEO に対応した URL を作成する方法について、一般的なヒントを紹介します。
ハイフンを使用して単語を区切ります。
可能な場合、クエリパラメーターの使用は避けます。必要な場合は、パラメーターを 2 つ以下に制限します。
ユーザーにとって 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 におけるキーワードの効果は低下します。つまり、短い方が良いのです。
mybrand.com/content/my-brand/en/myPage.html
より mybrand.com/en/myPage.html
を選択します。正規 URL を使用します。
複数のパスから、または複数のパラメーターやセレクターで 1 つの URL を提供できない場合は必ず、ページで rel=canonical
タグを使用します。
これは、AEM テンプレートのコードに含めることができます。
可能な限り、URL をページタイトルに一致させます。
URL リクエストで大文字と小文字を区別しないことをサポートします。
各ページを 1 つのプロトコルで提供するようにします。
ユーザーがチェックアウトやログインフォームなどを使用してページに到達するまでは、サイトが http
経由で提供されることがありますが、到達した時点で https
に切り替わります。このページからリンクするときに、ユーザーが http
ページに戻り、https
経由でそれらのページにアクセスできる場合、検索エンジンは、2 つの異なるページとして追跡します。
Google では現在、https
ページの方が http
ページよりも推奨されています。そのため、多くの場合、サイト全体を https
で配信する方が問題が少なくなります。
サーバーの設定に関しては、次の手段を講じることで、適切なコンテンツのみがクロールされるようにすることができます。
robots.txt
ファイルを使用して、インデックスを作成する必要がないコンテンツのクローリングをブロックします。
更新した URL を使用して新しいサイトの運用を開始する場合は、既存の SEO ランキングが失われないように 301 リダイレクトを実装します。
サイトの favicon を含めます。
XML サイトマップを実装して、検索エンジンがコンテンツをより簡単にクロールできるようにします。モバイルサイトやレスポンシブサイトの場合は、必ずモバイルサイトマップを組み込みます。
ここでは、SEO に関する前述のレコメンデーションに従って AEM を設定するために必要な実装手順を説明します。
これまで、エンタープライズ web アプリケーションを構築する場合、クエリパラメーターを使用するのが認められた手法でした。
最近の傾向では、URL をより読みやすくするために、これらを削除するようになっています。 多くのプラットフォームでは、Web サーバーやコンテンツ配信ネットワーク(CDN)へのリダイレクトの実装などが行われますが、Sling を使用すると簡単です。Sling セレクター:
AEM では、サーブレットを作成するときに次の 2 つのオプションが用意されています。
次に示す各例では、この両方のパターンに準拠したサーブレットを登録する方法とともに、Sling サーブレットを使用することによって得られる利点を説明します。
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
このアプローチで考慮すべき点は次のとおりです。
/bin/myApp/myServlet
を公開するように Dispatcher を(慎重に)設定する必要があります。単に /bin
を公開すると、サイト訪問者に公開してはいけない特定のサーブレットへのアクセスが許可されます。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
このアプローチの利点は次のとおりです。
/content/my-brand/my-page
に適用されているすべての ACL が有効になります。AEM では、すべての Web ページが /content/my-brand/my-content
に保存されます。これは、リポジトリーデータ管理の観点では便利な場合がありますが、必ずしもこの方法で顧客にサイトを表示するわけではなく、URL をできるだけ短くするという SEO のガイダンスと矛盾する可能性があります。また、同じ AEM インスタンスや異なるドメイン名から複数の web サイトを提供している場合もあります。
この節では、これらの URL を管理し、よりわかりやすく、SEO に適した方法で URL をユーザーに表示するために AEM で使用可能なオプションを説明します。
作成者が、プロモーション目的で別の場所からアクセス可能なページを作成する場合、ページごとに定義される AEM のバニティー URL が役立つことがあります。ページのバニティー URL を追加するには、 Sites コンソールで該当するページに移動し、ページのプロパティを編集します。「基本」タブの下部に、バニティー URL を追加できるセクションが表示されます。複数の URL を使用してページにアクセスできるようにすると、ページの SEO 値が分断されるので、正規 URL タグをページに追加して、この問題を回避する必要があることに留意してください。
翻訳されたコンテンツのユーザーには、ローカライズされたページ名を表示した方がよい場合があります。次に例を示します。
スペイン語を話すユーザーが次のページにアクセスするとします。
www.mydomain.com/es/home.html
この場合、URL を次のように表示した方が効果的です。
www.mydomain.com/es/casa.html
。
ページ名をローカライズする際の課題は、AEM プラットフォームで利用できるローカライズツールの多くが、コンテンツの同期を保つためにロケール間でページ名を一致させる必要があることです。
The sling:alias
プロパティを使用すると、両方を同時に実行できます。 sling:alias
を任意のリソースにプロパティとして追加すると、リソースのエイリアス名を使用することができます。前述の例では、次のようになります。
JCR の次の場所にページがあるとします。
…/es/home
プロパティを追加します。
sling:alias
= casa
これにより、マルチサイトマネージャーなどの AEM 翻訳ツールでは、次のページ間の関係を引き続き維持できます。
/en/home
/es/home
また、エンドユーザーもページ名を母国語で操作できます。
sling:alias
プロパティは、ページプロパティ編集時のエイリアスプロパティを使用して設定できます。
標準 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 のキャッシュの無効化に関する問題が生じることがあります。
次に、この問題がどのように生じるかについて例を示します。
ユーザーが Web サイトを訪問し、https://www.mydomain.com/my-page.html
を要求します。
Dispatcher が、このリクエストを公開サーバーに転送します。
公開サーバーが /etc/map
を使用して、このリクエストを /content/my-brand/my-page
に解決し、ページをレンダリングします。
Dispatcher が /my-page.html
に応答をキャッシュし、応答をユーザーに返します。
コンテンツ作成者がこのページを変更し、アクティブ化します。
Dispatcher フラッシュエージェントが /content/my-brand/my-page
の無効化リクエストを送信します。 Dispatcher はこのパスにページをキャッシュしていないので、古いコンテンツがキャッシュされたままになり、更新されません。
キャッシュの無効化のために、短い URL を長い URL にマッピングするカスタムのディスパッチフラッシュルールを設定する方法があります。
ただし、これをより簡単に管理する次のような方法もあります。
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 Mappings(resource.resolver.mapping
)に直接割り当てることができます。
resource.resolver.mapping="[/content/my-brand/(.*)</$1]"
この簡単な例では、URL に /content/my-brand/
が存在する場合、URL の先頭から削除されます。
これにより、URL は次のように変換されます。
/content/my-brand/my-page.html
から/my-page.html
これは、URL をできるだけ短く維持するという推奨事項に準拠しています。
ページに出力される URL のマッピング
Apache Sling Resource Resolver でマッピングを定義したら、ページに出力する URL が短く、適切になるように、それらのマッピングをコンポーネントで使用する必要があります。そのためには、ResourceResolver
のマッピング関数を使用します。
例えば、現在のページの子をリストアウトするカスタムナビゲーションコンポーネントを実装している場合、次のようなマッピングメソッドを使用できます。
for (Page child : children) {
String childUrl = resourceResolver.map(request, child.getPath());
//Output the childUrl on the page here
}
これまでに、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 タグは、コンテンツのインデックス作成時に検索エンジンでページがどのように処理されるかを明確にするために、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 を確認し、このタグを出力するには、このコードをページマークアップに挿入する必要があります。
すべてのページを小文字で提供することがベストプラクティスです。ただし、ユーザーが 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
。ただし、Google、Yahoo、Bing などの主要な検索エンジンではすべてこの点が考慮されるのに対し、なじみのない検索エンジンの中には、この点が考慮されないものもあります。
サイト全体へのアクセスをブロックするための最も簡単な方法は、robots.txt
というファイルに次の内容を指定して、サイトのルートに配置することです。
User-agent: *
Disallow: /
また、実稼働環境では、インデックスが作成されないように特定のパスを禁止することもできます。
ただし、robots.txt
ファイルをサイトルートに配置すると、Dispatcher フラッシュリクエストによって、このファイルが除去されることがあり、URL マッピングによって、サイトルートが Apache HTTP Server 設定で定義された DOCROOT
とは異なる場所に配置される可能性があります。こうした理由から、このファイルをオーサーインスタンスのサイトのルートに配置し、パブリッシュインスタンスにレプリケートするのが一般的です。
クローラーでは、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>
セレクター 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 サイトマップを再生成するための開始点として使用できます。
サイトマップ生成ジョブは、オーサー層のインスタンスとパブリッシュ層のインスタンスの両方で実行できます。ほとんどの場合、適切な正規 URL を生成できるのはパブリッシュ層インスタンスだけなので、パブリッシュ層インスタンスで生成を実行することをお勧めします(Sling リソースマッピングルールは一般にパブリッシュ層インスタンスにのみ存在するため)。ただし、SitemapLinkExternalizer インターフェイスを実装することにより、正規 URL の生成に使用される外部化メカニズムのカスタム実装をプラグインすることは可能です。カスタム実装により、オーサー層インスタンスでサイトマップの正規 URL を生成できる場合は、SitemapScheduler
をオーサー実行モードに設定して、XML サイトマップ生成ワークロードをオーサーサービスクラスターのインスタンス全体に分散させることができます。このシナリオでは、未公開のコンテンツ、変更済みのコンテンツ、限られたユーザーグループにのみ表示されるコンテンツの取り扱いには、特に注意が必要です。
AEM Sites には、ページのツリーをトラバースしてサイトマップを生成する SitemapGenerator
のデフォルトの実装が含まれています。サイトの正規 URL と(使用可能な場合は)代替言語のみを出力するように事前設定されています。また、必要に応じて、ページの最終変更日を含めるように設定することもできます。その場合は、Adobe AEM SEO - Page Tree Sitemap Generator 設定の「最終変更日を追加」オプションを有効にし、「最終変更ソース」を選択します。サイトマップがパブリッシュ層で生成される場合は、cq:lastModified
の日付を使用することをお勧めします。
サイトマップのコンテンツを制限するには、必要に応じて次のサービスインターフェイスを実装します。
デフォルトの実装が特定のユースケースで機能しない場合、または拡張ポイントが十分に柔軟性を持たない場合、カスタム 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 タグのインターフェイスを参照してください。
新しい構造でサイトの運用を開始するときには、次の 2 つの理由から、Apache HTTP Server で 301 リダイレクトを実装し、テストすることが重要です。
301 リダイレクトの実装に関する説明や、リダイレクトが正しく機能していることをテストするためのツールについては、その他のリソースの節を参照してください。
詳しくは、次のその他のリソースを参照してください。