---
schema_version: "1"
id: 1628fda8ac0bf7eb61ba23a91794ea6979cd38df44c0df9e984f0c72f008f0aa
title: Custom Personalization Interaction Examples
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/mktg/264-0-0/mc_dm_cpi_examples.md
canonical_url: https://help.salesforce.com/s/articleView?id=mktg.mc_dm_cpi_examples.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: afe787b114f3f4fe3957cc7016e2f1ec46e2e07e85a427b3f8fb948bad2293ab
description: Use these common use case examples to guide your custom personalization interaction setup in Marketing Cloud Engagement.
products:
  - Marketing
  - Cross Cloud
release: "264"
---
# Custom Personalization Interaction Examples

Use these common use case examples to guide your custom personalization interaction setup in Marketing Cloud Engagement.

Example 1: Custom Subject Line

This Custom Personalization Interaction example allows a user to specify a custom subject to override the default subject. There’s an entry for the custom subject in your Marketing Cloud Engagement Data Extension and in your Profile Attributes. In this example we use the customSubjectLine field. In Marketing Cloud Engagement, edit the email and select a dynamic subject. Click the lightning bolt below the subject.

Specify a default subject and create a rule. The subject for this new rule is `%%customSubjectLine%%`. Drag in the customSubjectLine profile attribute into the filters and change “is equal to” to “isn’t empty.” Save all the changes and save the email.

```

customSubjectLine.cmp
<aura:component access="GLOBAL" implements="mcdm_15:MessagePersonalizationHandler">
    <aura:attribute
        access="GLOBAL"
        name="personalizationReadyHandler"
        type="Aura.Action"
        default="{!c.messagePersonalizationReady}"
    />
<aura:attribute name="customSubjectLine" access="private" type="String" description="Custom email subject line"/>
   <aura:attribute name="selectedMembers" access="private" type="Object[]" description="The currently selected object"/>
  
   <aura:handler name="init" value="{!this}" action="{!c.init}"/>
<lightning:spinner variant="brand" size="large" aura:id="mySpinner"/>

   <div class="slds-card">
       <div class="slds-card__header">
           <div class="slds-media slds-media_center">
               <div class="slds-media__figure">
                   <lightning:icon iconName="custom:custom24" size="large"/>
               </div>
               <div class="slds-media__body">
                   <p class="slds-text-heading_small">Custom subject line demo component</p>
                   <p>Every change fires a <span class="slds-theme_shade">mcdm_15:JourneyApprovalsDataProvided</span> event</p>
               </div>
           </div>
       </div>
      
       <div class="slds-card__body slds-card__body_inner">
           <div>
               <p class="slds-text-title slds-text-align_center">'{!v.selectedMembers.length}' user(s) selected</p>
           </div>
           <div class="slds-m-around_medium">
               <lightning:input class="slds-m-bottom_small" label="Custom Subject Line" value="{!v.customSubjectLine}" onchange="{!c.handleInputChanged}"/>
           </div>
       </div>
   </div>
</aura:component>
customSubjectLineController.js
({
   init: function(cmp) {
       cmp.set('v.selectedMembers', []);
   },
  
   // Handler called when component is ready and receives a list of
   // members being personalized including all relevant information
   // required to customize member personalization
   messagePersonalizationReady: function(cmp, event) {
       var selectedMembers = event.getParam('arguments').members;
       cmp.set('v.selectedMembers', selectedMembers);
       if (selectedMembers.length) {
           // In this example, the custom subject applies to all members
           // so we can grab the customData from the first member
           var data = selectedMembers[0].customData || {};
           cmp.set('v.customSubjectLine', data.customSubjectLine || '');
       }
       var spinner = cmp.find('mySpinner');
       $A.util.addClass(spinner, 'slds-hide');
   },
  
   // Handles changes to the text field (Subject)
   // On each key down, this handler will store the custom
   // subject changes in each members custom data
   handleInputChanged: function(cmp) {
       var data = {
           customSubjectLine: cmp.get('v.customSubjectLine')
       };

       var selectedMembers = cmp.get('v.selectedMembers'),
           id,
           dataProvidedEvent;
      
       // Loop through each member and fire an event to update its custom
       // data with the new changes
       selectedMembers.forEach(function(member) {
           dataProvidedEvent = $A.get('e.mcdm_15:JourneyApprovalsDataProvided');
           // Depending on whether we're dealing with a campaign or quick send
           // use the campaignMemberId or fallback to the objectId which will
           // be present in all other cases.
           id = member.campaignMemberId || member.objectId;
           dataProvidedEvent.setParams({
               id: id,
               data: data
           });
           dataProvidedEvent.fire();
       });
   }
})
```

Example 2: Custom Send From (Team Sending)

This Custom Personalization Interaction example allows a user to change who the email is coming from by specifying a member of the same group.

Create an apex class to retrieve the group members.

```
GroupMemberController.apxc
public with sharing class GroupMembersController {
   @AuraEnabled
   public static List<User> getGroupMembers() {
       String currentUser = UserInfo.getUserId();
       GroupMember myGroup = [SELECT GroupId FROM GroupMember WHERE UserOrGroupId = :currentUser];
      
       List<User> groupMembers = [
           SELECT Name, Email from User WHERE Id in (SELECT userorgroupid from groupmember where group.Id = :myGroup.GroupId)
       ];
      
       return groupMembers;
   }
}
sendFromGroupMember.cmp
<aura:component access="GLOBAL" implements="mcdm_15:MessagePersonalizationHandler" controller="GroupMembersController">
   <aura:attribute access="GLOBAL" name="personalizationReadyHandler" type="Aura.Action" default="{!c.messagePersonalizationReady}"/>
  
   <aura:attribute name="selectedMembers" access="private" type="Object[]" description="The currently selected object"/>
   <aura:attribute name="groupMembers" access="private" type="List" description="List of group members"/>
   <aura:attribute name="sendFromValue" access="private" type="Integer" default="" description="Value of selected send from" />
  
   <aura:handler name="init" value="{!this}" action="{!c.init}"/>
  
   <lightning:spinner variant="brand" size="large" aura:id="mySpinner"/>

   <div class="slds-card">
       <div class="slds-card__header">
           <div class="slds-media slds-media_center">
               <div class="slds-media__figure">
                   <lightning:icon iconName="custom:custom24" size="large"/>
               </div>
               <div class="slds-media__body">
                   <p class="slds-text-heading_small">Send From Group Member Demo</p>
                   <p>Every change fires a <span class="slds-theme_shade">mcdm_15:JourneyApprovalsDataProvided</span> event</p>
               </div>
           </div>
       </div>
      
       <div class="slds-card__body slds-card__body_inner">
           <div>
               <p class="slds-text-title slds-text-align_center">'{!v.selectedMembers.length}' user(s) selected</p>
           </div>
           <div class="slds-m-around_medium">
               <lightning:select aura:id="selectGroupMembers" class="slds-m-bottom_small" name="selectGroupMembers" label="Send From Group Member" value="{!v.sendFromValue}" onchange="{!c.handleSelectChanged}">
                   <option value="">-- None --</option>
                   <aura:iteration items="{!v.groupMembers}" var="member">
                       <option value="{!_index}" text="{!member.Name}"></option>
                   </aura:iteration>
               </lightning:select>
           </div>
       </div>
   </div>
</aura:component>
sendFromGroupMemberController.js
({
   init: function(cmp, event, helper) {
       cmp.set('v.selectedMembers', []);
   },
  
   // Handler called when component is ready and receives a list of
   // members being personalized including all relevant information
   // required to customize member personalization
   messagePersonalizationReady: function(cmp, event, helper) {
       var selectedMembers = event.getParam('arguments').members;
       cmp.set('v.selectedMembers', selectedMembers);
      
       helper.fetchGroupMembers(cmp)
       .then(function(groupMembers) {   
           if (selectedMembers.length) {
               // In this example, the custom subject applies to all members
               // so we can grab the customData from the first member
               var data = selectedMembers[0].customData || {};
              
               // Go through group members update selected value if a value
               // was previously selected
               for (var i=0; i<groupMembers.length; i++) {
                   if (groupMembers[i].Email == data.customSendFromEmail) {
                       cmp.find("selectGroupMembers").set("v.value", i);
                   }
               }
           }
           var spinner = cmp.find('mySpinner');
           $A.util.addClass(spinner, 'slds-hide');
       });
   },
  
   // Handles changes to send from group member drop down
   // and updates all members custom data
   handleSelectChanged: function(cmp, event) {
       var members = cmp.get('v.groupMembers'),
           selectedMembers = cmp.get('v.selectedMembers'),
           id,
           dataProvidedEvent,
           value = cmp.find('selectGroupMembers').get('v.value'),
           data;
      
       if (value != "") {
           cmp.set('v.sendFromValue', value);
           data = {
               customSendFromEmail: members[value].Email,
               customSendFromName: members[value].Name
           };
       } else {
           data = {};
       }
      
       // Loop through each member and fire an event to update its custom
       // data with the new changes
       selectedMembers.forEach(function(member) {
           dataProvidedEvent = $A.get('e.mcdm_15:JourneyApprovalsDataProvided');
           // Depending on whether we're dealing with a campaign or quick send
           // use the campaignMemberId or fallback to the objectId which will
           // be present in all other cases.
           id = member.campaignMemberId || member.objectId;
           dataProvidedEvent.setParams({
               id: id,
               data: data
           });
           dataProvidedEvent.fire();
       });
   }
})
sendFromGroupMemberHelper.js
({
   // Fetches members in the same group as the logged in user and returns
   // a promise.
   // https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_promises.htm
   fetchGroupMembers : function(cmp) {
       return new Promise($A.getCallback(function(resolve, reject) {
           var action = cmp.get('c.getGroupMembers');
           action.setCallback(this, function(response) {
               if (!cmp.isValid() || response.getState() !== 'SUCCESS') {
                   reject(response.getError());
               } else {
                   cmp.set('v.groupMembers', response.getReturnValue());
                   resolve(response.getReturnValue());
               }
           });
          
           $A.enqueueAction(action);
       }));
   }
})
```

Example 3: Modify Specific Members

This Custom Personalization Interaction example allows a user to customize different values for each member.

```
modifySpecificMember.cmp
<aura:component access="GLOBAL" implements="mcdm_15:MessagePersonalizationHandler">
   <aura:attribute access="GLOBAL" name="personalizationReadyHandler" type="Aura.Action" default="{!c.messagePersonalizationReady}"/>
  
   <aura:attribute name="selectedMembers" access="private" type="Object[]" description="The currently selected object"/>
   <aura:attribute name="selectedMemberIndex" access="private" type="Integer" default="null" description="Index of the selected member"/>
   <aura:attribute name="selectedMemberId" access="private" type="String" description=""/>
   <aura:attribute name="selectedMemberData" access="private" type="String" description="Custom data for member"/>
  
   <aura:handler name="init" value="{!this}" action="{!c.init}"/>
  
   <lightning:spinner variant="brand" size="large" aura:id="mySpinner"/>

   <div class="slds-card">
       <div class="slds-card__header">
           <div class="slds-media slds-media_center">
               <div class="slds-media__figure">
                   <lightning:icon iconName="custom:custom24" size="large"/>
               </div>
               <div class="slds-media__body">
                   <p class="slds-text-heading_small">Modify specific members demo</p>
                   <p>Every change fires a <span class="slds-theme_shade">mcdm_15:JourneyApprovalsDataProvided</span> event</p>
               </div>
           </div>
       </div>
      
       <div class="slds-card__body slds-card__body_inner">
           <div>
               <p class="slds-text-title slds-text-align_center">'{!v.selectedMembers.length}' user(s) selected</p>
           </div>
           <div class="slds-m-around_medium">
               <lightning:select aura:id="member" class="slds-m-bottom_small" name="memberCustom" label="member custom data" onchange="{!c.handleMemberChanged}" value="{!v.selectedMemberIndex}">
                   <option value="">Select a member</option>
                   <aura:iteration items="{!v.selectedMembers}" var="member">
                       <option value="{!_index}" text="{!member.firstName + ' ' + member.lastName}"></option>
                   </aura:iteration>
               </lightning:select>
              
               <aura:if isTrue="{!not(empty(v.selectedMemberId))}">
                   <lightning:input class="slds-m-bottom_small" label="Custom Member Data" value="{!v.selectedMemberData}" onchange="{!c.handleInputChanged}"/>
               </aura:if>
           </div>
       </div>
   </div>
</aura:component>
modifySpecificMemberController.js
({
   init: function(cmp, event, helper) {
       cmp.set('v.selectedMembers', []);
   },
  
   // Handler called when component is ready and receives a list of
   // members being personalized including all relevant information
   // required to customize member personalization
   messagePersonalizationReady: function(cmp, event) {
       var selectedMembers = event.getParam('arguments').members;
       cmp.set('v.selectedMembers', selectedMembers);
      
       var spinner = cmp.find('mySpinner');
       $A.util.addClass(spinner, 'slds-hide');
   },
  
   // Handle change in member list drop down. Restore previously saved
   // custom data for member. Display text input box for selected
   // member.
   handleMemberChanged: function(cmp, event) {
       var selectedMemberIndex = parseInt(cmp.get('v.selectedMemberIndex'));
       var selectedMembers = cmp.get('v.selectedMembers');
      
       if(!isNaN(selectedMemberIndex)) {
           // Set member id (contact or campaignMemberId)
           cmp.set('v.selectedMemberId', selectedMembers[selectedMemberIndex].campaignMemberId || selectedMembers[selectedMemberIndex].objectId);
          
           // Check if we've previously stored custom data for member. if so, restore it
           if (selectedMembers[parseInt(selectedMemberIndex)].customData.customValue != undefined) {
               cmp.set('v.selectedMemberData', selectedMembers[selectedMemberIndex].customData.customValue);
           } else {
               cmp.set('v.selectedMemberData', "");
           }
       } else {
           cmp.set('v.selectedMemberIndex', null);
           cmp.set('v.selectedMemberId', "");
       }
   },
  
   // Handles changes to member custom data. Fired every change
   handleInputChanged: function(cmp, event) {
       var dataProvidedEvent = $A.get('e.mcdm_15:JourneyApprovalsDataProvided');
      
       var selectedMembers = cmp.get('v.selectedMembers');
       var selectedMemberId = cmp.get('v.selectedMemberId');
       var selectedMemberIndex = parseInt(cmp.get('v.selectedMemberIndex'));
      
       // Also store local value so we can repopulate field if we change
       // members without reloading the CPI. Fired events store the
       // members custom data outside the CPI context and is only retrieved
       // on component load.
       selectedMembers[selectedMemberIndex].customData.customValue = cmp.get('v.selectedMemberData');
      
       dataProvidedEvent.setParams({
           id: selectedMemberId,
           data: {
               customValue: cmp.get('v.selectedMemberData')
           }
       });
       dataProvidedEvent.fire();
   }
})
```