Adobe Experience Manager

Adobe製エンタープライズCMS。デジタルエクスペリエンス管理とマーケティング統合機能を提供。

CMSエンタープライズJavaデジタルエクスペリエンスパーソナライゼーションマーケティング統合Adobe
ライセンス
Commercial
言語
Java
料金
有料のみ

CMS

Adobe Experience Manager

概要

Adobe Experience Manager(AEM)は、デジタルエクスペリエンス管理とマーケティング統合機能を提供する、Adobe製の包括的なエンタープライズCMSプラットフォームです。

詳細

Adobe Experience Manager(AEM)は、大企業向けに設計された統合型デジタルエクスペリエンスプラットフォームです。コンテンツ管理、デジタルアセット管理(DAM)、パーソナライゼーション、マルチチャンネル配信を一つのプラットフォームで実現します。Javaベースで構築され、OSGiフレームワークとApache Slingを活用した堅牢なアーキテクチャを採用しています。AEM Sitesではコンテンツ管理、AEM Assetsではデジタルアセット管理、AEM Formsではフォーム管理を統合的に提供します。Adobe Senseiによる AIパワード機能により、コンテンツの自動生成、最適化、パーソナライゼーションを大規模に実現できます。Fortune 500企業の70%以上が採用し、クラウドネイティブアーキテクチャにより無限のスケーラビリティと低いTCOを実現しています。

メリット・デメリット

メリット

  • 包括的な機能セット: コンテンツ管理、DAM、フォーム管理を統合
  • AI駆動のパーソナライゼーション: Adobe Senseiによる高度な自動化
  • Adobe製品エコシステム: Creative Cloud、Analytics、Targetとの深い統合
  • エンタープライズグレード: Fortune 500企業の実績とサポート
  • マルチチャンネル配信: ヘッドレスCMS機能でオムニチャンネル対応
  • 高速な市場投入: テンプレートとコンポーネントで73%の時間短縮
  • グローバル対応: 多言語・多地域サイト管理機能

デメリット

  • 非常に高額なコスト: 年間数百万円から数千万円の投資が必要
  • 複雑な実装: 専門知識と長期の導入期間が必要
  • 高い学習曲線: 開発者とコンテンツ編集者の両方に習熟が必要
  • ベンダーロックイン: Adobe製品への依存が強い
  • リソース要求: 高いサーバースペックとインフラが必要
  • カスタマイズの複雑さ: 高度なカスタマイズには専門家が必須

主要リンク

使い方の例

プロジェクトの初期設定

# AEM プロジェクトアーキタイプでプロジェクト作成
mvn archetype:generate \
  -DarchetypeGroupId=com.adobe.aem \
  -DarchetypeArtifactId=aem-project-archetype \
  -DarchetypeVersion=41 \
  -DgroupId=com.mycompany \
  -DartifactId=myproject \
  -Dversion=1.0.0-SNAPSHOT \
  -Dpackage=com.mycompany.myproject \
  -DappTitle="My Company Site" \
  -DappId="mycompany" \
  -DincludeDispatcherConfig=y

# ローカル開発環境の起動
cd myproject
mvn clean install -PautoInstallPackage

コンポーネント開発

// HTL (HTML Template Language) コンポーネント
// /apps/myproject/components/content/hero/hero.html
<div class="hero-component" data-sly-use.hero="com.mycompany.myproject.models.Hero">
    <div class="hero-background" style="background-image: url('${hero.backgroundImage @ context='uri'}')">
        <div class="hero-content">
            <h1>${hero.title}</h1>
            <p>${hero.description}</p>
            <a href="${hero.ctaLink @ context='uri'}" class="cta-button">
                ${hero.ctaText}
            </a>
        </div>
    </div>
</div>

// Sling Model
package com.mycompany.myproject.models;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import javax.annotation.PostConstruct;

@Model(adaptables = Resource.class)
public class Hero {
    @ValueMapValue
    private String title;
    
    @ValueMapValue
    private String description;
    
    @ValueMapValue
    private String backgroundImage;
    
    @ValueMapValue
    private String ctaLink;
    
    @ValueMapValue
    private String ctaText;
    
    @PostConstruct
    protected void init() {
        // 初期化ロジック
    }
    
    // Getters
    public String getTitle() { return title; }
    public String getDescription() { return description; }
    public String getBackgroundImage() { return backgroundImage; }
    public String getCtaLink() { return ctaLink; }
    public String getCtaText() { return ctaText; }
}

コンテンツフラグメントとGraphQL

# GraphQL スキーマ定義
type Article {
  _path: ID
  title: String
  author: String
  publishDate: Calendar
  content: String
  tags: [String]
  featuredImage: String
}

type Query {
  articleList(
    filter: ArticleFilter
    sort: ArticleSort
    limit: Int
    offset: Int
  ): [Article]
  
  articleByPath(_path: ID!): Article
}
// GraphQL クエリの実行
const ARTICLE_QUERY = `
  query GetArticles($limit: Int, $offset: Int) {
    articleList(limit: $limit, offset: $offset) {
      _path
      title
      author
      publishDate
      content
      tags
      featuredImage
    }
  }
`;

async function fetchArticles() {
  const response = await fetch('/content/cq:graphql/myproject/endpoint.json', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: ARTICLE_QUERY,
      variables: { limit: 10, offset: 0 }
    })
  });
  
  const data = await response.json();
  return data.data.articleList;
}

パーソナライゼーション設定

// ContextHub セグメント定義
{
  "name": "premium-customers",
  "title": "Premium Customers",
  "description": "Visitors who are premium customers",
  "condition": {
    "and": [{
      "or": [{
        "equals": {
          "left": "${profile.membership}",
          "right": "premium"
        }
      }]
    }, {
      "greater": {
        "left": "${profile.purchaseHistory.totalAmount}",
        "right": 10000
      }
    }]
  }
}

// ターゲティングコンポーネント
<div data-sly-use.targeting="com.adobe.cq.wcm.core.components.models.Teaser"
     data-sly-test="${targeting.configured}">
    <sly data-sly-test="${targeting.actions}"
         data-sly-list.action="${targeting.actions}">
        <div class="teaser ${action.cssClass}"
             data-cmp-clickable="${action.link ? true : false}">
            <h2>${action.title}</h2>
            <p>${action.description}</p>
            <a href="${action.link}" class="cta">${action.ctaText}</a>
        </div>
    </sly>
</div>

ワークフロー自動化

// カスタムワークフロープロセス
package com.mycompany.myproject.workflow;

import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import org.osgi.service.component.annotations.Component;

@Component(
    service = WorkflowProcess.class,
    property = {"process.label=Auto Publish Process"}
)
public class AutoPublishProcess implements WorkflowProcess {
    
    @Override
    public void execute(WorkItem workItem, WorkflowSession workflowSession, 
                       MetaDataMap metaDataMap) throws WorkflowException {
        
        String payload = workItem.getWorkflowData().getPayload().toString();
        
        try {
            // レプリケーション API を使用してページを公開
            Replicator replicator = workflowSession.adaptTo(Replicator.class);
            Session session = workflowSession.adaptTo(Session.class);
            
            replicator.replicate(
                session,
                ReplicationActionType.ACTIVATE,
                payload
            );
            
        } catch (Exception e) {
            throw new WorkflowException("Failed to publish page", e);
        }
    }
}

Adobe Analytics統合

// Analytics データレイヤー実装
window.digitalData = {
  page: {
    pageInfo: {
      pageName: "${currentPage.title}",
      siteSection: "${currentPage.parent.name}",
      server: "${request.serverName}",
      language: "${currentPage.language}"
    },
    category: {
      primaryCategory: "${pageProperties.category}",
      subCategory1: "${pageProperties.subcategory}"
    }
  },
  user: {
    profile: {
      profileID: "${profile.authorizableId}",
      membershipLevel: "${profile.membershipLevel}"
    }
  },
  event: []
};

// カスタムイベントトラッキング
function trackCustomEvent(eventName, eventData) {
  window.digitalData.event.push({
    eventInfo: {
      eventName: eventName,
      eventAction: eventData.action,
      eventCategory: eventData.category
    }
  });
  
  // Adobe Analytics に送信
  if (window._satellite) {
    _satellite.track(eventName, eventData);
  }
}