Suppression Rules: Methods, Tips and Tricks
Methods for Suppression
Campaign Execution Exclusion App
One of the usages for the old Suppression Rules app have been to suppress contacts with specific email addresses or from certain domains. Luckily we now have this dedicated app to do exactly this. Additionally you can import CSV lists directly into the app and also provide a reason text for every entry.
See also documentation on Campaign Execution Exclusion.
Communication Category Limits App
Of course this app is around for a long time already but it still has a lot of value for a specific use case. However, it is not a globally active suppression method since you need to assign the communication category which has limits defined to every email or text message which need to be checked against those limits (Of course you can use that communication category already in an email template). Then the check also only looks at all emails with the same communication category. But this could also be exactly what you intend to do. The app is also restricted to email and text messages – no other communication medium is supported.
See also documentation on Communication Categories and Limits.
Segmentation / Filter with Live Target Groups
Just for completeness I also mention the segmentation as a means to suppress certain contacts. If you can build your dynamic target group already in such a way that it only holds this contacts that you want to address then you might avoid certain suppression requirements already.
Additionally you can use the segmentation to create Live target Groups which you can use as a filter in Campaign execution (look at the field ‘Filter Condition’ in the ‘Send Email’ action). This allows you to have an additional suppression method on execution level. Again this is not a global suppression rule because you have to make sure that you really use that filter condition. One way to achieve this is the usage of campaign templates with such a filter in place.
See also documentation on Filtering.
Suppression BAdI (New features and examples in 1908)
The BAdI for suppression exists for some time now but it has been improved in 1908 with some helper classes for cleaner code and examples for common use cases. The BAdI is checked right before the campaign execution like permissions, limits and the now deprecated Suppression Rules.
Of course you need to know a little ABAP to fully use the potential of this BAdI. However with the examples you can already start by just activating some of those example code snippets. In the use case section below I will explain some of the example code.
You find the app to define the BAdI logic in group ‘Extensibility and Adaptability for Marketing‘ in the app ‘Marketing Extensibility‘. In the app you need to select ‘Create Custom Fields‘ (A little counter-intuitive because it says nothing about logic). There you need to select the tab ‘Custom Logic‘.
Then you need to create a new entry for the business context ‘Marketing: Permission‘ and the BAdI Description ‘Suppression Rules Check‘. Give it a name and create. Next you should have a look at the BAdI Documentation (Tab and link in the UI) and the examples (By pressing the button ‘Example‘ on the right). Usually the example is already filled in the code editor of the draft. If not you can just copy and paste it from the example section. I would then recommend to pick one of the examples that you want to evaluate and remove the rest. However, you must not remove the first declarations above the first example! (DATA(factory) =…)
If you try to code for yourself based on the hints I give you further down, remember that you can usually get code completion information when hitting Control-Space.
You can now publish the BAdI and run a campaign to test it. Be aware that this is a global check and that any other users will also be affected by your Suppression BAdI! Once you get more familiar with the coding you could also include some restrictions during testing so that the code only affects certain campaigns, for example with a certain pattern (e.g. ‘_SR_‘) in the name:
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( ). suppression_rules_result = suppression_rules_input. DATA(campaign) = read->campaign( campaign_id ). IF campaign-CampaignName CP '*_SR_*'. # Your suppression code comes here... ENDIF.
Separation of Code Logic and Business Parameters
You might argue that you have certain parameters in your suppression logic which need to be adapted by business users from time to time and that it is not acceptable to allow your business users to adapt those parameters in the BAdI coding itself. There are two suggestions on how to approach this:
Split the Coding in two Sections and give Key Users Access
The easiest way, although not fool-proofed, is to split the code into a parameter section at the beginning and a logic section afterwards. You can use a lot of comments in the parameter section to explain the parameters. Then you give access to the app to change the BAdI to a limited number of key users and explain to them that they are allowed to change the first section but that they must not do any changes below. Here is an example:
*** Parameters ******************************************************** DATA(email_hours) = 12. "Delay between emails DATA(email_count) = 2. "Number of emails allowed in the delay period *** Code – Do not change ********************************************** IF action_id = 'SEND_EMAIL'. suppress->with_recent_interactions( EXPORTING interaction_type = 'EMAIL_OUTBOUND' period = calculate->period_hours( email_hours ) count = email_count CHANGING results = suppression_rules_result ). ENDIF.
Define a Custom Business Object for Suppression Parameters
This method is more advanced and I have described the process in this blog post: ‘Suppression: Separating Business Parameters from BAdI Coding using a Custom Business Object‘. Here is the summary of process steps:
- Specify the use case to derive the structure of the CBO
- Create a CBO which includes the desired parameters as fields. It is easy to generate a UI for this where you can then add new entries as a line with multiple columns. Then add the generated UI to a business catalog to give your business users the possibility to maintain those parameters.
- Develop a generic code inside your suppression BAdI which reads line by line of your CBO and executes the suppression logic accordingly.
Useful Helper Methods
In the following sections I explain some of the most useful helper methods which have been introduced in 1908. However there might be more when you read this at a later time – so this is only a limited choice.
Please note that for all examples shown below (and generally for the entire coding) it is necessary that you have the following declaration at the top of the coding (as its is in the example coding):
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( ). suppression_rules_result = suppression_rules_input.
Suppress with Recent Interactions
Suppress contacts which had a certain number of a specific interaction in a given time period (in seconds). This should be one of the most commonly used methods.
Example: Suppress all contacts that had 3 or more emails in the last 7 days (25200 seconds)
suppress->with_recent_interactions( EXPORTING interaction_type = 'EMAIL_OUTBOUND' period = 25200 count = 3 CHANGING results = suppression_rules_result ).
Suppress with Interactions
This method suppresses contacts that had a specific number of interactions of a certain type regardless of any period.
Example: Suppress all contacts with 3 soft bounces or more.
suppress->with_interactions( EXPORTING interaction_type = 'EMAIL_BOUNCE_SOFT' count = 3 CHANGING results = suppression_rules_result ).
This method allows the specific suppression of a list of contacts that has been prepared by any coding before.
Example: See example in section ‘Read Contacts and their Attributes‘ below.
This works similarly as the suppress class (it has the same methods, see above) but it reverses the effect. This might be useful as a code block at the end to include certain test contacts again into the execution regardless of any previous suppression rules.
Example: Re-introduce all contacts with email addresses of the domain ‘tester.domain‘
allow->with_email_address ( EXPORTING email_pattern = '*@tester.domain' CHANGING results = suppression_rules_result ).
Read Campaign Attributes
Retrieve campaign attributes from the campaign ID.
Example: Run suppression code only if the campaign name matches the pattern ‘_SR_’
DATA(campaign) = read->campaign( campaign_id ). IF campaign-CampaignName CP '*_SR_*'. #... ENDIF.
Read Contacts and their Attributes
Retrieve contacts together with all contact attributes.
Example: Get all contacts which live in ‘Banned Street’ and suppress them.
DATA(contacts) = read->contacts( suppression_rules_result ). DELETE contacts WHERE StreetName <> 'Banned Street'. suppress->contacts( EXPORTING contacts = contacts CHANGING results = suppression_rules_result ).
Calculate different Periods into Seconds
Since all suppression methods which involve a period use seconds as a unit this is a useful method for better readability. The following methods are available: period_days, period_hours, period_minutes.
Example: Suppress all contacts with an email in the last 7 days.
suppress->with_recent_interactions( EXPORTING interaction_type = 'EMAIL_OUTBOUND' period = calculate->period_days( 7 ) count = 1 CHANGING results = suppression_rules_result ).
There are some other related methods that do not take any parameter but return the number of seconds since the start of an actual period: period_current_month, period_current_week, period_today.
Example: Suppress all contacts that have already received an email in the current week.
suppress->with_recent_interactions( EXPORTING interaction_type = 'EMAIL_OUTBOUND' period = calculate->period_current_week( ) count = 1 CHANGING results = suppression_rules_result ).
Use Cases / Examples
- Suppress email addresses and domains (Exclusion List)
- Suppress based on a contact attribute (e.g. flag ‚Do not contact‘)
- Suppress based on past interaction types (e.g. hard bounces)
- Restrict outbound interactions to a certain number in a time interval
- Ensure a certain time interval between outbound interactions
- Ensure a certain time interval between outbound interactions depending on the Campaign Priority
In the following sections I discuss each of these use cases in more detail together with recommendations on the preferred solution and alternatives. Some of the use cases are also available in the BAdI examples.
Suppress email addresses and domains (Exclusion List)
|Description||Suppress all contacts with a specific email address or an address from a specific domain (Exclusion List scenario).|
|Preferred Solution||Campaign Execution Exclusion List (See above in section ‘Alternative Methods for Suppression‘)
|Alternative(s)||Suppression BAdI, Live Target Groups|
Suppress based on a contact attribute (e.g. flag ‚Do not contact‘)
|Description||Exclude contacts based on specific contact attributes.|
|Preferred Solution||Suppression BAdI|
|Alternative(s)||Live Target Groups|
|Example: Suppress all contacts not located in Germany for a campaign with marketing area ‘Germany’
Suppress based on past interactions
|Description||Do not send emails for a contact if a specific interaction had been created in the past. (e.g. Hard bounces,|
|Example: Do not send emails to contacts with 3 or more soft bounces
Restrict outbound interactions to a certain number in a time interval
|Description||Allow a certain number of outbound communication interactions per time frame.|
|Preferred Solution||Suppression BAdI
|Alternative(s)||Communication Category Limits (Was not possible with the Suppression Rules app)|
|Example: Suppress contacts with 3 or more emails every 7 days
Ensure a certain time interval between outbound interactions
|Description||Ensure a certain time interval between outbound communication interactions. Also consider different combinations of communication media (e.g. different intervals between 2 emails and between an email and a phone call).|
|Preferred Solution||Suppression BAdI
|Alternative(s)||Communication Category Limits (Limit set to 1)|
|Example: Do not send an email during 10 days after a phone call and during 4h after an email
Ensure a certain time interval between outbound interactions depending on the Campaign Priority
|Description||Enhanced variant of use case 3 with additional condition based on campaign data like the campaign priority|
|Preferred Solution||Suppression BAdI
|Example: For campaigns with priority ‘Low’ do not send an email during 10 days after a phone call and during 24h after an email.
After reviewing all of the sections above you should be able to make an informed decision on the suppression method you can use.
Neatly explained with use cases etc. Great Job!
Very nice and informative blog!
Very nice blog!
Dear Arne Manthey,
Thanks for the blog!
I have a use case to limit the number of e-mails or SMS sent to customer PER campaign.
Campaign A -> I want to limit 10,000 e-mails/month and 50,000 text messages/month
Campaign B -> I want to limit 3,000 e-mails/month and 10,000 text messagens/month
Meaning that, once the limits are reached, the campaign has to stop its execution
What would be the best approach for this? Is this possible at all?
May I ask, why you don't restrict this by a reduced target group? There you can include a number limit.
Or are you talking about trigger-based campaigns?
Hello Arne Manthey, .
Yes, trigger-based campaigns! As a matter of fact, all kinds of campaigns.
My customer wants to be able to limit number of e-mails and text messages sent per month and per campaign. Imagine we have a budget for sending 100,000 e-mails/month and 300,000 text messages/month. And we have over 20 different campaigns (trigger-based and non-trigger-based) going on simultaneously.
Do you know what's the best way to achieve this?
Thanks a lot,
Well for trigger-based campaigns this would be a feature request for the campaign. Please consider to create an influence request for this (https://influence.sap.com/sap/ino/#/campaign/38)
Many thanks for this Arne Manthey,!