CRM and CX Blogs by SAP
Stay up-to-date on the latest developments and product news about intelligent customer experience and CRM technologies through blog posts from SAP experts.
cancel
Showing results for 
Search instead for 
Did you mean: 
Arne_Manthey
Advisor
Advisor



Introduction


With the suppression custom logic you can define rules to avoid sending too many emails to your customers and prospects (See also this blog post). Until release 2102 you could only evaluate attributes and conditions on the level of campaign, contact and interactions. Sometimes you may want to base your suppression decision also on the type of email you are really sending. In case of only one email in a campaign this could already be done by using a campaign category. However, if there are multiple emails in a campaign and some of those should be treated as 'operational' emails there was no way to distinguish those different emails with respect to the suppression logic.

With release 2105 we have enhanced the capabilities of the suppression custom logic to also get details on the specific email.

Example Use Case


Julia is a marketeer for the coffee company Gallo d'Oro and she prepared 2 campaigns. The spring offer campaign is scheduled for April 1 and contains a follow-up email with a special promotion. Additionally a second campaign on April 9 is planned with an invitation for our next barista event.


When Julia tests the setup of the first campaign the initial email is sent out just fine:


But after she clicked on the CTA button in the initial email she did not get the follow-up email as expected. When looking at the campaign performance she notices that that email had been suppressed.


Julia gets on the phone with the IT department and learned that there is a central suppression logic which only allows one email every 7 days for any contact. She explains to the IT expert that such follow-up emails should rather be treated as operational emails and therefore not be suppressed.

The IT expert just learned about a new enhancement in the new release and gets to work...

Implementation








Note: Every coding I show here comes without warranty or maintenance. Please use at your own risk and test carefully!

First let's have a look at the existing suppression logic:
DATA(factory) = cl_cuan_sr_badi_api_factory=>get_instance( ).
DATA(read) = factory->create_reader( ).
DATA(suppress) = factory->create_suppressor( ).
DATA(allow) = factory->create_allowance( ).
DATA(calculate) = factory->create_calculator( ).
DATA(calendar) = factory->create_calendar( ).
DATA(log) = factory->create_logger( ).
DATA(campaign) = read->campaign( campaign_id ).
suppression_rules_result = suppression_rules_input.

IF action_id = 'SEND_EMAIL'
suppress->with_recent_interactions(
EXPORTING
interaction_type = 'EMAIL_OUTBOUND'
period = calculate->period_days( 7 )
count = 1
CHANGING
results = suppression_rules_result
).
ENDIF.

Always allow Operational Emails


The new enhancement allows to also get email data of the email that is about to be sent by the current campaign action. For example, this allows to get the communication category of that email. Gallo d'Oro IT decides to use the communication category '_OP' as indicator for operational emails which should be ignored.

To accomplish this, a section in the code is introduced which allows such emails regardless of any suppression logic which had been executed before.
" ---------------------------------------------------------------------------------
" Allow all emails with communication category '_OP' (Check attributes of outgoing email)
" ---------------------------------------------------------------------------------
IF action_id EQ if_cuan_mkt_orch_constants=>sc_action_id-send_email
AND line_exists( action_parameters[ name = if_cuan_mkt_orch_constants=>sc_action_parameter_id-email_template_id ] ).
" read email ID
DATA(email_template_id) = action_parameters[ name = if_cuan_mkt_orch_constants=>sc_action_parameter_id-email_template_id ]-value.
" select email using CDS view
SELECT SINGLE campaigncontentname, communicationcategoryname FROM i_mkt_campaigncontent
WHERE campaigncontent EQ @email_template_id INTO @DATA(email).
" check that email communication category equals special ID
IF email-communicationcategoryname EQ '_OP'.
allow->all( CHANGING results = suppression_rules_result ).
ENDIF.

After activating the new version of the custom suppression code IT asks Julia to test the process. She sets up a new follow-up email with the operational communication category '_OP':


After starting a new test campaign Julia is happy with the result: The follow-up email was sent successfully:



Ignore Interactions from Operational Emails in your Suppression Logic


Remembering her second planned campaign for the barista workshop invitation Julia checks in with IT again and ask whether the operational emails would also be ignored for any following campaign. The IT expert realizes that the helper method suppress->with_recent_interactions would still consider those operational emails and therefore they replaced the method with a new code:
" ---------------------------------------------------------------------------------
" Check for marketing e-mails in recent days but ignore operational e-mails
" ---------------------------------------------------------------------------------
DATA contact_key_ranges TYPE RANGE OF cuan_bopf_key.
contact_key_ranges = VALUE #( FOR <result> IN suppression_rules_result
( sign = 'I'
option = 'EQ'
low = <result>-contact_key ) ).
DATA(week_period) = calculate->period_days( 7 ).
DATA suppress_keys TYPE TABLE OF cuan_cds_interaction.

SELECT DISTINCT interactioncontact FROM i_mkt_interaction AS interaction
INNER JOIN i_mkt_campaigncontent AS email ON email~campaigncontent = interaction~marketingorchestrationid
AND ( email~communicationcategoryname IS NULL
OR email~communicationcategoryname NOT LIKE '%_OP%' )
WHERE interactiontype EQ @if_cuan_ce_c=>co_iatype_email_outbound
AND interactioncontact IN @contact_key_ranges
AND tstmp_seconds_between( tstmp1 = CAST( interactiontimestamputc AS DEC( 15, 0 ) ), tstmp2 = tstmp_current_utctimestamp( ) ) LE @week_period
GROUP BY interactioncontact
HAVING COUNT(*) GE 1
INTO TABLE @suppress_keys.

suppress->contacts(
EXPORTING
contact_keys = suppress_keys
CHANGING
results = suppression_rules_result
).

Testing the second campaign a few days after the first one Julia is happy that the email is sent:


Looking at the timeline of the test contact Julia can see that the proposed solution by IT does indeed work. The first campaign sent the initial email on April 1 and after a few days the email was opened and the link clicked. The operational follow-up email was successfully sent because of the allow statement for operational emails described in the last section.

But also the email of the second campaign had been sent although it would have been suppressed before that code change. This is because the time difference between the email on April 4 and April 9 would have been less than 7 days. With this code the last relevant email is the one from April 1 and here the time difference is more than 7 days and thus the email of the barista invitation had been sent.



Final Code


For your convenience I have the complete coding - but of course without any warranty.
DATA(factory) = cl_cuan_sr_badi_api_factory=>get_instance( ).
DATA(read) = factory->create_reader( ).
DATA(suppress) = factory->create_suppressor( ).
DATA(allow) = factory->create_allowance( ).
DATA(calculate) = factory->create_calculator( ).
DATA(calendar) = factory->create_calendar( ).
DATA(log) = factory->create_logger( ).
DATA(campaign) = read->campaign( campaign_id ).
suppression_rules_result = suppression_rules_input.

*****************************************************************************************
* Suppress/Allow involving Email Communication Category
*****************************************************************************************
IF action_id = 'SEND_EMAIL'

" ---------------------------------------------------------------------------------
" Check for marketing e-mails in recent days but ignore operational e-mails
" ---------------------------------------------------------------------------------
DATA contact_key_ranges TYPE RANGE OF cuan_bopf_key.
contact_key_ranges = VALUE #( FOR <result> IN suppression_rules_result
( sign = 'I'
option = 'EQ'
low = <result>-contact_key ) ).

DATA(week_period) = calculate->period_days( 7 ).

DATA suppress_keys TYPE TABLE OF cuan_cds_interaction.

SELECT DISTINCT interactioncontact FROM i_mkt_interaction AS interaction
INNER JOIN i_mkt_campaigncontent AS email ON email~campaigncontent = interaction~marketingorchestrationid
AND ( email~communicationcategoryname IS NULL
OR email~communicationcategoryname NOT LIKE '%_OP%' )
WHERE interactiontype EQ @if_cuan_ce_c=>co_iatype_email_outbound
AND interactioncontact IN @contact_key_ranges
AND tstmp_seconds_between( tstmp1 = CAST( interactiontimestamputc AS DEC( 15, 0 ) ), tstmp2 = tstmp_current_utctimestamp( ) ) LE @week_period
GROUP BY interactioncontact
HAVING COUNT(*) GE 1
INTO TABLE @suppress_keys.

suppress->contacts(
EXPORTING
contact_keys = suppress_keys
CHANGING
results = suppression_rules_result
).

" ---------------------------------------------------------------------------------
" Allow all emails with communication category '_OP' (Check attributes of outgoing email)
" ---------------------------------------------------------------------------------
IF action_id EQ if_cuan_mkt_orch_constants=>sc_action_id-send_email
AND line_exists( action_parameters[ name = if_cuan_mkt_orch_constants=>sc_action_parameter_id-email_template_id ] ).
" read email ID
DATA(email_template_id) = action_parameters[ name = if_cuan_mkt_orch_constants=>sc_action_parameter_id-email_template_id ]-value.
" select email using CDS view
SELECT SINGLE campaigncontentname, communicationcategoryname FROM i_mkt_campaigncontent
WHERE campaigncontent EQ @email_template_id INTO @DATA(email).
" check that email communication category equals special ID
IF email-communicationcategoryname EQ '_OP'.
allow->all( CHANGING results = suppression_rules_result ).
ENDIF.

ENDIF.

ENDIF.

Conclusion


After reading this post you should be able to set up your suppression logic considering the exclusion of operational emails.
2 Comments