LoyaltyLion
Integration
The following is a guide on how to integrate LoyaltyLion with Bloomreach Engagement using Omniconnect.
This integration allows you to use LoyaltyLion functions in Bloomreach Engagement. Use this integration to feed events and customer property updates from LoyaltyLion, such as tiers, points, earnings, vouchers, upgrades, or downgrades, into Bloomreach Engagement.
Use cases
You can use LoyaltyLion for tasks such as:
- Welcome emails
- Monthly updates about loyalty points
- Warnings about the expiration of loyalty points
- Emails about the next tier
- Emails about upgraded tiers
- Reminders about unused vouchers
How to set it up
Prerequisites
- A Bloomreach Engagement project with integration access
- Ability to use LoyaltyLion API to set up webhooks
- Knowledge of JavaScript
1. Set up Omniconnect
This integration makes use of the Omniconnect feature in Bloomreach Engagement. To set up Omniconnect:
- Go to your Bloomreach Engagement environment.
- Go to Data & Assets > Integrations and press + Add new integration.
- Find Omniconnect and press + Add integration.
- Name the integration and press Save integration.
- Click on the Transformation tab.
- Paste the transformation function into the appropriate text field.
- Adjust the
email_id
customer identifier name, if required
- Go back to the Settings tab and copy the Omniconnect URL
2. Configure LoyaltyLion
Use the LoyaltyLion API to enable webhooks on the required topics. The topics refer to different actions that will trigger webhooks to send data to Bloomreach. Decide which topics suit you and configure them in the LoyaltyLion API. You can use Postman, for example.
The following topics were used in the transformation function.
Requirements for the initial integration
customers/update
program_events/customer.tier_upgraded
program_events/customer.tier_downgraded
program_events/customer.points_earned
program_events/customer.claimed_reward
program_events/customer.approaching_tier_upgrade
The customers/update
topic triggers a customer update call. All program_events
topics trigger events with names taken from the text following the ".", and prefixed with loyalty_lion
. For example, program_events/customer.tier_upgraded > loyalty_lion_tier_upgraded
.
Customer properties tracked
loyalty_lion_customer_updated_at
loyalty_lion_points_approved
loyalty_lion_points_pending
loyalty_lion_points_spent
loyalty_lion_rewards_claimed
loyalty_lion_tier_name
Events tracked and their properties
loyalty_lion_approaching_tier_upgrade
current_tier_default
current_tier_hidden
current_tier_id
current_tier_lower_bound
current_tier_name
current_tier_number
current_tier_upper_bound
email
next_tier_default
next_tier_hidden
next_tier_id
next_tier_lower_bound
next_tier_name
next_tier_number
next_tier_upper_bound
loyalty_lion_tier_downgraded
email
new_tier_default
new_tier_hidden
new_tier_id
new_tier_lower_bound
new_tier_name
new_tier_number
new_tier_upper_bound
previous_tier_default
previous_tier_hidden
previous_tier_id
previous_tier_lower_bound
previous_tier_name
previous_tier_number
previous_tier_upper_bound
loyalty_lion_tier_upgraded
email
new_tier_default
new_tier_hidden
new_tier_id
new_tier_lower_bound
new_tier_name
new_tier_number
new_tier_upper_bound
previous_tier_default
previous_tier_hidden
previous_tier_id
previous_tier_lower_bound
previous_tier_name
previous_tier_number
previous_tier_upper_bound
loyalty_lion_points_earned
activity_id
activity_merchant_id
activity_order
activity_resource
activity_state
activity_value
email
rule_id
rule_name
rule_title
transaction_created_at
transaction_id
transaction_points_approved
transaction_points_pending
transaction_resource
transaction_adjustment
transaction_claimed_reward
email
discount_amount
discount_type
reward_type
title
voucher_code
Note
Have a look at the Postman collection code for further assistance
Transormation function
This function handles webhooks for different topics in different formats, though some common elements exist. It sets some common payload data at the start and then uses a switch statement based on the incoming topic to add the specific data required for that event. Depending on the topic, it generates either a customer update or an event. An email_id
identifier, which can be edited, is required.
/**
* Handler is the entry point for the function that enables the transformation of the data.
* @param data
* @returns {*}
*/
function handler(data) {
const topicParts = data.topic.split( "/" );
const email = topicParts[0] == "customers" ? data.payload.customer.email : data.payload.properties.customer.email;
const properties = topicParts[0] == "customers" ? {} : {
"email": email
};
const timestamp_name = topicParts[0] == "customers" ? "update_timestamp" : "timestamp";
const timestamp_value = topicParts[0] == "customers" ? data.payload.customer.updated_at : data.created_at;
const output = [ {
"name": topicParts[0].replace( "program_", "customers/" ),
"data": {
"customer_ids": {
"email_id": email
},
"properties": properties,
[ timestamp_name ]: Math.round( Date.parse( timestamp_value ) / 1000 )
}
} ];
const body = output[0].data; //for easier referencing later
// If this is an event, set the name based on Loyalty Lion topic.
if (topicParts[0] == "program_events") {
body.event_type = topicParts[1].replace("customer.", "loyalty_lion_")
}
switch ( topicParts[1] ) {
case "update": {
// Customer properties update
body.properties.loyalty_lion_points_approved = data.payload.customer.points_approved;
body.properties.loyalty_lion_points_pending = data.payload.customer.points_pending;
body.properties.loyalty_lion_points_spent = data.payload.customer.points_spent;
body.properties.loyalty_lion_rewards_claimed = data.payload.customer.rewards_claimed;
body.properties.loyalty_lion_customer_updated_at = body.update_timestamp;
body.properties.loyalty_lion_tier_name = data.payload.customer.loyalty_tier_membership.loyalty_tier.name;
break;
}
case "customer.tier_upgraded":
case "customer.tier_downgraded":
case "customer.approaching_tier_upgrade": {
// These three are very similar, but have slightly different tier object names within the payload
const tierObjects = ["previous_tier","next_tier","current_tier","new_tier"];
// Loop through all available tier objects and set into properties
for (const obj of tierObjects) {
for (const prop in data.payload.properties[obj]) {
body.properties[obj + "_" + prop] = data.payload.properties[obj][prop];
}
}
break;
}
case "customer.points_earned": {
// This has a more complex structure than most. transaction > activity > rule is a nested structure
for (const prop in data.payload.properties.transaction) {
if (prop != "activity") {
body.properties["transaction_" + prop] = data.payload.properties.transaction[prop];
}
}
for (const prop in data.payload.properties.transaction.activity) {
if (prop != "rule") {
body.properties["activity_" + prop] = data.payload.properties.transaction.activity[prop];
}
}
if(data.payload.properties.transaction.activity) {
for (const prop in data.payload.properties.transaction.activity.rule) {
body.properties["rule_" + prop] = data.payload.properties.transaction.activity.rule[prop];
}
}
break;
}
default: {
// Any other event we aren't specifically catering for can be handled in this generic way - includes customer.claimed_reward.
for (const prop in data.payload.properties) {
// capture all properties except customer
if (prop != "customer") {
body.properties[prop] = data.payload.properties[prop];
}
}
}
}
return output;
}
Postman collection code
{
"info": {
"_postman_id": "77b293f0-dbf1-491d-b96a-7439f77f8242",
"name": "Loyalty Lion API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "28889212"
},
"item": [
{
"name": "List Webhooks",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Delete Webhook",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks/123456",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks",
"123456"
]
}
},
"response": []
},
{
"name": "Create Webhook - approaching_tier_upgrade",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"program_events/customer.approaching_tier_upgrade\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Create Webhook - update",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"customers/update\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Create Webhook - tier_upgraded",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"program_events/customer.tier_upgraded\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Create Webhook - tier_downgraded",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"program_events/customer.tier_downgraded\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Create Webhook - points_earned",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"program_events/customer.points_earned\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
},
{
"name": "Create Webhook - claimed_reward",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\"webhook\":{\"topic\":\"program_events/customer.claimed_reward\",\"address\":\"{{webhookUrl}}\"}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "https://api.loyaltylion.com/v2/webhooks",
"protocol": "https",
"host": [
"api",
"loyaltylion",
"com"
],
"path": [
"v2",
"webhooks"
]
}
},
"response": []
}
],
"auth": {
"type": "basic",
"basic": [
{
"key": "password",
"value": "{{secret}}",
"type": "string"
},
{
"key": "username",
"value": "{{token}}",
"type": "string"
}
]
},
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
}
]
}
Limitations
Loyalty Lion sends a lot of data with each payload in a rather nested structure. The transformation function only takes selected attributes and flattens the structure for the Engagement events. Therefore, not everything is included by default. You may have different requirements for which data points you want to capture.
Updated 12 days ago