瞭解如何將AEM內容片段匯出至Adobe Target,將AEM Headless與Adobe Target整合,並使用Adobe Experience Platform Web SDK的alloy.js來個人化Headless體驗。 此 React WKND應用程式 用於探索如何使用內容片段選件將個人化Target活動新增到體驗,以促進WKND冒險。
本教學課程涵蓋設定AEM和Adobe Target的相關步驟:
有助於在AEM和Adobe Target之間進行驗證的Adobe IMS設定。
檢閱 說明檔案 以取得如何建立Adobe IMS設定的逐步指示。
在AEM中建立Adobe TargetCloud Service,以促進將內容片段匯出至Adobe Target。
檢閱 說明檔案 以取得如何建立Adobe TargetCloud Service的逐步指示。
在內容感知設定中設定的Adobe TargetCloud Service,必須套用至包含要匯出至Adobe Target之內容片段的AEM Assets資料夾階層。
/conf
套用至/conf
)包含Adobe Target Cloud Services設定。Adobe Target整合(顯示為developer.adobe.com專案)必須授予 編輯者 Adobe Admin Console產品角色,用於將內容片段匯出至Adobe Target。
存在於下的內容片段 已設定的AEM Assets資料夾階層 可作為內容片段選件匯出至Adobe Target。 這些內容片段選件(Target中特殊形式的JSON選件)可用於Target活動,在Headless應用程式中提供個人化體驗。
在Adobe Target中,可建立使用內容片段選件JSON作為內容的活動,允許在Headless應用程式中使用在AEM中建立和管理內容的個人化體驗。
在此範例中,我們使用簡單的A/B活動,但可使用任何Target活動。
wknd-adventure-promo
鎖定目標的Adobe Target活動 wknd-adventure-promo
位置現在可以在AEM Headless應用程式中整合和公開。
一個 Adobe Experience Platform資料串流 AEM Adobe Target Headless應用程式需要ID才能使用 AdobeWeb SDK.
AEM Target integration
Datastream used by the Adobe Web SDK to serve personalized Content Fragments Offers.
Leave blank
本教學課程透過以下方式,探索使用Adobe Target中的內容片段選件來個人化簡單的React應用程式 Adobe Experience Platform Web SDK. 此方法可用於個人化任何以JavaScript為基礎的網頁體驗。
Android™和iOS行動體驗可透過以下類似模式進行個人化: Adobe的行動SDK.
從下載範例React應用程式的原始碼 Github.com
$ mkdir -p ~/Code
$ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
開啟程式碼基底於 ~/Code/aem-guides-wknd-graphql/personalization-tutorial
在您最愛的IDE中
更新您要應用程式連線的AEM服務主機 ~/Code/aem-guides-wknd-graphql/personalization-tutorial/src/.env.development
...
REACT_APP_HOST_URI=https://publish-p1234-e5678.adobeaemcloud.com/
...
執行應用程式,並確保其連線至設定的AEM服務。 從命令列,執行:
$ cd ~/Code/aem-guides-wknd-graphql/personalization-tutorial
$ npm install
$ npm run start
安裝 AdobeWeb SDK 作為NPM套件。
$ cd ~/Code/aem-guides-wknd-graphql/personalization-tutorial
$ npm install @adobe/alloy
Web SDK可用於程式碼中,以依活動位置擷取內容片段選件JSON。
設定Web SDK時,需要兩個ID:
edgeConfigId
這就是 資料串流IDorgId
AEMas a Cloud Service/TargetAdobe組織ID可在以下網址找到: Experience Cloud>設定檔>帳戶資訊>目前組織ID叫用Web SDK時,Adobe Target活動位置(在我們的範例中, wknd-adventure-promo
)必須設定為 decisionScopes
陣列。
import { createInstance } from "@adobe/alloy";
const alloy = createInstance({ name: "alloy" });
...
alloy("config", { ... });
alloy("sendEvent", { ... });
建立React元件 AdobeTargetActivity.js
以顯示Adobe Target活動。
src/components/AdobeTargetActivity.js
import React, { useEffect } from 'react';
import { createInstance } from '@adobe/alloy';
const alloy = createInstance({ name: 'alloy' });
alloy('configure', {
'edgeConfigId': 'e3db252d-44d0-4a0b-8901-aac22dbc88dc', // AEP Datastream ID
'orgId':'7ABB3E6A5A7491460A495D61@AdobeOrg',
'debugEnabled': true,
});
export default function AdobeTargetActivity({ activityLocation, OfferComponent }) {
const [offer, setOffer] = React.useState();
useEffect(() => {
async function sendAlloyEvent() {
// Get the activity offer from Adobe Target
const result = await alloy('sendEvent', {
// decisionScopes is set to an array containing the Adobe Target activity location
'decisionScopes': [activityLocation],
});
if (result.propositions?.length > 0) {
// Find the first proposition for the active activity location
var proposition = result.propositions?.filter((proposition) => { return proposition.scope === activityLocation; })[0];
// Get the Content Fragment Offer JSON from the Adobe Target response
const contentFragmentOffer = proposition?.items[0]?.data?.content || { status: 'error', message: 'Personalized content unavailable'};
if (contentFragmentOffer?.data) {
// Content Fragment Offers represent a single Content Fragment, hydrated by
// the byPath GraphQL query, we must traverse the JSON object to retrieve the
// Content Fragment JSON representation
const byPath = Object.keys(contentFragmentOffer.data)[0];
const item = contentFragmentOffer.data[byPath]?.item;
if (item) {
// Set the offer to the React state so it can be rendered
setOffer(item);
// Record the Content Fragment Offer as displayed for Adobe Target Activity reporting
// If this request is omitted, the Target Activity's Reports will be blank
alloy("sendEvent", {
xdm: {
eventType: "decisioning.propositionDisplay",
_experience: {
decisioning: {
propositions: [proposition]
}
}
}
});
}
}
}
};
sendAlloyEvent();
}, [activityLocation, OfferComponent]);
if (!offer) {
// Adobe Target offer initializing; we render a blank component (which has a fixed height) to prevent a layout shift
return (<OfferComponent></OfferComponent>);
} else if (offer.status === 'error') {
// If Personalized content could not be retrieved either show nothing, or optionally default content.
console.error(offer.message);
return (<></>);
}
console.log('Activity Location', activityLocation);
console.log('Content Fragment Offer', offer);
// Render the React component with the offer's JSON
return (<OfferComponent content={offer} />);
};
使用叫用AdobeTargetActivity React元件,如下所示:
<AdobeTargetActivity activityLocation={"wknd-adventure-promo"} OfferComponent={AdventurePromo}/>
建立React元件 AdventurePromo.js
以呈現JSON Adobe Target提供的冒險活動。
此React元件採用完全水合的JSON來表示冒險內容片段,並以促銷方式顯示。 根據匯出至Adobe Target的內容片段,顯示從Adobe Target內容片段選件提供JSON服務的React元件可能視需要而多樣且複雜。
src/components/AdventurePromo.js
import React from 'react';
import './AdventurePromo.scss';
/**
* @param {*} content is the fully hydrated JSON data for a WKND Adventure Content Fragment
* @returns the Adventure Promo component
*/
export default function AdventurePromo({ content }) {
if (!content) {
// If content is still loading, then display an empty promote to prevent layout shift when Target loads the data
return (<div className="adventure-promo"></div>)
}
const title = content.title;
const description = content?.description?.plaintext;
const image = content.primaryImage?._publishUrl;
return (
<div className="adventure-promo">
<div className="adventure-promo-text-wrapper">
<h3 className="adventure-promo-eyebrow">Promoted adventure</h3>
<h2 className="adventure-promo-title">{title}</h2>
<p className="adventure-promo-description">{description}</p>
</div>
<div className="adventure-promo-image-wrapper">
<img className="adventure-promo-image" src={image} alt={title} />
</div>
</div>
)
}
src/components/AdventurePromo.scss
.adventure-promo {
display: flex;
margin: 3rem 0;
height: 400px;
}
.adventure-promo-text-wrapper {
background-color: #ffea00;
color: black;
flex-grow: 1;
padding: 3rem 2rem;
width: 55%;
}
.adventure-promo-eyebrow {
font-family: Source Sans Pro,Helvetica Neue,Helvetica,Arial,sans-serif;
font-weight: 700;
font-size: 1rem;
margin: 0;
text-transform: uppercase;
}
.adventure-promo-description {
line-height: 1.75rem;
}
.adventure-promo-image-wrapper {
height: 400px;
width: 45%;
}
.adventure-promo-image {
height: 100%;
object-fit: cover;
object-position: center center;
width: 100%;
}
叫用此React元件的方式如下:
<AdventurePromo adventure={adventureJSON}/>
將AdobeTargetActivity元件新增至React應用程式的 Home.js
在冒險清單之上。
src/components/Home.js
import AdventurePromo from './AdventurePromo';
import AdobeTargetActivity from './AdobeTargetActivity';
...
export default function Home() {
...
return(
<div className="Home">
<AdobeTargetActivity activityLocation={"wknd-adventure-promo"} OfferComponent={AdventurePromo}/>
<h2>Current Adventures</h2>
...
)
}
如果React應用程式未執行,請使用 npm run start
.
在兩種不同的瀏覽器中開啟React應用程式,以允許A/B測試向每個瀏覽器提供不同的體驗。 如果兩個瀏覽器顯示相同的冒險選件,請嘗試關閉/重新開啟其中一個瀏覽器,直到顯示另一個體驗。
下圖顯示兩個不同的內容片段選件,分別用於 wknd-adventure-promo
活動,根據Adobe Target的邏輯。
現在我們已將AEMas a Cloud Service設定為將內容片段匯出至Adobe Target、在Adobe Target活動中使用內容片段選件,並在AEM Headless應用程式中顯示該活動,進而個人化體驗。