Show Menu
トピック×

Analytics 用のサーバー側ページネーミングの実装

Adobe Analytics は、 s.pageName プロパティを使用してページを一意に識別し、そのページのために収集されたデータを関連付けます。AEM から Analytics に送信されるこのプロパティに値を割り当てるには、通常は AEM 内で次のタスクを実行します。
Analytics レポートデータをサイトコンソールとコンテンツインサイトに公開するには、各ページの s.pageName プロパティの値が必要です。The AEM Analytics Java API defines the AnalyticsPageNameProvider interface that you implement to provide the Sites console and Content Insights with the value of the s.pageName property. AnaltyicsPageNameProvider サービスは、レポート生成のためにサーバー上の pageName プロパティを解決します。このプロパティは、追跡のためにクライアント上で Javascript を使用して動的に設定できるからです。

デフォルトの Analytics ページ名プロバイダーサービス

The DefaultPageNameProvider service is the default service that determines the value of the s.pageName property to use for retrieving Analytics data for a page. The service works in conjunction with the AEM foundation page component ( /libs/foundation/components/page ). このページコンポーネントは、 s.pageName プロパティにマップされる次の CQ 変数を定義します。
  • pagedata.path :ページのパスに設定されます。
  • pagedata.title :ページのタイトルに設定されます。
  • pagedata.navTitle :ページのナビゲーションのタイトルに設定されます。
The DefaultPageNameProvider service determines which of these CQ variables is mapped to the s.pageName property in the Analytics cloud service framework. その後、Analytics レポートデータの取得に使用する適切なページプロパティを決定します。
  • pagedata.path :サービスでは、 page.getPath()
  • pagedata.title :サービスでは、 page.getTitle()
  • pagedata.navTitle :サービスでは、 page.getNavigationTitle()
The page object is the is the com.day.cq.wcm.api.Page Java object for the page.
If you do not map a CQ variable to the s.pageName property in the framework, the value for s.pageName is generated from the page path. For example, the page with the path /content/geometrixx/en uses the value content:geometrixx:en for s.pageName .
DefaultPageNameProviderサービスは、100のサービスランクを使用します。

Analytics レポートにおける連続性の維持

ページの分析データに関するすべての履歴を維持するには、一度も変更されたことがないページに使用される s.pageName プロパティの値が必要です。ただし、基盤ページコンポーネントが定義する分析プロパティは簡単に変更できます。例えば、ページを移動すると pagedata.path の値が変更され、レポート履歴の連続性が途切れて、次のようなことが起こります。
  • 前のパスで収集されたデータは、このページと関連付けられなくなります。
  • 以前に他のページが使用していたパスを別のページが使用する場合は、後から使用するほうのページがそのパスのデータを継承します。
レポートの連続性を保証するには、 s.pageName の値に以下の性質を持たせる必要があります。
  • 一意性。
  • 安定性。
  • 人間にとっての可読性。
例えば、カスタムページコンポーネントに、作成者がページの一意の ID を指定するために使用するページプロパティ( s.pageProperties プロパティの値として使用されるもの)を含めることができます。
  • ページに含まれる Analytics 変数は、ページプロパティに保存されている一意の ID の値に設定されます。
  • The analytics variable is mapped to the s.pageProperties property in the Analytics framework.
  • AnalytcsPageNameProvider インターフェイスの実装は、このページプロパティの値を取得して、ページの Analytics データのクエリに使用します。
s.pageName の値について効果的な戦略を策定できるよう、Analytics のコンサルタントに相談してください。

Analytics ページ名プロバイダーサービスの実装

com.day.cq.analytics.sitecatalyst.AnalyticsPageNameProvider s.pageName インターフェイスを OSGi サービスとして実装し、 プロパティの値を取得するロジックをカスタマイズします。サイトページ分析およびコンテンツインサイトでこのサービスを使用して、Analytics からレポートデータを取得します。
AnalyticsPageNameProvider インターフェイスで定義されている次の 2 つのメソッドを実装する必要があります。
  • getPageName :プロパティ String として使用する値を表す値を返し s.pageName ます。
  • getResource :プロパティ org.apache.sling.api.resource.Resource に関連付けられているページを表すオブジェクトを返 s.pageName します。
Both methods take a com.day.cq.analytics.sitecatalyst.AnalyticsPageNameContext object as a parameter. AnalyticsPageNameContext クラスは、Analytics 呼び出しのコンテキストに関する以下の情報を提供します。
  • ページリソースのベースパス。
  • Analytics クラウドサービス設定の Framework オブジェクト。
  • ページの Resource オブジェクト。
  • ページの ResourceResolver オブジェクト。
このクラスは、ページ名の setter も提供します。

サンプル AnalyticsPageNameProvider 実装

以下に示すサンプル AnalyticsPageNameProvider 実装は、以下のようなカスタムページコンポーネントをサポートしています。
  • 基盤ページコンポーネントを拡張したコンポーネントです。
  • The dialog box includes a field that authors use to specify the value of the s.pageName property.
  • プロパティの値は、ページインスタンスの jcr:content ノードの pageName プロパティに保存されます。
  • s.pageName プロパティを保存する Analytics プロパティは、 pagedata.pagename です。This property is mapped to the s.pageName property in the Analytics framework.
以下に示す getPageName メソッドの実装は、フレームワークのマッピングが正しく設定されていれば、pageName ノードのプロパティの値を返します。
public String getPageName(AnalyticsPageNameContext context) {
        String pageName = null;

        Framework framework = context.getFramework();
        Resource resource = context.getResource();

        if (resource != null && framework != null && framework.mapsSCVariable(S_PAGE_NAME)) {
            String cqVar = framework.getMapping(S_PAGE_NAME);
            Page page = resource.adaptTo(Page.class);
            if (cqVar.equals("pagedata.pagename")) {
                pageName = page.getProperties().get("pageName",null);
            }
        }
        return pageName;
    }

以下に示す getResource メソッドの実装は、ページの Resource オブジェクトを返します。
     public Resource getResource(AnalyticsPageNameContext context) {
        Resource res = null;

        Framework framework = context.getFramework();
        ResourceResolver resolver = context.getResourceResolver();
        String pageName = context.getPageName();
        String basePath = context.getBasePath();

        if (pageName != null && basePath != null && resolver != null
                && framework != null && framework.mapsSCVariable(S_PAGE_NAME)) {
            String cqVar = framework.getMapping(S_PAGE_NAME);
            if (cqVar.equals("pagedata.pagename")) {
             Iterator<Resource>
             hits = resolver.findResources(createQuery(pageName, basePath, "pagename"), Query.JCR_SQL2);
             if (hits.hasNext()) {
              res = hits.next();
              res = res.getParent();
             }
            }
        }
        return res;
    }

    private String createQuery(String pageName, String basePath, String propName) {
        return "SELECT * FROM [cq:PageContent] WHERE ISDESCENDANTNODE(["
                + basePath + "]) and [" + propName + "] = \"" + pageName + "\"";
    }

以下のコードは、サービスを設定する SCR アノテーションを含む、クラス全体を表します。デフォルトのサービスをオーバーライドするサービスランキングが 200 であることに注意してください。
/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 * Copyright 2019 Adobe Systems Incorporated
 * All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.day.cq.analytics.sitecatalyst;

import java.util.Iterator;

import javax.jcr.query.Query;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;

import com.day.cq.analytics.sitecatalyst.AnalyticsPageNameContext;
import com.day.cq.analytics.sitecatalyst.AnalyticsPageNameProvider;
import com.day.cq.analytics.sitecatalyst.Framework;
import com.day.cq.wcm.api.Page;

import static com.day.cq.analytics.sitecatalyst.AnalyticsPageNameContext.S_PAGE_NAME;

/**
 * Default implementation of {@link AnalyticsPageNameProvider} that resolves
 * page title, path or navTitle if mapped in {@link Framework}.
 */
@Component(
    service = { AnalyticsPageNameProvider.class },
    property = {
        Constants.SERVICE_DESCRIPTION + "=Example Page Name Resolver implementation",
        Constants.SERVICE_RANKING + ":Integer=200"
    }
)
public class ExamplePageNameProvider implements AnalyticsPageNameProvider {
    public String getPageName(AnalyticsPageNameContext context) {
        String pageName = null;

        Framework framework = context.getFramework();
        Resource resource = context.getResource();

        if (resource != null && framework != null && framework.mapsSCVariable(S_PAGE_NAME)) {
            String cqVar = framework.getMapping(S_PAGE_NAME);
            Page page = resource.adaptTo(Page.class);
            if (cqVar.equals("pagedata.path")) {
                pageName = page.getProperties().get("pageName",null);
            }
        }
        return pageName;
    }

    public Resource getResource(AnalyticsPageNameContext context) {
        Resource res = null;

        Framework framework = context.getFramework();
        ResourceResolver resolver = context.getResourceResolver();
        String pageName = context.getPageName();
        String basePath = context.getBasePath();

        if (pageName != null && basePath != null && resolver != null
                && framework != null && framework.mapsSCVariable(S_PAGE_NAME)) {
            String cqVar = framework.getMapping(S_PAGE_NAME);
            if (cqVar.equals("pagedata.pagename")) {
                Iterator<Resource>
                hits = resolver.findResources(createQuery(pageName, basePath, "pagename"), Query.JCR_SQL2);
                if (hits.hasNext()) {
                    res = hits.next();
                    res = res.getParent();
                }
            }
        }
        return res;
    }

    private String createQuery(String pageName, String basePath, String propName) {
        return "SELECT * FROM [cq:PageContent] WHERE ISDESCENDANTNODE(["
                + basePath + "]) and [" + propName + "] = \"" + pageName + "\"";
    }
}