[整合]{class="badge positive"}

整合AEM Headless和Target

[AEM Headlessas a Cloud Service]{class="badge informative"}

瞭解如何將AEM內容片段匯出至Adobe Target,以將AEM Headless與Adobe Target整合,並使用Adobe Experience Platform Web SDK的alloy.js來使用它們個人化Headless體驗。 React WKND應用程式用於探索如何使用內容片段選件來將個人化Target活動新增到體驗中,以促進WKND冒險。

本教學課程涵蓋設定AEM和Adobe Target的相關步驟:

Adobe IMS設定 adobe-ims-configuration

Adobe IMS設定可促進AEM與Adobe Target之間的驗證。

如需如何建立Adobe IMS設定的逐步指示,請參閱檔案

Adobe TargetCloud Service adobe-target-cloud-service

在AEM中建立Adobe TargetCloud Service,以方便將內容片段匯出至Adobe Target。

如需如何建立Adobe TargetCloud Service的逐步指示,請參閱檔案

設定資產資料夾 configure-asset-folders

在內容感知設定中設定的Adobe TargetCloud Service,必須套用至包含要匯出至Adobe Target的內容片段的AEM Assets資料夾階層。

展開以取得逐步指示
  1. 以DAM管理員身分登入​ AEM作者服務
  2. 導覽至​ Assets >檔案,找出已套用/conf的資產資料夾
  3. 選取資產資料夾,並從上方動作列選取​ 屬性
  4. 選取​ Cloud Service ​索引標籤
  5. 請確定雲端設定已設為包含Adobe Target Cloud Service設定的內容感知設定(/conf)。
  6. 從​ Cloud Service設定 ​下拉式清單中選取​ Adobe Target
  7. 選取右上方的​ 儲存並關閉

許可AEM Target整合 permission

Adobe Target整合(顯示為developer.adobe.com專案)必須授予Adobe Admin Console中的​ 編輯者 ​產品角色,才能將內容片段匯出至Adobe Target。

展開以取得逐步指示
  1. 以可在Adobe Admin Console中管理Adobe Target產品的使用者身分登入Experience Cloud
  2. 開啟Adobe Admin Console
  3. 選取​ 產品,然後開啟​ Adobe Target
  4. 在​ 產品設定檔 ​索引標籤上,選取​ 預設工作區
  5. 選取​ API認證 ​標籤
  6. 在此清單中找出您的developer.adobe.com應用程式,並將其​ 產品角色 ​設定為​ 編輯者

將內容片段匯出至目標 export-content-fragments

存在於已設定的AEM Assets資料夾階層下的內容片段,可以作為內容片段選件匯出至Adobe Target。 這些內容片段選件(Target中的特殊形式JSON選件)可用於Target活動,在Headless應用程式中提供個人化體驗。

展開以取得逐步指示
  1. 以DAM使用者身分登入​ AEM作者

  2. 導覽至「Assets >檔案」,並在「啟用Adobe Target」資料夾下找出要匯出為JSON至Target的內容片段

  3. 選取要匯出至Adobe Target的內容片段

  4. 在頂端動作列中選取​ 匯出至Adobe Target選件

    • 此動作會將內容片段的完全水合JSON表示法匯出至Adobe Target,做為「內容片段選件」

    • 可以在AEM中檢閱完全水合的JSON表示法

      • 選取內容片段
      • 展開側面板
      • 在左側面板中選取​ 預覽 ​圖示
      • 匯出至Adobe Target的JSON表示會顯示在主檢視中
  5. 以Adobe Target編輯器角色的使用者登入Adobe Experience Cloud

  6. Experience Cloud,從右上方的產品切換器中選取​ 目標 ​以開啟Adobe Target。

  7. 確定已在右上方的​ Workspace切換器 ​中選取預設Workspace。

  8. 選取頂端導覽列中的​ 選件 ​索引標籤

  9. 選取​ 型別 ​下拉式清單,並選取​ 內容片段

  10. 驗證從AEM匯出的內容片段是否出現在清單中

    • 將滑鼠停留在選件上,並選取​ 檢視 ​按鈕
    • 檢閱​ 選件資訊 ​並檢視直接在AEM Author服務中開啟內容片段的​ AEM深層連結

使用內容片段選件的Target活動 activity

在Adobe Target中,可建立使用內容片段選件JSON作為內容的活動,允許在Headless應用程式中使用在AEM中建立和管理內容的個人化體驗。

在此範例中,我們使用簡單的A/B活動,但可使用任何Target活動。

展開以取得逐步指示
  1. 選取頂端導覽列中的​ 活動 ​索引標籤

  2. 選取​ +建立活動,然後選取要建立的活動型別。

    • 此範例會建立簡單的​ A/B測試,但內容片段選件可支援任何活動型別
  3. 在​ 建立活動 ​精靈中

    • 選取​ 網頁
    • 在​ 選擇體驗撰寫器 ​中,選取​ 表單
    • 在​ 選擇Workspace ​中選取​ 預設Workspace
    • 在​ 選擇屬性 ​中,選取活動可用的屬性,或選取​ 無屬性限制 ​以允許在所有屬性中使用。
    • 選取​ 下一步 ​以建立活動
  4. 選取左上方的​ 重新命名,以重新命名活動

    • 為活動提供有意義的名稱
  5. 在初始體驗中,設定活動目標的​ 位置1

    • 在此範例中,將目標定位為名為wknd-adventure-promo的自訂位置
  6. 在「內容」下選取預設內容,然後選取「變更內容片段

  7. 選取要用於此體驗的匯出內容片段,並選取​ 完成

  8. 檢閱內容文字區域中的內容片段選件JSON,這是透過內容片段的預覽動作在AEM作者服務中提供的相同JSON。

  9. 在左側欄中新增體驗,並選取要提供的不同內容片段選件

  10. 選取​ 下一步,並依活動需求設定鎖定目標規則

    • 在此範例中,請將A/B測試保留為手動50/50分割。
  11. 選取​ 下一步,並完成活動設定

  12. 選取​ 儲存並關閉,並為它指定有意義的名稱

  13. 在Adobe Target的「活動」中,從右上角的「非使用中/啟動/封存」下拉式清單中選取「啟動」。

現在可以在AEM Headless應用程式中整合併公開鎖定在wknd-adventure-promo位置的Adobe Target活動。

Experience Platform資料串流ID datastream-id

AEM Headless應用程式需要Adobe Experience Platform資料流 ID,才能使用AdobeWeb SDK與Adobe Target互動。

展開以取得逐步指示
  1. 導覽至Adobe Experience Cloud

  2. 開啟​ Experience Platform

  3. 選取​ 資料收集>資料串流 ​並選取​ 新增資料串流

  4. 在「新增資料流」精靈中,輸入:

    • 名稱:AEM Target integration
    • 描述: Datastream used by the Adobe Web SDK to serve personalized Content Fragments Offers.
    • 事件結構描述: Leave blank
  5. 選取​ 儲存

  6. 選取​ 新增服務

  7. 在​ 服務 ​中選取​ Adobe Target

    • 已啟用:
    • 屬性Token: 留空
    • 目標環境ID: 保留空白
      • 可在Adobe Target中的​ 管理>主機 ​設定目標環境。
    • 目標協力廠商ID名稱空間: 保留空白
  8. 選取​ 儲存

  9. 在右側,複製​ 資料串流ID ​以用於AdobeWeb SDK設定呼叫。

將個人化新增至AEM Headless應用程式 code

本教學課程探討如何透過Adobe Experience Platform Web SDK,使用Adobe Target中的內容片段選件,個人化簡單的React應用程式。 此方法可用於個人化任何以JavaScript為基礎的網頁體驗。

Android™和iOS行動體驗可使用Adobe的行動SDK依類似的模式進行個人化。

先決條件

設定

  1. Github.com下載範例React應用程式的原始程式碼

    code language-shell
    $ mkdir -p ~/Code
    $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
    
  2. 在您最喜愛的IDE中,開啟位於~/Code/aem-guides-wknd-graphql/personalization-tutorial的程式碼基底

  3. 更新您要應用程式連線至~/Code/aem-guides-wknd-graphql/personalization-tutorial/src/.env.development的AEM服務主機

    code language-none
    ...
    REACT_APP_HOST_URI=https://publish-p1234-e5678.adobeaemcloud.com/
    ...
    
  4. 執行應用程式,並確保其連線至已設定的AEM服務。 從命令列,執行:

    code language-shell
    $ cd ~/Code/aem-guides-wknd-graphql/personalization-tutorial
    $ npm install
    $ npm run start
    
  5. AdobeWeb SDK安裝為NPM套件。

    code language-shell
    $ cd ~/Code/aem-guides-wknd-graphql/personalization-tutorial
    $ npm install @adobe/alloy
    

    Web SDK可用於程式碼中,以依活動位置擷取內容片段選件JSON。

    設定Web SDK時,需要兩個ID:

    • edgeConfigId,即資料流識別碼
    • orgId可在​ Experience Cloud>設定檔>帳戶資訊>目前組織ID ​找到的AEM as a Cloud Service/TargetAdobe組織ID

    叫用Web SDK時,Adobe Target活動位置(在我們的範例中,wknd-adventure-promo)必須設定為decisionScopes陣列中的值。

    code language-javascript
    import { createInstance } from "@adobe/alloy";
    const alloy = createInstance({ name: "alloy" });
    ...
    alloy("config", { ... });
    alloy("sendEvent", { ... });
    

實作

  1. 建立React元件AdobeTargetActivity.js以顯示Adobe Target活動。

    src/components/AdobeTargetActivity.js

    code language-javascript
    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元件如下:

    code language-jsx
    <AdobeTargetActivity activityLocation={"wknd-adventure-promo"} OfferComponent={AdventurePromo}/>
    
  2. 建立React元件AdventurePromo.js,以呈現JSON Adobe Target提供的冒險。

    此React元件採用代表冒險內容片段的完全水合的JSON,並以促銷方式顯示。 根據匯出至Adobe Target的內容片段,顯示從Adobe Target內容片段選件提供JSON服務的React元件可能視需要複雜多樣。

    src/components/AdventurePromo.js

    code language-javascript
    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

    code language-css
    .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元件的方式如下:

    code language-jsx
    <AdventurePromo adventure={adventureJSON}/>
    
  3. 將AdobeTargetActivity元件新增至React應用程式的Home.js (在冒險清單上方)。

    src/components/Home.js

    code language-javascript
    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>
              ...
        )
    }
    
  4. 如果React應用程式未執行,請使用npm run start重新啟動。

    在兩種不同的瀏覽器中開啟React應用程式,以便讓A/B測試為各瀏覽器提供不同的體驗。 如果兩個瀏覽器都顯示相同的冒險選件,請嘗試關閉/重新開啟其中一個瀏覽器,直到顯示另一個體驗為止。

    下圖根據Adobe Target的邏輯,顯示wknd-adventure-promo活動的兩個不同內容片段選件。

    體驗選件

恭喜!

現在我們已將AEM as a Cloud Service設定為將內容片段匯出至Adobe Target、在Adobe Target活動中使用內容片段選件,並在AEM Headless應用程式中顯示該活動,將體驗個人化。

recommendation-more-help
4859a77c-7971-4ac9-8f5c-4260823c6f69