AEM 64 - Creating Dynamic Brand specific Emails using Experience Fragments for Delivery using Adobe Campaign


Leveraging Experience Fragments (XF) in AEM and AEM - ACS (Adobe Campaign Standard) integration, create Brand specific emails with dynamic personalization based on the recipient's profile attributes...

Here the usecase is say, sending About Your State emails to profiles (managed in Adobe Campaign) on Independence Day; assuming the profiles in campaign have Address > State attribute entered

Demo | Package Install | Github


Following are the high level steps explaining creation of Dynamic Brand (here State) Specific Emails

1) Content authors specific to the territory (state) create state specific experience fragments in AEM e.g. Texas XF, California XF and tag it with respective state

2) Content approver creates the email by adding Experience AEM Dynamic EMail Experience Fragment Component, on AEM page of template type Adobe Campaign Email (ACS), selecting the campaign folder e.g. Summer 2019, starts and completes the workflow Approve for Adobe Campaign

3) On the ACS side, campaign manager creates a template for importing the AEM content with experience fragments and conditional expressions

4) Create an email selecting the target audience using Profile attribute State (stateLink)

5) Prepare and Send emails

Create Location Tags

Setup the Tag Structure in AEM. Identifying the right content (state specific) for a recipient's email is based on the tag its associated to...

e.g. Here adding the tag TX to an experience fragment sends it to Texas recipients

Create Experience Fragments

Enable the content authors to create state specific experience fragments...

1) Create an experience fragment of template type /libs/cq/experience-fragments/components/experiencefragment/template for Texas state with texas flag in a Image component and some write up about texas in a Text component e.g. /content/experience-fragments/summer_2019/texas-xf/master.html and tag it with /content/cq:tags/locations/TX

2) Similarly create the California XF /content/experience-fragments/summer_2019/california-xf/master.html tag it with /content/cq:tags/locations/CA

3) The experience fragments storage structure /content/experience-fragments/summer_2019

Create the Email Page

1) Assign the AEM - ACS cloud configuration to brand Experience AEM/content/campaigns/experience-aem

2) Create the Campaign page structure and page /content/campaigns/experience-aem/main-area/independence-day/about-states-email of template type /libs/mcm/campaign/templates/ac-email-acs

3) Drag and drop the component /apps/eaem-campaign-dynamic-emails-component/components/campaign-dynamic-email-xf-component and select path of the folder with campaign specific XFs (all XFs in this folder are tagged with their respective states TX, CA etc)

4) The component reads XFs, renders them and adds the necessary conditional expressions with context variables. we are interested in context variable context.profile.location.stateCode for the expression (read by campaign later during email delivery)


<div data-sly-use.dynamicEmail="DynamicEmailUsePojo">
    <div data-sly-test="${!dynamicEmail.regionContent}" style="padding:10px ; background-color: #3e999f">
        Select campaign folder with region specific experience fragments...
    <div data-sly-test="${dynamicEmail.regionContent}">
        <P>Hi <%= context.profile.lastName %>!</P>

        <div data-sly-list.stateCode="${dynamicEmail.regionContent}">
                ${dynamicEmail.conditionalExpressionBegin @ context='unsafe'}  if ( context.profile.location.stateCode == '${stateCode}' ) { ${dynamicEmail.conditionalExpressionEnd @ context='unsafe'}

                    <sly data-sly-resource="${@path=dynamicEmail.regionContent[stateCode], selectors='content', wcmmode='disabled'}"></sly>

                <% } %>

<div data-sly-test="${!wcmmode.disabled && !personalization.isTouch}"
     data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap>
    <meta data-sly-call="${clientLib.all @ categories='cq.personalization'}" data-sly-unwrap></meta>
    <script type="text/javascript">
        CQ.personalization.variables.Variables.applyToEditComponent("${resource.path @ context='scriptString'}");


package apps.eaem_campaign_dynamic_emails_component.components.campaign_dynamic_email_xf_component;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.cq.sightly.WCMUsePojo;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class DynamicEmailUsePojo extends WCMUsePojo {

    private static final Logger log = LoggerFactory.getLogger(DynamicEmailUsePojo.class);

    private static String CAMPAIGN_FOLDER_PATH = "campaignFolderPath";
    private static String EMAIL_BODY = "emailBody";
    private static String LOCATIONS_NAME_SPACE = "locations";

    private Map<String, String> regionContent = new HashMap<String, String>();

    public void activate() {
        String xfFolderPath = getProperties().get(CAMPAIGN_FOLDER_PATH, "");


        ResourceResolver resolver = getResourceResolver();

        Resource xfFolder = resolver.getResource(xfFolderPath);

        if(xfFolder == null){

        Iterator<Resource> xfFolderItr = xfFolder.listChildren();
        Page xfMaster = null;
        Tag[] tags = null;

            xfMaster ="master").adaptTo(Page.class);

            tags = xfMaster.getTags();

            if(ArrayUtils.isEmpty(tags)) {

            for(Tag tag : tags){

                regionContent.put(tag.getName(), xfMaster.getPath() + "/jcr:content");

    public Map<String, String> getRegionContent() {
        return regionContent;

    public String getConditionalExpressionBegin(){
        return "<% ";

    public String getConditionalExpressionEnd(){
        return " %>";

5) Run the workflow Approve for Adobe Campaign (make it available for ACS)

6) Since the images displayed in email are directly accessed from AEM Publish, publish the images added in XF /content/dam/experience-aem (this can be streamlined into a workflow step)

Setup the Delivery Template in ACS

1) Navigate to Adobe Campaign using Experience cloud solution switcher and access Delivery templates - Adobe Campaign Logo > Resources > Templates > Delivery Templates

2) Duplicate the template AEM Delivery Template and create States AEM Template for this campaign specific emails...

3) Edit the new template created States AEM Template, and import the email page content created in AEM - /content/campaigns/experience-aem/main-area/independence-day/about-states-email

Create & Send Brand (State) Specific Email

1) From Campaign Home click on Create an Email

2) Select the template States AEM Template created in previous section...

3) Enter email properties

4) In this step, select the profile attributes for targeting & personalization. Here we drag and drop the attribute Location > State (stateLink) and add rules, to pick the recipients belonging to Texas and California

5) Click on Prepare to run the prechecks, find number of deliveries etc.

6) Email sent statistics...

7) Profiles with state TX in address receive Texas specific content (added in Texas tagged experience fragment in AEM)

8) Profiles with state CA in address receive California specific content (added in California specific experience fragment)


  1. This comment has been removed by the author.

  2. Hi Sreekanth

    Thanks for sharing the insightful post. Do you think we can use email fragments created in AEM in Marketo?

    1. Potentially you can push email compliant XF to Marketo's REST endpoints as snippet:

  3. is it possible to use non profile fields for personalization ? we have a custom jason payload which will populate HTML content.

  4. Hi,
    That was really helpful. But I have got a few question:
    1. I don't see the template you are using for creating XF. Even though that path is already present in the settings for allowed Templates.
    2. I am using Campaign Classic, will your example work in that case?
    3. I got a little confused in the step where you created an email using ACS template, and then edited it. You are getting so many components
    available to be dragged and dropped, in my case i only see 5-6 components that can be dropped on the parsys. How can i get component options as many as yours?