Adobe Experience Manager
Adobe製エンタープライズCMS。デジタルエクスペリエンス管理とマーケティング統合機能を提供。
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製品への依存が強い
- リソース要求: 高いサーバースペックとインフラが必要
- カスタマイズの複雑さ: 高度なカスタマイズには専門家が必須
主要リンク
- Adobe Experience Manager公式サイト
- AEM Documentation
- Adobe Experience League
- AEM Developer Portal
- AEM Community
- AEM Assets
使い方の例
プロジェクトの初期設定
# 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);
}
}