Skip to Content
Product Information
Author's profile photo Arne Manthey

Suppression Rules: Methods, Tips and Tricks

Methods for Suppression

Campaign Execution Exclusion App

<img />

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

<img />

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

<img />

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)

<img />

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.

Getting Started

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:

  1. Specify the use case to derive the structure of the CBO
  2. 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.
  3. 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 ).

 

Suppress Contacts

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.

 

Allow …

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_monthperiod_current_weekperiod_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

Here are the most common use cases that we have identified in numerous customer interactions:
  1. Suppress email addresses and domains (Exclusion List)
  2. Suppress based on a contact attribute (e.g. flag ‚Do not contact‘)
  3. Suppress based on past interaction types (e.g. hard bounces)
  4. Restrict outbound interactions to a certain number in a time interval
  5. Ensure a certain time interval between outbound interactions
  6. 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‘)

  • Dedicated app for the use case
  • Easy to maintain
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’

DATA(contacts) = read->contacts(suppression_rules_result).

IF campaign-marketingarea EQ 'GERMANY'.

    LOOP AT contacts ASSIGNING FIELD-SYMBOL(<contact>)
      WHERE country NE 'DE'.

      suppress->contact(
        EXPORTING
          contact_key = <contact>-InteractionContact
        CHANGING
          results     = suppression_rules_result ).

    ENDLOOP.

ENDIF.

 

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,
Preferred Solution
  • For hard bounces nothing needs to be done since the system removes any email adress which resulted in a hard bounce (see Handling Bounces).
  • For emails which have been classified as spam an automatic opt-out can be done if the ESP supports it (see Enabling Complaints for Emails)
  • For all other cases: Suppression BAdI
Alternative(s) None
Example: Do not send emails to contacts with 3 or more soft bounces

suppress->with_interactions(
      EXPORTING
        interaction_type = 'EMAIL_BOUNCE_SOFT'
        count            = 3
      CHANGING
        results          = suppression_rules_result ).

 

 

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

  • Any communication medium possible
  • Flexible time intervals
  • Global rule
Alternative(s) Communication Category Limits (Was not possible with the Suppression Rules app)
Example: Suppress contacts with 3 or more emails every 7 days

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

 

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

  • Any communication medium possible
  • Dependencies between different communication media possible
  • Flexible time intervals
  • Global rule
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

IF action_id = 'SEND_EMAIL'.

    suppress->with_recent_interactions(
      EXPORTING
        interaction_type = 'TELEPHONE_OUTBOUND'
        period           = calculate->period_days(10)
        count            = 1
      CHANGING
        results          = suppression_rules_result).

    suppress->with_recent_interactions(
      EXPORTING
        interaction_type = 'EMAIL_OUTBOUND'
        period           = calculate->period_hours(24)
        count            = 1
      CHANGING
        results          = suppression_rules_result ).

ENDIF.​

 

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

  • Additional conditions based on contact and campaign attributes
  • Any communication medium possible
  • Dependencies between different communication media possible
  • Flexible time intervals
  • Global rule
Alternative(s) None
Example: For campaigns with priority ‘Low’ do not send an email during 10 days after a phone call and during 24h after an email.

IF campaign-campaignpriority = '4'.

  IF action_id = 'SEND_EMAIL'.

    suppress->with_recent_interactions(
      EXPORTING
        interaction_type = 'TELEPHONE_OUTBOUND'
        period           = calculate->period_days( 10 )
        count            = 1
      CHANGING
        results          = suppression_rules_result).

    suppress->with_recent_interactions(
      EXPORTING
        interaction_type = 'EMAIL_OUTBOUND'
        period           = calculate->period_hours( 24 )
        count            = 1
      CHANGING
        results          = suppression_rules_result ).

  ENDIF.

ENDIF.

 

Conclusion

After reviewing all of the sections above you should be able to make an informed decision on the suppression method you can use.

Assigned Tags

      8 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ajit Kumar Panda
      Ajit Kumar Panda

      HI Arne,

      Neatly explained with use cases etc. Great Job!

      Congrats.

      Best, Ajit

      Author's profile photo Saurabh Kabra
      Saurabh Kabra

      Very nice and informative blog!

      Author's profile photo Keshav Harake
      Keshav Harake

      Very nice blog!

      Author's profile photo Guilherme Paulino
      Guilherme Paulino

      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.

      Example:

      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?

      BR,

      Guilherme.

      Author's profile photo Arne Manthey
      Arne Manthey
      Blog Post Author

      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?

      Author's profile photo Guilherme Paulino
      Guilherme Paulino

      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,

      Guilherme.

      Author's profile photo Arne Manthey
      Arne Manthey
      Blog Post Author

      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)

      Author's profile photo Glenn Van Eijk
      Glenn Van Eijk

      Many thanks for this Arne Manthey,!