Skip to main content

Loyalty & Retention

tip

The Loyalty Icon can be used by the user to access his/her Loyalty Profile Card. The following options can be used to handle the Loyalty Icon and User Profile in your game.

Showing/hiding the wappier Icon

You can add the Loyalty Icon programmatically or with .xml in your layout. When the user taps the icon, his Loyalty Profile card is shown.

Find the method of every framework in the tabs below:

//Programmatically
WappierButton mCustomButton= new WappierButton();
<!--Xml-->
<wappier.sdk.wappier.com.loyalty.ui.WappierButton
android:id="@+id/wappier_button"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"/>

To present the wappier Loyalty Icon at any time, use the following line:

mCustomButton.showLoyIcon("REFERRER");
note

REFERRER is a free text parameter describing the screen that the Icon has shown.

To hide the wappier Loyalty Icon at any time, use the following line:

mCustomButton.hideLoyIcon();

To set the wappier Loyalty Icon position at any given in-game screen, use one of the following lines:

mCustomButtom.setPosition(200,200) // setPosition(xPoint,yPoint)
mCustomButton.setPosition(Position.Top,Position.Left)
mCustomButton.setPosition(10,Position.Top,Position.Left)

One of the following constants can also be used in order to set the wappier Loyalty Icon position:

ConstantPosition
Position.DEFAULTIcon displays default position
Position.LEFTIcon displays at left of the screen
Position.RIGHTIcon displays at right of the screen
Position.TOPIcon displays at top of the screen
Position.BOTTOMIcon displays at bottom of the screen

Showing/hiding the custom Icon

In case you implement your custom Loyalty button you make sure that it will be visible only to the users that have active loyalty status. You can register a listener to receive updates with the current end-user’s loyalty status by adding the following lines:

WappierSDKWrapper::getInstance()->setLoyaltyListener([](bool enabled){
//do something with the status
//e.g. control whether the Wappier loyalty icon is visible
});

The custom loyalty button can be hidden by adding the following attributes:

controlGroupFlag = true or status = false or flag = false.

Tracking Custom Icon Impression

When a custom Loyalty Icon is displayed add the following code:

Wappier.getInstance().trackLoyIconDisplay("REFERRER");
Info REFERRER is a free text parameter describing the screen the user is on when the Loyalty Profile card was presented.

Showing Loyalty User Profile

To display the Loyalty User Profile/ Loyalty Card, you should add the following line:

Wappier.getInstance().showLoyaltyView("REFERRER");
Info REFERRER is a free text parameter describing the screen that the user is on when the Loyalty Profile card was presented.

Loyalty Profile Orientation

You can control the orientation of the Loyalty Profile depending on the app needs:

Wappier.getInstance()
.startSession(this, YOUR_APPLICATION_KEY, new Locale("en"), userName, kvpMap);
.setLOYOrientation(PREFERRED_ORIENTATION);

The PREFERRED_ORIENTATION can take one of the following options:

ConstantResult
Orientation.PORTRAITLock orientation to portrait
Orientation.LANDSCAPELock orientation to landscape
Orientation.OPENLoyalty card will rotate depending on device orientation
ConstantResult
Orientation.PORTRAITLock orientation to portrait
Orientation.LANDSCAPELock orientation to landscape
Orientation.OPENLoyalty card will rotate depending on device orientation

Loyalty Sfx Sounds

By default the Sfx sounds in the Loyalty User Profile are disabled. In order to enable the Sfx sounds in the Loyalty User Profile, please add the following code:

Wappier.Instance.setLoySounds(true);

You can select specific sounds for various actions in the Loyalty User Profile:

  • When the end-user opens-closes the Loyalty User Profile
  • When a popup is displayed
  • When a button is clicked
  • When the "Claim" button is clicked
  • When a reward redemption is successful
  • When an error occurred

Loyalty App Fonts Customization

The wappier Optimization SDK can display the texts with the same fonts as the app uses in the Loyalty User Profile. First of all you should provide us the font files in order to upload them on the wappier Back-End and you have to store them in specific folders in Android and iOS version of your app:

  • Android: All font files should be stored in a folder with name "Assets"
  • iOS: All font files should be added in the app’s info.plist. Furthermore please make sure that the fonts are added to a folder in the same level with the app’s info.plist in the Xcode hierarchy. Also they must be included in your app by checking it in the "Target Membership" list For instance, please check the screenshots below:

Getting Control/Target Group Status

To get Control/Target Group Status, add the following code:

bool controlFlag = Wappier.Instance.isUserControlGroup();

Getting User Status

You can get the end-user status for each wappier service. In the response, you can find if the end-user is included in the control or target group, for the wappier service that you are asking for. To get User Status, add the following code:

// tags is a string[] and can take values "all" | "loyalty" | "pricing" | "campaign"
string[] tags = new string[] {"loyalty","pricing","campaign"}

Wappier.Instance.GetUserStatus(tags, UserStatusCallback);

void UserStatusCallback(string response)
{
//Handle response json
}

OR

Wappier.Instance.GetUserStatus(tags, response => {
//Handle response json
});

which takes a list of tags as an argument and returns a JSON response as a String.

Example response:

"{
\"loyalty\" : {
\"population\" : 0.67220987,
\"control\" : false,
\"enabled\" : false
},
\"campaign\" : {
\"population\" : 0.36149076,
\"control\" : false,
\"enabled\" : false
},
\"pricing\" : {
\"population\" : 0.34617529,
\"control\" : false,
\"enabled\" : true,
\"billingCountry\": \"GR\",
\"isInScope\": true
}
}"

In the response, you may find if the user is included in the control or target group per each service. If the end-user is included in the control group for the requested service if the {{service}}.control:true and {{service}}.enabled:false If the end-user is included in the target group for the requested service if the {{service}}.control:false and {{service}}.enabled:true

Loyalty Status Update

You can register a listener to receive updates about the current loyalty status:

Wappier.Instance.setLoyaltyStatusDelegate(flag =>
{
...
});

Loyalty Notifications Count Update

The wappier Optimization SDK provides you a callback that informs you about the current number of notifications. For instance, if there are notifications you can show their count on your custom button by adding the following lines:

Wappier.Instance.setLoyaltyNotificationsCountDelegate(count =>
//do something with the count of loyalty notifications
//e.g. show some icon over the loyalty icon
});

Loyalty Unlocked Reward Update

You can register a listener to receive updates for unlocked rewards:

Wappier.Instance.setRewardUnlockDelegate((eventName, redeemableItems) =>
{
...
});

Loyalty Balance Increase Update

You can register a listener to receive updates for balance increases:

Wappier.Instance.setBalanceIncreaseDelegate((eventName, redeemableItems) =>
{
...
});

Loyalty Inventory Update

You may get the items that the end-user has redeemed. The below callback must be called occasionally based on when you should be informed for the end-user’s inventory. Ιndicatively, it may be called when a new session starts and ends in your application. In the items, you can find the title, description and images of rewarded items along with the current state of the rewards.

int[] invTypes = { 0 };
int[] statuses = { 0, 1 };

Wappier.Instance.getInventoryRequest(invTypes, statuses, (inventoryItems) =>
{
...
});

Arguments invTypes and itemStatuses are arrays of integers that can contain the following values:

Note 1: You can pass in each parameter a combination of more than one of the above values. Note 2: If you pass wrong params in the callback, you will not be informed and the response listener will never be called. Note 3: Response example:

{
"inventories": [
{
"type": 0, // INVENTORY_TYPE
"balance": {
"WP_POINTS": { // Loyalty Points
"total": 20000, // Total Loyalty Points
"current": 12200 // Current Loyalty Points
}
},
"redeemed": [ // Redeemed In-app Rewards

{
"amount": 2, // Reward Amount
"redeemable": {
"sku": "WP_20_COINS", // wappier Redeemable Identifier
"type": "INAPP", // redeemable type - "INAPP" for in-app rewards
"amount": 10, // redeemable amount
"refCode": "com.package.coin" //publisher's in-app reward identifier
}// The redeemed reward is 20 coins because the end-user got 2 WP_20_COINS. The WP_20_COINS redeemable is 10 com.package.coin
},...
],
"unlocked": [ // Unlocked In-app Rewards
{
"amount": 2, // Reward Amount
"redeemable": {
"sku": "WP_1_GEM", // wappier Redeemable Identifier
"type": "INAPP", // redeemable type - "INAPP" for in-app rewards
"amount": 1, // redeemable amount
"refCode": "com.package.gem" // publisher's in-app reward identifier
}// The unlocked reward is 2 gems because the end-user got 2 WP_1_GEM. The WP_1_GEM redeemable is 1 com.package.gem
},...
]
}
],
"total": 1 // number of user inventory
}

Get Loyalty Notifications Count

You can get the current number of notifications on demand by using this method:

int notificationsCount = Wappier.getInstance().getNotificationsCount();

In-App Products Setup & Redemption Flow

In order to reward in-app items through the wappier Optimization SDK, each of these items should be matched with a unique and custom name.

When the user attempts to spend points to redeem an item, the wappier Optimization SDK should be informed whether that redemption is successful in order to subtract the respective points.

You can receive the redemption notifications by adding the following code:

Use one of the following code snippets in your activity:

Wappier.registerRedeemCallback(new RedeemListener() {
@Override
public void redeemCallback(final Redeemable redeemable, final String redemptionId, final long quantity) {
...
}
});

//or

RedeemListener redeemListener = new RedeemListener() {
@Override
public void redeemCallback(final Redeemable redeemable, final String redemptionId, final long quantity) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (redeemable.getRefCode().equals("SKU1") || redeemable.getRefCode().contains("test_sku_")) {
...
}
}
}, 3000);
}
};

@Override
protected void onStart() {
super.onStart();
Wappier.getInstance().registerRedeemCallback(redeemListener);
}

@Override
protected void onStop() {
super.onStop();
Wappier.getInstance().unregisterRedeemCallBack();
}

When the transaction is completed and the user receives the reward you can call the following line to complete the redemption flow:

info

Please don’t forget to call redemptionIsCompleted method as soon as possible!

Wappier.registerRedeemCallback(new RedeemListener() {
@Override
public void redeemCallback(final Redeemable redeemable, final String redemptionId, final long quantity) {
// added delay to emulate a transaction
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (redeemable.getRefCode().equals("SKU1") || redeemable.getRefCode().contains("test_sku_")) {
Wappier.getInstance().redemptionIsCompleted(true, redemptionId);
} else {
Wappier.getInstance().redemptionIsCompleted(false, redemptionId);
}
}
}, 3000);
}
});

Posssible responses

// Failed redemption due to a missing item ID
Error buffer(com.android.okhttp.internal.http.Http1xStream$FixedLengthSource@8a15e97).inputStream() Message :{"error": "Reward is not found, is locked or claimed","code":916} Code :400

// Failed redemption due to a game error
Redeem sending demo.sku.com with Quantity : 5 to server
Redeem Item found. 5000 will committed
Calling mother app callback with SKU : demo.sku.com
Redemption is Completed :false
Redeem – Status: 1000
Points restored

// Successful redemption
Redeem sending demo.sku.com with Quantity : 5 to server
Redeem Item found. 5000 will committed
Calling mother app callback with SKU : demo.sku.com
Redemption is Completed :true
Redeem – Status: 200
Transaction Completed

Find an explanatory diagram of the redemption flow below:

Redemption flow