Introduction
As enterprise e-commerce platform, SAP Commerce Cloud provides solid support for marketing, such as coupon management, promotion rule, personalization etc. Unfortunately, although SAP commerce has implemented a demo in B2C/B2B accelerator to distribute coupon by using free coupon action in promotion rule, it’s far from enough to meet the complex scenarios in real projects, such as:
-
- Coupon can be distributed across multiple channels
-
- Personalization can be supported in coupon distribution related content
-
- Statistics is required to help customers understand how much these related marketing targets are reached
On the other hand, Emarsys is the omni-channel marketing platform, which just cover all these requirements:
-
- Coupon can be distributed across multi channels, such as email, mobile, web, etc.
-
- All kinds of personalization features (such as token, conditional text, ESL, etc.) can be used in coupon distribution related email or message.
-
- Different dashboards are provided to give an overall insight about coupon distribution program from different aspects
Apparently, we can use Emarsys to distribute coupon for SAP Commerce Cloud. In this post, I will implement a simplified prototype to demo it
Design
The basic thinking is simple:
-
- Whenever a coupon is created in SAP Commerce by using any way (Backoffice, ImpEx, coding), an outer event is created in Emarsys.
-
- Create an interactive coupon distribution program in Emarsys, which will use the outer event as the trigger event
-
- When coupon codes for this coupon are generated in SAP Commerce, they need to be uploaded in Emarsys
-
- Any related components in SAP Commerce Cloud can trigger this outer event to activate coupon distribution
The following diagram is the conceptual architecture of this prototype,
Figure 1: The Conceptual Architecture for This Prototype
Two major components are introduced in SAP Commerce Cloud:
-
- CouponEventListener: responsible for create outer event in Emarsys whenever a new coupon is created in SAP Commerce Cloud
-
- EmarsysCouponService: responsible for activating the coupon distribution program in Emarsys
In Emarsys, we need to create an interaction program with outer event as the trigger event, this interaction program can distribute coupon across multiple channels
Prototype Implementation
Assumptions
We have the following assumptions for simplicity:
-
- Only implement email-based coupon distribution, if you want to support other channels, please refer to Emarsys online help documents
-
- User is identified using email
-
- Only happy path is covered for interaction between Sap Commerce and Emarsys, in other words, we don’t process exceptional conditions in code
SAP Commerce Cloud Side
Define New Type EmarsysCoupon
First, create an new extension, define a new type EmarsysCoupon in this new extension:
<itemtype code="EMarsysCoupon" jaloclass="de.hybris.platform.couponservices.jalo.EmarsysCoupon"
extends="MultiCodeCoupon" generate="true" autocreate="true">
<attributes>
<attribute qualifier="outerEventId" type="java.lang.String">
<persistence type="property"/>
<description>used to indicate outer event generated by Emarsys.</description>
</attribute>
</attributes>
</itemtype>
EmarsysCoupon is a subtype of MultiCodeCoupon with a new attribute ‘outerEventId’, this attribute is used to uniquely identify related outer event created by Emarsys.
Define EmarsysConnector Interface and Implementation
public interface EmarsysConnector
{
/**
* Send data to Emarsys.
*
* @param method
* the http method, such as get, post, etc.
* @param urlText
* url path
* @param data
* the data in JSON format, which will be send to Emarsys as request body
*/
String send(String method, String urlText, String data);
}
public class DefaultEmarsysConnector implements EmarsysConnector
{
...
}
EmarsysConnector is used to communicate with Emarsys based on Emarsys API, for simplicity, i don’t paste the details for DefaultEmarsysConnector, you can refer to https://emarsys-sap.stoplight.io/docs/emarsys-api/10827827b819d-3-configure-authentication
Define EmarsysCouponService Interface and Implementation
EmarsysCouponService interface is a sub interface of CouponService, which introduces two method:
public interface EmarsysCouponService extends CouponService
{
/**
* Create an outer event in Emarsys, by which coupon distribution can be triggered.
*
* @param couponDistribEventName
* the outer event to be created in Emarsys in order to distribute coupon
* @return the coupon distribution event id returned by Emarsys
*/
String createCouponDistribEvent(String couponDistribEventName);
/**
* Delegate Emarsys to distribute coupon.
*
* @param couponDistribEventId
* the outer event id in Emarsys
* @param userEmail
* the email used to identify current user
* @return the outer event id returned by Emarsys
*/
void distributeCoupon(String couponDistribEventId, String userEmail);
}
The default implementation is DefaultEmarsysCouponService, which is a sub class of Default CouponService.
public class DefaultEmarsysCouponService extends DefaultCouponService implements EmarsysCouponService
{
private EmarsysConnector emarsysConnector;
...
@Override
public String createCouponDistribEvent(final String couponDistribEventName)
{
final String response = emarsysConnector.send("POST", "/event", "{"name":"" + couponDistribEventName + ""}");
final Gson gson = new Gson();
final EventResponse eventResponse = gson.fromJson(response, EventResponse.class);
if (eventResponse.getData() != null)
{
return eventResponse.getData().getId();
}
return null;
}
@Override
public void distributeCoupon(final String couponDistribEventId, final String userEmail)
{
final String response = emarsysConnector.send("POST", "/event/" + couponDistribEventId + "/trigger",
"{"key_id":"3", "external_id":"" + userEmail + "", "data":null, "contacts":null}");
}
}
Define CouponEventListener
CouponEventListener will invoke Emarsys API to create an outer event whenever an EmarsysCoupon is created in SAP Commerce.
public class CouponEventListener extends AbstractEventListener<AfterItemCreationEvent>
{
private ModelService modelService;
private EmarsysCouponService emarsysCouponService;
...
@Override
protected void onEvent(final AfterItemCreationEvent event)
{
if (event.getTypeCode().equals(EMarsysCouponModel._TYPECODE))
{
if ((event.getSource() != null))
{
final EMarsysCouponModel coupon = (EMarsysCouponModel) modelService.get(event.getSource());
final String couponDistribEventName = coupon.getCouponId() + "CouponDistribEvent";
final String eventId = emarsysCouponService.createCouponDistribEvent(couponDistribEventName);
coupon.setOuterEventId(eventId);
modelService.save(coupon);
}
}
}
}
Please note
-
- There is a contract between EmarsysCoupon ID and outer event name, if the coupon id is ‘tmp’, then outer event name is ‘tmpCouponDistribEvent’.
-
- As CouponEventListener successfully invoke Emarsys API to create an outer event, it will keep the outer event ID in the new created EmarsysCoupon, so other Commerce modules can use this ID to trigger the distribution of EmarsysCoupon codes
Configure Spring
<bean id="couponEventListener" class="de.hybris.emarsysintegrate.listener.CouponEventListener"
parent="abstractEventListener" >
<property name="modelService" ref="modelService" />
<property name="emarsysCouponService" ref="emarsysCouponService" />
</bean>
<bean id="emarsysConnector" class="de.hybris.emarsysintegrate.service.impl.DefaultEmarsysConnector" lazy-init="true">
<constructor-arg name="environment" value="${environment}" />
<constructor-arg name="apiUsername" value="${apiUsername}" />
<constructor-arg name="apiSecretKey" value="${apiSecretKey}" />
</bean>
<alias name="emarsysCouponService" alias="couponService" />
<bean id="emarsysCouponService" class="de.hybris.emarsysintegrate.service.impl.DefaultEmarsysCouponService" >
<property name="emarsysConnector" ref="emarsysConnector" />
</bean>
Create an EmarsysCoupon in Backoffice
Navigate to System -> Marketing ->Coupon Management -> Coupons, create a new EmarsysCoupon
-
- Id: tmp
-
- Name: tmp emarsys coupon
After this step is finished, you can visit Emarsys to make sure an outer event ‘tmpCouponDistribEvent’ has been created, it indicates CouponEventListener has used EmarsysCouponService to create related outer event in Emarsys.
Figure 2: New Created Outer Event in Emarsys
Furthermore, Refresh new created EmarsysCoupon in Backoffice, you will find outer event ID has been filled.
Figure 3: Outer Event ID Set in Backoffice
Generate Coupon Codes
Open new created EmarsysCoupon ‘tmp’
Generate 100 coupon codes for EmarsysCoupon ‘tmp’, download this generated csv file into local file system.
Emarsys Side
Create Voucher Pool
Navigate to Add-ons -> Omnichannel Voucher, create a voucher pool ‘demo_voucher_pool’, upload coupons csv file generated by previous step.
Figure 4: New Created Voucher Pool in Emarsys
Create Voucher-Based Personalization Token
Navigate to Content->Personalization, create a voucher-based token ‘demo_voucher_token’, choose ‘demo_voucher_pool’ as the value of Field.
Create Coupon Distribution Email Campaign
Navigate to Channels -> Tiggered Email, create a block based coupon distribution email ‘Demo Coupon Distribution Email’, email content will contain token ‘demo_voucher_token’ created by previous step. Finally, don’t forget to activate this email campaign
Figure 5: The Content for The Demo Email Campaign
Create Interaction Program
Navigate to Automation -> Automation Programs, create an interactions program ‘Demo Coupon Distribution’.
Figure 6: The Demo Interaction Program for Distributing Email
Configure like this:
-
- Choose tmpCouponDistribEvent as the outer event
-
- Choose ‘Demo Coupon Distribution Email’ in the Send email node
-
- Enable ‘Only once ever’ in the Participation check node to make sure each customer will just receive one email
Finally, activate this program.
Verify
Write a test code to invoke EmarsysCouponService.distributeCoupon(String couponDistribEventId, String userEmail) with the following parameters
-
- couponDistribEventId: 12460, this value is gotten from the new created Emarsys coupon, which is returned from Emarsys (don’t foreget we extend Multi code coupon with new attribute ‘outerEventId’
-
- userEmail: use your personal email
After running the test code, wait several minutes, you will get a new email containing assigned coupon code similar like this:
Figure 7: Received Coupon in Email
Improvement
Since Emarsys doesn’t provide API to programmatically create vouch pool, upload related coupon code, and create related personalization token, we’ll have to manually do it, but we can use workflow in SAP Commerce to make sure related users will be assigned task to do these work in Emarsys whenever a new EmarsysCoupon is created,
Another possible enhancement is to support batch coupon distribution, so a list of users will be assigned coupon code with just one invocation.
Conclusion
This post just shed some light on how to use Emarsys to support multi-channel coupon distribution for SAP Commerce Cloud, in future, i will share more example to utilize Emarsys features to extend SAP Commerce Cloud functionalities.