Client Context in Detail

注意

用戶端內容已由觸控UI中的ContextHub取代。 如需詳細資訊,請參閱相關檔案

「用戶端內容」代表動態組合的使用者資料集合。 您可以使用資料來判斷在特定情況(內容定位)下要在網頁上顯示的內容。 此資料也可用於網站分析,以及頁面上的任何javascript。

Client Context主要包含下列方面:

  • 包含使用者資料的作業存放區。
  • 顯示使用者資料並提供工具以模擬使用者體驗的UI。
  • 用於與會話儲存交互的javascript API

若要建立獨立作業存放區並將其新增至「用戶端內容」,或建立系結至「內容存放區」元件的作業存放區。 安AEM裝幾個您可立即使用的Context Store元件。 您可以將這些元件當做元件的基礎。

如需有關開啟「用戶端內容」、設定其顯示的資訊以及模擬使用者體驗的詳細資訊,請參閱「用戶端內容」

會話儲存

「用戶端內容」包含包含使用者資料的各種作業儲存區。 儲存來自下列來源的資料:

  • 用戶端網頁瀏覽器。
  • 伺服器(請參閱JSONP Store以儲存來自第三方來源的資訊)

Client Context架構提供javascript API,您可用來與作業存放區互動,以讀取和寫入使用者資料,以及監聽和回應儲存事件。 您也可以針對您用於內容定位或其他目的的使用者資料建立工作階段儲存。

會話儲存資料仍保留在客戶端上。 客戶端上下文不會將資料寫回伺服器。 若要傳送資料至伺服器,請使用表單或開發自訂javascript。

每個作業存放區都是屬性值配對的集合。 會話儲存表示(任何類型)的資料集合,其概念含義可由設計人員和/或開發人員決定。 下列範例javascript程式碼定義一個物件,代表作業階段儲存可能包含的描述檔資料:

{
  age: 20,
  authorizableId: "aparker@geometrixx.info",
  birthday: "27 Feb 1992",
  email: "aparker@geometrixx.info",
  formattedName: "Alison Parker",
  gender: "female",
  path: "/home/users/geometrixx/aparker@geometrixx.info/profile"
}

作業存放區可跨瀏覽器作業持續存留,或僅適用於建立作業的瀏覽器作業。

注意

商店永續性使用瀏覽器儲存或Cookie(SessionPersistence Cookie)。 瀏覽器儲存空間更常見。

當瀏覽器關閉並重新開啟時,作業存放區可載入來自持續存放區的值。 然後需要清除瀏覽器快取,才能移除舊值。

上下文商店元件

上下文儲存元件是可AEM以添加到「客戶端上下文」的元件。 通常,上下文儲存元件顯示來自與其關聯的會話儲存的資料。 但是,上下文儲存元件顯示的資訊不限於會話儲存資料。

上下文商店元件可包含下列項目:

  • 定義客戶端上下文中外觀的JSP指令碼。
  • 用於在Sidekick中列出元件的屬性。
  • 編輯用於配置元件實例的對話框。
  • 初始化作業存放區的Javascript。

有關可添加到上下文儲存庫的已安裝的上下文儲存庫元件的說明,請參閱可用客戶端上下文元件

注意

「頁面資料」不再以預設元件的形式出現在用戶端內容中。 如有需要,您可以編輯用戶端內容、新增​一般商店屬性​元件,然後設定此元件,將​商店​定義為pagedata

目標內容傳送

描述檔資訊也用於傳送目標內容

clientcontext_ targetedcontentdeliveryclientcontext_targetedcontentdeliverydetail

將客戶端上下文添加到頁面

將「用戶端內容」元件加入網頁的正文區段,以啟用「用戶端內容」。 「客戶端上下文」元件節點的路徑為/libs/cq/personalization/components/clientcontext。 要包含該元件,請將以下代碼添加到頁面元件的JSP檔案中,該檔案位於頁面的body元素的正下方:

<cq:include path="clientcontext" resourceType="cq/personalization/components/clientcontext"/>

clientcontext元件會使頁面載入實作「用戶端內容」的用戶端程式庫。

  • 用戶端內容javascript API。
  • 支援工作階段儲存、事件管理等的Client Context架構。
  • 定義的區段。
  • 為每個已添加到客戶端上下文的上下文儲存元件生成的init.js指令碼。
  • (僅限作者例項)用戶端內容UI。

用戶端內容UI僅適用於作者例項。

擴展客戶端上下文

若要擴充用戶端內容,請建立作業存放區並選擇性地顯示儲存資料:

  • 為您針對內容定位和網頁分析所需的使用者資料建立工作階段商店。
  • 建立內容儲存區元件,讓管理員可設定關聯的工作階段儲存區,並在「用戶端內容」中顯示儲存資料,以便進行測試。
注意

如果您有(或建立)可提供資料的JSONP服務,您只需使用JSONP內容儲存元件並將它對應至JSONP服務。 這將處理會話儲存。

建立會話儲存

為需要添加到客戶端上下文並從中檢索的資料建立會話儲存。 通常,您使用以下過程建立會話儲存:

  1. 建立具有categories屬性值personalization.stores.kernel的客戶端庫資料夾。 Client Context會自動載入此類別的用戶端程式庫。

  2. 配置客戶端庫資料夾,使其與personalization.core.kernel客戶端庫資料夾相依。 personalization.core.kernel用戶端程式庫提供用戶端內容javascript API。

  3. 新增建立和初始化作業存放區的javascript。

將javascript包含在personalization.stores.kernel客戶程式庫中,會在載入Client Context架構時建立商店。

注意

如果您要建立作為內容儲存元件一部分的作業儲存區,則可以選擇將javascript置於元件的init.js.jsp檔案中。 在這種情況下,只有將元件添加到「客戶端上下文」中時,才會建立會話儲存。

會話儲存的類型

作業存放區會在瀏覽器作業期間建立並可用,或保存在瀏覽器儲存區或Cookie中。 Client Context javascript API定義了數個表示兩種資料儲存類型的類別:

API也提供這些類別的擴充功能,這些類別專門用來儲存JSON資料或JSONP資料:

建立會話儲存對象

用戶端程式庫資料夾的javascript會建立並初始化工作階段商店。 然後,必須使用上下文商店管理員註冊作業商店。 下面的示例建立並註冊CQ_Analytics.SessionStore對象。

//Create the session store
if (!CQ_Analytics.MyStore) {
    CQ_Analytics.MyStore = new CQ_Analytics.SessionStore();
    CQ_Analytics.MyStore.STOREKEY = "MYSTORE";
    CQ_Analytics.MyStore.STORENAME = "mystore";
    CQ_Analytics.MyStore.data={};
}
//register the session store
if (CQ_Analytics.ClientContextMgr){
    CQ_Analytics.ClientContextMgr.register(CQ_Analytics.MyStore)
}

若要儲存JSON資料,下列範例會建立並註冊CQ_Analytics.JSONStore物件。

if (!CQ_Analytics.myJSONStore) {
    CQ_Analytics.myJSONStore = CQ_Analytics.JSONStore.registerNewInstance("myjsonstore",{});
}

建立上下文儲存元件

建立內容儲存元件,以在「用戶端內容」中呈現工作階段儲存資料。 建立後,您可將內容存放區元件拖曳至「用戶端內容」,以從作業存放區轉譯資料。 上下文商店元件包含下列項目:

  • 用於呈現資料的JSP指令碼。
  • 編輯對話框。
  • 用於初始化會話儲存的JSP指令碼。
  • (可選)用於建立會話儲存的客戶端庫資料夾。 如果元件使用現有會話儲存,則不需要包括客戶端庫資料夾。

擴展提供的上下文儲存元件

提AEM供一般商店和一般商店屬性上下文商店可擴充的元件。 儲存資料的結構決定了擴展的元件:

  • 屬性——值對:擴展GenericStoreProperties元件。 此元件會自動呈現屬性值對的儲存區。 提供數個互動點:

    • prolog.jspepilog.jsp:元件互動功能,可讓您在元件轉換之前或之後新增伺服器端邏輯。
  • 複雜資料:擴展GenericStore元件。 然後,您的作業商店將需要「轉譯器」方法,每次需要轉譯元件時都會呼叫此方法。 轉換程式函式是使用兩個參數來呼叫:

    • @param {String} store

      要演算的商店

    • @param {String} divId

      必須呈現商店的div的ID。

注意

所有客戶端上下文元件都是通用儲存或通用儲存屬性元件的擴展。 在/libs/cq/personalization/components/contextstores資料夾中安裝了幾個範例。

在Sidekick中配置外觀

編輯「用戶端內容」時,內容儲存元件會顯示在Sidekick中。 與所有元件一樣,客戶端上下文元件的componentGroupjcr:title屬性確定元件的組和名稱。

預設情況下,componentGroup屬性值Client Context的所有元件都顯示在Sidekick中。 如果您對componentGroup屬性使用不同的值,則必須使用「設計」模式手動將元件添加到Sidekick。

上下文儲存元件實例

將上下文儲存元件添加到「客戶端上下文」時,將在/etc/clientcontext/default/content/jcr:content/stores下建立代表元件實例的節點。 此節點包含使用元件的編輯對話框配置的屬性值。

初始化「客戶端上下文」時,會處理這些節點。

初始化關聯的會話儲存

將init.js.jsp檔案新增至元件,以產生Javascript程式碼,以初始化上下文儲存區元件所使用的工作階段儲存區。 例如,使用初始化指令碼檢索元件的配置屬性,並使用這些屬性填充會話儲存。

當在作者和發佈例項的頁面載入時初始化「用戶端內容」時,產生的Javascript會新增至頁面。 此JSP在載入和呈現上下文儲存元件實例之前執行。

代碼必須將檔案的MIME類型設定為text/javascript,否則不會執行。

注意

init.js.jsp指令碼會在作者和發佈例項上執行,但前提是上下文儲存元件已新增至用戶端內容。

以下過程建立init.js.jsp指令碼檔案並添加設定正確MIME類型的代碼。 執行儲存初始化的代碼將遵循。

  1. 按一下右鍵上下文儲存元件節點,然後按一下「建立」(Create)>「建立檔案」(Create File)。

  2. 在「Name(名稱)」欄位中,鍵入init.js.jsp ,然後按一下「OK(確定)」。

  3. 在頁面頂端,新增下列程式碼,然後按一下「全部儲存」。

    <%@page contentType="text/javascript" %>
    

呈現一般儲存屬性元件的會話儲存資料

使用一致的格式,在「用戶端內容」中顯示工作階段儲存資料。

顯示屬性資料

個人化標籤庫提供personalization:storePropertyTag標籤,顯示會話商店中屬性的值。 若要使用標籤,請在JSP檔案中加入下列程式碼行:

<%@taglib prefix="personalization" uri="https://www.day.com/taglibs/cq/personalization/1.0" %>

標籤具有下列格式:

<personalization:storePropertyTag propertyName="property_name" store="session_store_name"/>

propertyName屬性是要顯示之商店屬性的名稱。 store屬性是註冊商店的名稱。 下列範例標籤顯示profile商店的authorizableId屬性值:

<personalization:storePropertyTag propertyName="authorizableId" store="profile"/>

HTML結構

personalization.ui用戶端資料庫檔案夾(/etc/clientlibs/foundation/personalization/ui/themes/default?lang=zh-Hant)提供「用戶端內容」用來設定HTML程式碼格式的CSS樣式。 下列程式碼說明用於顯示儲存資料的建議結構:

<div class="cq-cc-store">
   <div class="cq-cc-thumbnail">
      <div class="cq-cc-store-property">
           <!-- personalization:storePropertyTag for the store thumbnail image goes here -->
      </div>
   </div>
   <div class="cq-cc-content">
       <div class="cq-cc-store-property cq-cc-store-property-level0">
           <!-- personalization:storePropertyTag for a store property goes here --> 
       </div>
       <div class="cq-cc-store-property cq-cc-store-property-level1">
           <!-- personalization:storePropertyTag for a store property goes here --> 
       </div>
       <div class="cq-cc-store-property cq-cc-store-property-level2">
           <!-- personalization:storePropertyTag for a store property goes here --> 
       </div>
       <div class="cq-cc-store-property cq-cc-store-property-level3">
           <!-- personalization:storePropertyTag for a store property goes here --> 
       </div>
   </div>
   <div class="cq-cc-clear"></div>
</div>

/libs/cq/personalization/components/contextstores/profiledata上下文儲存元件使用此結構來顯示配置檔案會話儲存中的資料。 cq-cc-thumbnail類別會放置縮圖影像。 cq-cc-store-property-level*x*類別會格式化英數字元資料:

  • level0、level1和level2是垂直分佈的,並使用白字型。
  • level3及任何其他層級均以水準分佈,並使用較深色背景的白色字型。

chlimage_1-222

為一般儲存元件呈現會話儲存資料

若要使用一般商店元件來轉換商店資料,您必須:

  • 將personalization:storeRendererTag標籤新增至元件JSP指令碼,以識別作業商店的名稱。
  • 在會話儲存類上實現渲染器方法。

標識一般儲存會話儲存

個人化標籤庫提供personalization:storePropertyTag標籤,顯示會話商店中屬性的值。 若要使用標籤,請在JSP檔案中加入下列程式碼行:

<%@taglib prefix="personalization" uri="https://www.day.com/taglibs/cq/personalization/1.0" %>

標籤具有下列格式:

<personalization:storeRendererTag store="store_name"/>

實施會話儲存渲染器方法

然後,您的作業商店將需要「轉譯器」方法,每次需要轉譯元件時都會呼叫此方法。 轉換程式函式是使用兩個參數來呼叫:

  • @param {String} store

    要演算的商店

  • @param {String} divId

    必須呈現商店的div的ID。

與會話儲存庫交互

使用javascript與作業存放區互動。

訪問會話儲存

獲取會話儲存對象以讀取或寫入資料到儲存。 CQ_Analytics.ClientContextMgr 根據商店名稱提供對商店的存取。取得後,使用CQ-Analytics.SessionStoreCQ-Analytics.PersistedSessionStore的方法與儲存資料互動。

下面的示例獲取profile儲存,然後從儲存中檢索formattedName屬性。

function getName(){
   var profilestore = CQ_Analytics.ClientContextMgr.getRegisteredStore("profile");
   if(profilestore){
      return profilestore.getProperty("formattedName", false);
   } else {
      return null;
   }
} 

建立偵聽器以響應會話儲存更新

工作階段會儲存觸發事件,因此可以新增監聽器並根據這些事件觸發事件。

會話儲存器是基於Observable模式構建的。 它們會延伸CQ_Analytics.Observable,提供addListener方法。

以下示例向profile會話儲存的update事件添加偵聽器。

var profileStore = ClientContextMgr.getRegisteredStore("profile");
if( profileStore ) {
  //callback execution context
  var executionContext = this;

  //add "update" event listener to store
  profileStore.addListener("update",function(store, property) {
    //do something on store update

  },executionContext);
}

檢查是否已定義並初始化會話儲存

會話儲存在載入並用資料初始化之前不可用。 下列因素可能會影響作業存放區可用性的時間:

  • 頁面載入
  • JavaScript載入
  • JavaScript執行時間
  • XHR請求的回應時間
  • 會話儲存的動態更改

使用CQ_Analytics.ClientContextUtils物件的onStoreRegisteredonStoreInitialized方法,僅在會話儲存可用時才可存取這些儲存。 這些方法可讓您註冊回應作業註冊和初始化事件的事件接聽程式。

注意

如果您依賴其他商店,則需要迎合從未註冊商店的情況。

以下示例使用profile會話儲存的onStoreRegistered事件。 在註冊儲存時,會向會話儲存的update事件添加偵聽器。 當商店更新時,頁面上的<div class="welcome">元素內容會以profile商店的名稱更新。

//listen for the store registration
CQ_Analytics.ClientContextUtils.onStoreRegistered("profile", listen);

//listen for the store's update event
function listen(){
 var profilestore = CQ_Analytics.ClientContextMgr.getRegisteredStore("profile");
    profilestore.addListener("update",insertName);
}

//insert the welcome message
function insertName(){
 $("div.welcome").text("Welcome "+getName());
}

//obtain the name from the profile store
function getName(){
 var profilestore = CQ_Analytics.ClientContextMgr.getRegisteredStore("profile");
 if(profilestore){
  return profilestore.getProperty("formattedName", false);
    } else {
        return null;
    }
}

若要防止PersistedSessionStore的屬性持續存在(亦即從sessionpersistence Cookie中排除它),請將屬性新增至持續作業商店的非持續屬性清單。

請參閱 CQ_Analytics.PersistedSessionStore.setNonPersisted(propertyName)

CQ_Analytics.ClientContextUtils.onStoreRegistered("surferinfo", function(store) {
  //this will exclude the browser, OS and resolution properties of the surferinfo session store from the 
  store.setNonPersisted("browser");
  store.setNonPersisted("OS");
  store.setNonPersisted("resolution");
});

配置設備滑塊

條件

目前頁面必須有對應的行動頁面;這只有在頁面有LiveCopy設定為行動轉出設定(rolloutconfig.path.toLowerCase包含mobile)時才會決定。

設定

從案頭頁面切換至其行動裝置頁面時:

  • 已載入行動頁面的DOM。

  • div(必要)包含內容,會擷取並插入目前的案頭頁面。

  • 需要載入的CSS和內文類別需要手動設定。

例如:

window.CQMobileSlider["geometrixx-outdoors"] = {
  //CSS used by desktop that need to be removed when mobile
  DESKTOP_CSS: [
    "/etc/designs/${app}/clientlibs_desktop_v1.css"
  ],
  
  //CSS used by mobile that need to be removed when desktop
  MOBILE_CSS: [
    "/etc/designs/${app}/clientlibs_mobile_v1.css"
  ],
  
  //id of the content that needs to be removed when mobile
  DESKTOP_MAIN_ID: "main",
  
  //id of the content that needs to be removed when desktop
  MOBILE_MAIN_ID: "main",
  
  //body classes used by desktop that need to be removed when mobile
  DESKTOP_BODY_CLASS: [
    "page"
  ],
  
  //body classes used by mobile that need to be removed when desktop
  MOBILE_BODY_CLASS: [
    "page-mobile"
  ]
};

範例:建立自訂內容存放區元件

在此示例中,您建立上下文儲存元件,該元件從外部服務中檢索資料並將其儲存在會話儲存中:

  • 延伸一般儲存屬性元件。
  • 使用CQ_Analytics.JSONPStore javascript物件初始化商店。
  • 呼叫JSONP服務以擷取資料並將其新增至商店。
  • 在用戶端內容中轉譯資料。

添加geoloc元件

建立CQ應用程式並新增geoloc元件。

  1. 在您的網頁瀏覽器中開啟CRXDE Lite(http://localhost:4502/crx/de)。

  2. 按一下右鍵/apps資料夾,然後按一下「建立」>「建立資料夾」。 指定myapp的名稱,然後按一下「確定」。

  3. 同樣地,在myapp下方,建立名為contextstores的資料夾。"

  4. 按一下右鍵/apps/myapp/contextstores資料夾,然後按一下「建立」>「建立元件」。 指定下列屬性值,然後按一下「下一步」:

    • 標籤:geoloc
    • 標題:位置商店
    • 超級類型: cq/personalization/components/contextstores/genericstoreproperties
    • 群組:客戶端上下文
  5. 在「建立元件」對話方塊中,按一下每頁的「下一步」,直到啟用「確定」按鈕,然後按一下「確定」。

  6. 按一下「全部儲存」。

建立geoloc編輯對話框

上下文儲存區元件需要編輯對話方塊。 geoloc edit對話框將包含一條靜態消息,指出沒有要配置的屬性。

  1. 按一下右鍵/libs/cq/personalization/components/contextstores/genericstoreproperties/dialog節點,然後按一下「複製」。

  2. 按一下右鍵/apps/myapp/contextstores/geoloc節點,然後按一下「貼上」。

  3. 刪除/apps/myapp/contextstores/geoloc/dialog/items/items/tab1/items節點下的所有子節點:

    • 商店
    • 屬性
    • 縮圖
  4. 按一下右鍵/apps/myapp/contextstores/geoloc/dialog/items/items/tab1/items節點,然後按一下「建立」>「建立節點」。 指定下列屬性值,然後按一下「確定」:

    • 名稱:static
    • 類型:cq:Widget
  5. 將以下屬性添加到節點:

    名稱 類型
    cls 字串 x-form-fieldset-description
    文字 字串 geoloc元件不需要配置。
    xtype 字串 靜態
  6. 按一下「全部儲存」。

    chlimage_1-223

建立初始化指令碼

將init.js.jsp檔案新增至geoloc元件,並使用它來建立作業存放區、擷取位置資料,並將它新增至存放區。

init.js.jsp檔案會在頁面載入用戶端內容時執行。 目前,用戶端內容javascript API已載入,可供您的指令碼使用。

  1. 按一下右鍵/apps/myapp/contextstores/geoloc節點,然後按一下​建立->建立檔案。 指定init.js.jsp的名稱,然後按一下「確定」。

  2. 將下列程式碼新增至頁面頂端,然後按一下「全部儲存」。

    <%@page contentType="text/javascript;charset=utf-8" %><%
    %><%@include file="/libs/foundation/global.jsp?lang=zh-Hant"%><%
    log.info("***** initializing geolocstore ****");
    String store = "locstore";
    String jsonpurl = "https://api.wipmania.com/jsonp?callback=${callback}";
    
    %>
    var locstore = CQ_Analytics.StoreRegistry.getStore("<%= store %>");
    if(!locstore){
     locstore = CQ_Analytics.JSONPStore.registerNewInstance("<%= store %>", "<%= jsonpurl %>",{});
    }
    <% log.info(" ***** done initializing geoloc ************"); %>
    

呈現geoloc會話儲存資料

將代碼添加到geoloc元件的JSP檔案中,以在Client Context中呈現儲存資料。

chlimage_1-224

  1. 在CRXDE Lite中,開啟/apps/myapp/contextstores/geoloc/geoloc.jsp檔案。

  2. 在存根程式碼下方新增下列HTML程式碼:

    <%@taglib prefix="personalization" uri="https://www.day.com/taglibs/cq/personalization/1.0" %>
    <div class="cq-cc-store">
       <div class="cq-cc-content">
           <div class="cq-cc-store-property cq-cc-store-property-level0">
               Continent: <personalization:storePropertyTag propertyName="address/continent" store="locstore"/> 
           </div>
           <div class="cq-cc-store-property cq-cc-store-property-level1">
               Country: <personalization:storePropertyTag propertyName="address/country" store="locstore"/> 
           </div>
           <div class="cq-cc-store-property cq-cc-store-property-level2">
               City: <personalization:storePropertyTag propertyName="address/city" store="locstore"/> 
           </div>
           <div class="cq-cc-store-property cq-cc-store-property-level3">
               Latitude: <personalization:storePropertyTag propertyName="latitude" store="locstore"/> 
           </div>
           <div class="cq-cc-store-property cq-cc-store-property-level4">
               Longitude: <personalization:storePropertyTag propertyName="longitude" store="locstore"/> 
           </div>
       </div>
        <div class="cq-cc-clear"></div>
    </div>
    
  3. 按一下「全部儲存」。

將元件添加到客戶端上下文

將Location Store元件新增至Client Context,以便在頁面載入時初始化它。

  1. 開啟作者例項(http://localhost:4502/content/geometrixx-outdoors/en.html)上的Geometrixx Outdoors首頁。

  2. 按一下Ctrl-Alt-c(windows)或control-option-c(Mac)以開啟「用戶端內容」。

  3. 按一下「用戶端內容」頂端的編輯圖示,以開啟「用戶端內容設計器」。

  4. 將Location Store元件拖曳至Client Context。

請參閱客戶端上下文中的位置資訊

以編輯模式開啟Geometrixx Outdoors首頁,然後開啟用戶端內容,以查看位置商店元件中的資料。

  1. 開啟Geometrixx Outdoors網站的英文頁面。 (http://localhost:4502/content/geometrixx-outdoors/en.html)
  2. 要開啟「客戶端上下文」,請按Ctrl-Alt-c(windows)或control-option-c(Mac)。

建立自定義客戶端上下文

要建立第二個客戶機上下文,您需要複製分支:

/etc/clientcontext/default

  • 子資料夾:

    /content

    將包含自訂用戶端內容的內容。

  • 資料夾:

    /contextstores

    允許您為上下文儲存庫定義不同的配置。

若要使用自訂的用戶端內容,請編輯屬性
path
在客戶端上下文元件的設計樣式中,如頁面模板中所示。 例如,作為以下的標準位置:
/libs/cq/personalization/components/clientcontext/design_dialog/items/path

本頁內容

Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Summit Banner

A virtual event April 27-28.

Expand your skills and get inspired.

Register for free
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now