Marketing Cloud (SFMC™) Integration Guide
Presented by Exchange Solutions | February 21, 2025
ES Loyalty Offer Syndication with SFMC
Overview
ES Loyalty™ has native integration with Salesforce Marketing Cloud™ (SFMC) that supports core loyalty marketing communications. This includes both batch and near-real-time integrations that let marketers inform members about their current offers, point balance, tier status, and more — or trigger a message when a redemption is made. This document describes both the near-real-time integrations and the batch/feed integrations.
Exchange Solutions can trigger email communications through SFMC. The goal of this feature is to publish targeted offers and other information to SFMC so that you can send emails based on the state of a client's offers — including current offers, reminders, and confirmations.
System Architecture for Marketing Integration
In the following diagram, the lines marked Event represent transaction-level API integrations and cryptography handling the SFTP upload. Events can trigger an email, synchronize data, or both.
Configuration, audit, and authorization flows are not shown in the diagram.
(Architecture diagram: ES Loyalty API → Event Processing → Marketing Integration Service → Marketing Integration Router → Triggered Send / Data Sync → Marketing Provider / ESP)
Integration with Customer Data Platform (CDP) Systems
CDP systems use SFMC instances to trigger email (such as a registration email) or push notifications. The AccountID that Exchange Solutions syncs to SFMC is used by CDP systems and acts as a unique identifier for both CDP and Loyalty to send email.
Scale and Real-Time Integration
Clients with millions of users and multiple offers per week may have up to 10 million data points that need to be synchronized. At that scale, true real-time integration is not feasible. The goal of this design is to enable as near-real-time integration as possible.
Automation Studio
Salesforce Automation Studio™ is a Salesforce Marketing Cloud™ application used to execute multi-step marketing and data management activities on an immediate, triggered, or scheduled basis. Exchange Solutions recommends that clients use Automation Studio's workflow canvas to build simple or multi-step automations.
Further reading:
Encryption
Security is a non-functional requirement, so the automation task is built to handle decryption. SFMC requires decryption processes to use a custom key. As a result of the encryption process, the extract file is named:
SFMC_TARGETED_OFFERS_V2_YYYYMMDDHHmmssSSS.pgp
Further reading: SFMC key management
Enhanced FTP
"Enhanced FTP" is the marketing term SFMC uses for its FTP server. Exchange Solutions configures a client username and password associated with a client-specific site. Files to be imported are uploaded into the Import directory on the FTP site.
SFMC user credentials are valid for 3 months. A credential rotation schedule is required.
File Drop
The SFMC Automation (Non-Loyalty Members Import) begins with a File Drop trigger definition:
import\
Queue Files: On
Filename Pattern Settings: Begins with TARGETED_OFFERS_
This means: when any file beginning with TARGETED_OFFERS_ appears in the import\ directory, the automation starts.
File Transfer
The first step in the pipeline is a File Transfer Activity. Its purpose is to decrypt the file and move it to the "safehouse" — a special secure area inside SFMC. The encrypted file remains on the server, but the decrypted file moves to a protected area accessible only by other SFMC processes.
Salesforce Marketing Cloud (SFMC) API
Exchange Solutions recommends using the REST API where possible, to simplify integration with standard HTTP clients:
Ongoing maintenance integration is limited to a small set of well-defined API calls.
OAuth 2.0 Authorization Token
The Salesforce REST API is protected by OAuth 2.0. Exchange Solutions configures server-to-server API integration for each client, generating a client_id and client_secret required to obtain a valid API access token. Two endpoints are also created:
authAPI— used to interact with the OAuth APIsrestAPI— used to interact with SFMC once an OAuth access token has been obtained
These endpoints are provided to the client.
Request:
POST {{authAPI}}/v2/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "{{client_id}}",
"client_secret": "{{client_secret}}"
}
The
client_idandclient_secretvalues are provided to Exchange Solutions.
Response:
A successful call returns a valid access_token:
{
"access_token": "eyJhbGciOiJIUzI1NiIsImtpZCI6IjEiLCJ2ZXIiOiIxIiwidHlwIjoiSldUIn0...",
"token_type": "Bearer",
"expires_in": 1079,
"scope": "offline automations_execute journeys_execute email_send list_and_subscribers_write data_extensions_write",
"soap_instance_url": "https://mc4swg8ykrt2k.soap.marketingcloudapis.com/",
"rest_instance_url": "https://mc4swg8ykrt2k.rest.marketingcloudapis.com/"
}
The access_token expires after the number of seconds specified in expires_in. On a subsequent API call, the client may receive a 401 response and must be ready to obtain a new token:
{
"documentation": "https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/error-handling.htm",
"errorcode": 0,
"message": "Not Authorized"
}
Further reading: Types of data security solutions
ES Loyalty Batch Load
In addition to user-specific targeting data, Exchange Solutions requires data from the offer template itself. This lets SFMC emails join data together to provide a complete "Full Offer" view. Generated files must follow this naming convention:
SFMC_TARGETED_OFFERS_V2_YYYYMMDDHHmmssSSS.txt
This convention allows multiple targeted offer files to be processed daily, if required. If the expected volume of loyalty offers being loaded or changed is relatively low, Exchange Solutions will attempt to push updates as they happen via the SFMC REST API.
Targeted Offer Completion (USER_TARGETED_COMPLETION_FACTS) DE
This data extension (DE) stores cumulative history on spend or amount for continuity (frequency) offers and non-continuity (non-frequency) offers. OfferCompletionCount has a default value of 0. Frequency fields are only used for continuity (frequency) offers.
Exchange Solutions syndicates all identified fields where possible. The data extension has the following definition (PK = Primary Key):
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | OfferCode | Text | 128 | Required. Unique ID for the promotion. | |
| X | AccountID | Text | 128 | Required. Member Account ID. | |
OfferCompletionDate | Text (ISO UTC) | 50 | X | UTC timestamp of when this offer was fully completed. If an offer has a max completions of 2, this value is not set when completed for the first time. | |
OfferCompletionCount | Number | Required. Number of completions; the max is in the promotion data (the template). Default: 0. | |||
FrequencyTotal | Number | X | Total spend toward completion of this offer so far; can also represent quantity of items. | ||
FrequencyNext | Number | X | Remaining spend required to reach the minimum threshold; can also represent quantity of items. | ||
FrequencyUnused | Number | X | Total spend accumulated on this offer that has not yet been applied because the spend threshold has not been reached; can also represent quantity of items. | ||
OfferCompletionLimit | Number | X | Maximum number of times the offer can be completed. | ||
MinTransactionCount | Number | X | Minimum number of transactions required to complete the offer. | ||
CurrentTransactionCount | Number | X | Current number of transactions for this offer. |
Example REST API request:
PUT {{restAPI}}/hub/v1/dataevents/key:USER_TARGETED_FACTS/rows/OfferCode:FREQ_OFFER_SPEND100_3TRANS
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"AccountID": "43e8f98d-6a29-43ff-950e-7471a9c185cd",
"AcceptanceState": "ACCEPTED",
"OfferCompletedDate": "2024-08-20T18:28:03.405Z",
"OfferCompletionCount": 1,
"FrequencyTotal": 260,
"FrequencyNext": 40,
"FrequencyUnused": 60,
"OfferCompletionLimit": 1,
"MinTransactionCount": 1,
"CurrentTransactionCount": 1
}
Data Events Submission for an Offer Template (PROMOTION_FACTS) DE
The key API for offer template integration is putDataExtensionRowByKey. This API upserts a live promotion's information based on the known OfferCode.
See Event Submission for Loyalty Profile Update to see how that process is carried out.
Exchange Solutions syndicates all identified fields where possible. There are no default values for this data extension.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | OfferCode | Text | 128 | Required. Unique ID for the promotion. Must use 3–128 alphanumeric characters and underscores only (a-z, A-Z, 0-9, _). | |
OfferName | Text | 128 | Required. Human-readable name of the offer. Must use 3–128 alphanumeric characters, allowed symbols (.@+-$&'), French letters, and spaces. | ||
OfferStatus | Text | 50 | Required. In-market status. Possible values: ACTIVE, DISABLED, or DELETED. | ||
MaxCompletions | Number | X | Maximum number of times the offer can be completed. | ||
OfferRank | Number | X | Ranking priority in the list of available offers. Offers ranked 1 are highest priority. | ||
OfferStartDate | Text | 50 | Required. UTC timestamp for when the offer begins. | ||
OfferEndDate | Text | 50 | X | UTC timestamp for when the offer ends. | |
EventID | Text | 128 | X | Used for filtering in the Promotion Details dashboard. Allows grouping of recurring events for year-over-year analysis or as a campaign identifier for a collection of offers. Use 3–64 alphanumeric characters and underscores only (a-z, A-Z, 0-9, _). | |
VehicleID | Text | 128 | X | Used for filtering in the Promotion Details report, one level deeper than EventID. Can be used to group related offers in the same period or the same offer across different periods. Use 3–64 alphanumeric characters and underscores only (a-z, A-Z, 0-9, _). | |
ReportingIdentifier | Text | 50 | X | Provides a label for a filter in a Promotion dashboard. Usually used to group categories of promotions, channels of distribution, or department ownership. Examples: FLASH_SALE, GLOBAL_MASS, BEHAVIORAL_OFFER, DIGITAL_PERSONALIZED_OFFER. | |
IsDynamic | Boolean | Required. Whether the offer is static or dynamic. True = dynamic, False = static. | |||
ActivationMethod | Text | 50 | Required. Method by which the offer is activated. Values: AUTO, LTC (load to card), or COUPON. | ||
VendorFunded | Boolean | X | Whether the offer is funded by a client vendor. True or False. | ||
PromoHeadline | Text | 128 | X | Promotional headline that accompanies the offer. See localization note below. | |
ShortDescription1 | Text | 128 | X | First line of a short description of the offer. See localization note below. | |
ShortDescription2 | Text | 128 | X | Second line of a short description of the offer. See localization note below. | |
LongDescription | Text | 4000 | X | Longer text description of the offer. See localization note below. | |
SmallImageURL | Text | 1016 | X | URL linking to a small image. See localization note below. | |
SmallImageHDURL | Text | 1016 | X | URL linking to a small high-definition image. See localization note below. | |
LargeImageURL | Text | 1016 | X | URL linking to a large image. See localization note below. | |
LargeImageHDURL | Text | 1016 | X | URL linking to a large high-definition image. See localization note below. | |
RewardType | Text | 50 | Required. Type of reward associated with the offer. Values: FLAT or MULTIPLIER. | ||
RewardAmount | Number | Required. Number of points in the reward. | |||
Category | Text | 50 | X | Category for this offer. Value: PROMO. | |
SubCategory | Text | 50 | X | Subcategory for this offer. Value: BONUS. | |
OfferDisplayDate | Text | 50 | X | UTC timestamp when the offer was first displayed to members. | |
IsFrequency | Boolean | X | Whether the offer is a frequency offer that requires the member to carry out more than one transaction to fulfill it. True or False. | ||
UserCompletionLimit | Number | X | Maximum number of offer completions allowed per member. | ||
UserPointsLimit | Number | X | Maximum number of reward points allowed per member. | ||
OfferCompletionLimit | Number | X | Maximum number of completions allowed for the offer across all members. | ||
UserRewardLimit | Number | X | Maximum number of reward dollars allowed per member. | ||
Currency | Text | 50 | X | Currency rewarded for this offer. |
Note for Localization
If the integration is in GATEWAY mode and only the default language is used, standard field names are used in SFMC. If localized fields are submitted (for English and French), localized fields are created in SFMC as follows:
| EN | FR |
|---|---|
PromoHeadline_en | PromoHeadline_fr |
ShortDescription1_en | ShortDescription1_fr |
ShortDescription2_en | ShortDescription2_fr |
LongDescription_en | LongDescription_fr |
SmallImageURL_en | SmallImageURL_fr |
SmallImageHDURL_en | SmallImageHDURL_fr |
LargeImageURL_en | LargeImageURL_fr |
LargeImageHDURL_en | LargeImageHDURL_fr |
Example Data Extension
The following is an example of the PROMOTION_FACTS data extension (localization not used):
PUT {{restAPI}}/hub/v1/dataevents/key:PROMOTION_FACTS/rows/OfferCode:OFFER1
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"OfferStatus": "ACTIVE",
"OfferName": "PP10979_CEREAL_OR_OATMEAL",
"MaxCompletions": 1,
"OfferRank": 1,
"OfferStartDate": "2024-08-09T04:00:00Z",
"OfferEndDate": "2024-08-12T03:59:59Z",
"EventID": "00979",
"VehicleID": "10979",
"ReportingIdentifier": "FLYER_INSTORE_BONUS",
"IsDynamic": false,
"ActivationMethod": "MASS",
"VendorFunded": false,
"ShortDescription1": "3 DAYS: CEREAL, HONEY CEREAL OR MULTI GRAIN CEREAL 350G TO 430G, OR OATMEAL ASSORTED VARIETIES 425G TO 475G $2.99 LIMIT 3 AFTER LIMIT ROW $3.99",
"ShortDescription2": "If we have it",
"LongDescription": "3 DAYS: CEREAL, HONEY CEREAL OR MULTI GRAIN CEREAL 350G TO 430G, OR OATMEAL ASSORTED VARIETIES 425G TO 475G $2.99 LIMIT 3 AFTER LIMIT ROW $3.99",
"SmallImageURL": "https://www.someimage.image001reg.png",
"SmallImageHDURL": "https://www.someimage.image001hd.png",
"LargeImageURL": "https://www.someimage.image002reg.png",
"LargeImageHDURL": "https://www.someimage.image002hd.png",
"RewardType": "MULTIPLIER",
"RewardAmount": 20,
"Category": "PROMO",
"SubCategory": "BONUS",
"OfferDisplayDate": "2024-06-09T04:00:00Z",
"IsFrequency": "false",
"PromoHeadline": "Stock up on cereal today!",
"UserCompletionLimit": "2",
"UserPointsLimit": "100",
"OfferCompletionLimit": "50"
}
Response:
A successful (200) response echoes back the updated information:
{
"keys": {
"offerCode": "OFFER1"
},
"values": {
"offerStatus": "ACTIVE",
"offerName": "PP10979_CEREAL_OR_OATMEAL",
"promoHeadline": "Stock up on cereal today!",
"category": "PROMO",
"subCategory": "BONUS",
"maxCompletions": 1,
"offerRank": 1,
"offerStartDate": "2024-08-09T04:00:00Z",
"offerEndDate": "2024-08-12T03:59:59Z",
"offerDisplayDate": "2024-06-09T04:00:00Z",
"eventID": "00979",
"vehicleID": "10979",
"reportingIdentifier": "FLYER_INSTORE_BONUS",
"isDynamic": false,
"isFrequency": "false",
"activationMethod": "MASS",
"vendorFunded": false,
"shortDescription1": "3 DAYS: CEREAL, HONEY CEREAL OR MULTI GRAIN CEREAL 350G TO 430G, OR OATMEAL ASSORTED VARIETIES 425G TO 475G $2.99 LIMIT 3 AFTER LIMIT ROW $3.99",
"shortDescription2": "If we have it",
"longDescription": "3 DAYS: CEREAL, HONEY CEREAL OR MULTI GRAIN CEREAL 350G TO 430G, OR OATMEAL ASSORTED VARIETIES 425G TO 475G $2.99 LIMIT 3 AFTER LIMIT ROW $3.99",
"smallImageURL": "https://www.someimage.image001reg.png",
"smallImageHDURL": "https://www.someimage.image001hd.png",
"largeImageURL": "https://www.someimage.image002reg.png",
"largeImageHDURL": "https://www.someimage.image002hd.png",
"rewardType": "MULTIPLIER",
"rewardAmount": 20,
"userPointsLimit": "100",
"userCompletionLimit": "2",
"offerCompletionLimit": "50"
}
}
Most of these fields are self-explanatory, but some require client-specific validation. Validate that all size restrictions are compatible with current Promotion Templates. SFMC can be updated if required.
Content for a Banner (BANNER_FACTS) DE
The BANNER_FACTS data extension provides content for a banner.
Exchange Solutions syndicates all identified fields where possible. There are no default values for this data extension.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | BannerCode | Text | 128 | Required. Unique ID for the banner. Must use 3–128 alphanumeric characters and underscores only (a-z, A-Z, 0-9, _). | |
Description | Text | 128 | X | Description of the banner (a headline). See localization note below. | |
Channel | Text | 50 | Required. Channel through which the banner was provided (for example, CONSOLE). | ||
Status | Text | 50 | Maximum number of times the offer can be completed. | ||
BusinessUnit | Text | 50 | X | Business unit associated with the banner, if any. The banner may be branded for this business unit. | |
AltText | Text | 128 | X | Alternative text displayed if the banner image cannot be displayed. See localization note below. | |
BannerImageLarge | Text | 1016 | X | URL linking to a large image. See localization note below. | |
BannerImageLargeHD | Text | 1016 | X | URL linking to a large high-definition image. See localization note below. | |
BannerImageSmall | Text | 1016 | X | URL linking to a small image. See localization note below. | |
BannerImageSmallHD | Text | 1016 | X | URL linking to a small high-definition image. See localization note below. | |
BannerLink | Text | 1016 | X | URL in the banner for the member to click through. See localization note below. |
Note for Localization
If the integration is in GATEWAY mode and only the default language is used, standard field names are used in SFMC. If localized fields are submitted (for English and French), localized fields are created in SFMC as follows:
| EN | FR |
|---|---|
Description_en | Description_fr |
AltText_en | AltText_fr |
BannerImageLarge_en | BannerImageLarge_fr |
BannerImageLargeHD_en | BannerImageLargeHD_fr |
BannerImageSmall_en | BannerImageSmall_fr |
BannerImageSmallHD_en | BannerImageSmallHD_fr |
BannerLink_en | BannerLink_fr |
Example Data Extension
The following is an example of the BANNER_FACTS data extension (localization not used):
PUT {{restAPI}}/hub/v1/dataevents/key:BANNER_FACTS/rows/BannerCode:BANNER1
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"Description": "ACTIVE",
"Status": "PP10979_CEREAL_OR_OATMEAL",
"Channel": 1,
"BusinessUnit": 1,
"AltText": "2024-08-09T04:00:00Z",
"BannerImageLarge": "https://www.someimage.image001reg.png",
"BannerImageLargeHD": "https://www.someimage.image001hd.png",
"BannerImageSmall": "https://www.someimage.image002reg.png",
"BannerImageSmallHD": "https://www.someimage.image002hd.png",
"BannerLink": "https://www.buyco.co/clickthrough/"
}
Response:
{
"keys": {
"bannerCode": "BANNER1"
},
"values": {
"Description": "ACTIVE",
"Status": "PP10979_CEREAL_OR_OATMEAL",
"Channel": 1,
"BusinessUnit": 1,
"AltText": "2024-08-09T04:00:00Z",
"BannerImageLarge": "https://www.someimage.001reg.png",
"BannerImageLargeHD": "https://www.someimage.001hd.png",
"BannerImageSmall": "https://www.someimage.002reg.png",
"BannerImageSmallHD": "https://www.someimage.002hd.png",
"BannerLink": "https://www.buyco.co/clickthrough/"
}
}
Member Household Balance (MEMBER_HOUSEHOLD_FACTS) DE
The MEMBER_HOUSEHOLD_FACTS data extension provides updates to household balances and the corresponding dollar value of points.
Exchange Solutions syndicates all identified fields where possible. There are no default values for this data extension.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | AccountID | Text | 254 | Required. Unique ID for a member account in the household. GUID format. | |
HouseholdPointBalance | Number | Required. Point balance for a member account. | |||
HouseholdPointValue | Decimal | 18,2 | Point value in dollars (two decimal places) for a member account. |
Example Data Extension
PUT {{restAPI}}/hub/v1/dataevents/key:MEMBER_HOUSEHOLD_FACTS/rows/AccountID:34de4da3-cce0-4def-ae11-b71b28b9f8ef
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"HouseholdPointBalance": "50000",
"HouseholdPointValue": "500.00"
}
Response:
{
"keys": {
"AccountID": "34de4da3-cce0-4def-ae11-b71b28b9f8ef"
},
"values": {
"HouseholdPointBalance": "50000",
"HouseholdPointValue": "500.00"
}
}
API Exceptions
With any REST API call, a successful (200) response is expected. However, when using an external provider (SFMC), issues may occur. There are two primary concerns and one rare scenario.
Unauthorized
If the API token has expired, the client receives a 401 exception and must acquire a new token before retrying the original call. See OAuth 2.0 Authorization Token for more information.
Throttled
SFMC is a SaaS provider that protects its platform from excessive API call volumes. From a REST service perspective, an unusually large number of API calls within a given period may be treated as an attack.
See: SFMC API limits
If the expected bulk load of Promotions is under 2,500, Exchange Solutions does not anticipate throttling issues. However, clients should be prepared to handle a 429 response.
See: SFMC error handling
Unavailable
In rare cases, SFMC may be unavailable. This is outside the control of Exchange Solutions.
ES Loyalty Member Profile Update with SFMC
Syndicating Data and System of Record
After a member registers in the Loyalty Program, it may be necessary to syndicate data to Salesforce. This provides a broader set of information for more precise targeting, including:
- Profile data
- Offer data
- Other relevant data
A system of record (SOR) is the authoritative data source for a given data element. The SOR can be either ES Loyalty or the client's system, depending on requirements.
- If ES Loyalty is the SOR, it is predominantly responsible for syndicating data changes.
- If the client system is the SOR, it is predominantly the source of data changes.
Primary Identifier
The primary identifier is the LoyaltyId or AccountId. This is an internal identifier (GUID) that does not change for any individual member. All facts are optional in the SFMC Data Extensions, which allows fine-grained upserts as data changes.
Salesforce Marketing Cloud (SFMC) API
See Salesforce Marketing Cloud (SFMC) API for details.
Event Submission for Loyalty Profile Update (LOYALTY_PROFILE_FACTS) DE
Additional SFMC Data Extensions support the persistent state of a member's data. This data extension stores loyalty profile-related attributes managed by ES Loyalty. The Source attribute has a default value of ES-Loyalty.
Profile data is stored in its own data extension using the same API as for General Registration and Profile Update — putDataExtensionRowByKey. This API upserts a member's loyalty data based on the known LoyaltyId (as assigned in ES Loyalty). The only differences from other calls are the target data extension (LOYALTY_PROFILE_FACTS), the key property name (LoyaltyId), and the fact values provided.
Exchange Solutions syndicates all identified fields where possible.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | LoyaltyId | Text | 128 | Required. The member's Loyalty ID, which ties to the SFMC SubscriberKey for the Loyalty Program. | |
LoyaltyAccountStatus | Text | 25 | X | Status of the account. For example, ACTIVE or EXPIRED. | |
CardNumber | Text | 25 | X | The member's current default Loyalty Card Number. | |
CardStatus | Text | 25 | X | The member's current default Loyalty Card Status. For example, ACTIVE. | |
IsEmployee | Boolean | X | Whether the member is an employee. True or False. | ||
TotalPointBalance | Number | X | The member's current total point balance. | ||
AvailablePointBalance | Number | X | The member's current available point balance, accounting for holds and reservations. | ||
Timestamp | Text | 50 | Required. UTC timestamp for when loyalty profile data was accessed. | ||
Source | Text | 50 | Required. Source of the data. Default: ES-Loyalty. | ||
TotalPointValue | Decimal | 18,2 | X | The member's current total point value in dollars and cents. | |
AvailablePointValue | Decimal | 18,2 | X | The member's current available point value in dollars and cents, accounting for holds and reservations. | |
InitialAppSessionDate | Text | 50 | X | UTC timestamp of the first session. | |
EnrollmentChannel | Text | 50 | X | The channel through which the member enrolled. For example, MOBILE. | |
CardType | Text | 50 | X | The type of card. Values: DIGITAL or PHYSICAL. | |
LastActivityDate | Text | 50 | X | UTC timestamp for the most recent account activity. | |
SuspendedFlag | Boolean | X | Whether the account is suspended. True or False. | ||
ExpiredFlag | Boolean | X | Whether the account is expired. True or False. |
Note:
Numberis an integer field with a value range of -2,147,483,648 to 2,147,483,648.Decimalis a decimal field that can contain 18 digits with 2 decimal points of precision.
Example — Full profile update:
PUT {{restAPI}}/hub/v1/dataevents/key:LOYALTY_PROFILE_FACTS/rows/LoyaltyId:d39a85cd-353f-4044-ae87-a20a69c8d2ec
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"values": {
"LoyaltyAccountStatus": "ACTIVE",
"CardNumber": "9731501234617937283",
"CardStatus": "ACTIVE",
"IsEmployee": false,
"TotalPointBalance": 25000,
"TotalPointValue": 10.00,
"AvailablePointBalance": 24000,
"AvailablePointValue": 9.60,
"Timestamp": "2024-06-26T04:00:00Z",
"Source": "ES-Loyalty"
}
}
Response:
{
"keys": {
"loyaltyId": "d3969c8d-cd3f-8844-ae87-a20aa85cd2ec"
},
"values": {
"loyaltyAccountStatus": "ACTIVE",
"cardNumber": "9731501234617937283",
"cardStatus": "ACTIVE",
"isEmployee": "false",
"totalPointBalance": "25000",
"totalPointValue": "10",
"availablePointBalance": "24000",
"availablePointValue": "9.6",
"timestamp": "2024-06-26T04:00:00Z",
"source": "ES-Loyalty"
}
}
In most cases, only a few fields are updated. You can pass only the fields you want to set, along with Timestamp and Source for audit purposes. The remaining data in the extension row is unchanged.
Example — Partial profile update:
PUT {{restAPI}}/hub/v1/dataevents/key:LOYALTY_PROFILE_FACTS/rows/LoyaltyId:d3969c8d-cd3f-8844-ae87-a20aa85
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"values": {
"LoyaltyAccountStatus": "EXPIRED",
"Timestamp": "2024-06-26T04:04:00Z",
"Source": "ES-Loyalty"
}
}
Response:
{
"keys": {
"loyaltyId": "d3969c8d-cd3f-8844-ae87-a20aa85"
},
"values": {
"loyaltyAccountStatus": "EXPIRED",
"timestamp": "2024-06-26T04:04:00Z",
"source": "ES-Loyalty"
}
}
SMS Messaging
The integration between Exchange Solutions and SFMC supports management of SMS subscriptions for members.
SMS Subscription Updates (ALL_MOBILE_NUMBERS) DE
This data extension tracks loyalty members' phone numbers based on their marketing SMS sign-up numbers. It captures both registered and unregistered activities, as well as new sign-ups classified as non-loyalty accounts. ES Loyalty reads from and writes to this data extension to manage SMS subscriptions. An automation in SFMC updates the subscription status from the SFMC Mobile Connect module back to this data extension. In production, this automation runs every 20 minutes.
Exchange Solutions syndicates all identified fields where possible.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | ShortCode | Text | 4000 | The ShortCode value differs per client. Contact your Exchange Solutions TSA for more information. | |
| X | SubscriberKey | Text | 256 | Assigned to the phone number on SMS subscription opt-in. UUID version 4 format. Example: 9367a37f-4a9f-43c9-a71f-e3dcf8332b63. | |
MobileNumber | Phone | 50 | Phone number in format: country code + area code + phone number. Example: 16475746574. | ||
CreatedDate | Text | 50 | Most recent date and time at which the member opted in with the current SMS subscription SubscriberKey. ISO 8601 extended format. Example: 2025-01-08T19:42:06.862Z. | ||
Source | Text | 50 | Source of the original SMS subscription. Values: CONSOLE, POS, WEBSITE, or Mobile Opt-in. | ||
Transformation | Boolean | Whether a recent change has occurred. Default: False. | |||
TransformationAction | Text | 1000 | X | Action to take for the SMS subscription. For loyalty records: REGISTER or UNREGISTER. For non-loyalty records: ADD. | |
TransformationTimestamp | Text | 50 | X | Date/time stamp indicating when a script ran to transform contacts when Transformation is True. Format: MMM DD YYYY HH:MMAM/PM. Example: Jan 22 2025 12:31PM. | |
Program | Text | 254 | Program associated with the subscription. Values: GENERAL or LOYALTY. | ||
Welcome | Boolean | Whether the member has received the Welcome Offer incentive message. Not used by all clients. Default: True. | |||
Locale | Text | 50 | The locale, identified by language. Default: en-ca. Can also be fr-ca. | ||
SubscriptionStatus | Text | 50 | Whether the member is subscribed to SMS messages. Values: OptedIn, OptInPending (in progress), or OptedOut (opt-in failed or subscription was opted out). | ||
OptinDate | Date | X | Last date and time on which the member opted in to an SMS subscription. Format is specific to clients using MobileConnect: MONTH-DD-YYYY (H)H:MMAM/PM. Example: January-22-2025 2:31PM. | ||
OptOutDate | Date | X | Last date and time at which the member opted out of the subscription (if applicable). Format is specific to clients using MobileConnect: MONTH-DD-YYYY (H)H:MMAM/PM. Example: January-22-2025 2:31PM. | ||
Timestamp | Date | X | Date and time for this update. Format is specific to clients using MobileConnect: MONTH-DD-YYYY (H)H:MMAM/PM. Example: January-22-2025 2:31PM. |
Example:
PUT {{restAPI}}/hub/v1/dataevents/key:ALL_MOBILE_NUMBERS/rows/SubscriberKey:9367a37f-4a9f-43c9-a71f-e3dcf8332b63
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"values": {
"ShortCode": "703588",
"SubscriberKey": "9367a37f-4a9f-43c9-a71f-e3dcf8332b63",
"MobileNumber": 16475746574,
"CreatedDate": "2025-01-08T19:42:06.862Z",
"Source": "CONSOLE",
"Transformation": true,
"TransformationAction": "REGISTER",
"TransformationTimestamp": "Jan 22 2025 12:31PM",
"Program": "LOYALTY",
"Welcome": false,
"Locale": "en-ca",
"SubscriptionStatus": "OptedIn",
"OptinDate": "January-16-25 3:17PM",
"OptoutDate": "January-16-25 3:17PM",
"Timestamp": "January-16-25 3:17PM"
}
}
Response:
{
"keys": {
"ShortCode": "703588",
"SubscriberKey": "d3969c8d-cd3f-8844-ae87-a20aa85cd2ec"
},
"values": {
"MobileNumber": 16475746574,
"CreatedDate": "2025-01-08T19:42:06.862Z",
"Source": "CONSOLE",
"Transformation": true,
"TransformationAction": "REGISTER",
"TransformationTimestamp": "Jan 22 2025 12:31PM",
"Program": "LOYALTY",
"Welcome": false,
"Locale": "en-ca",
"SubscriptionStatus": "OptedIn",
"OptinDate": "January-16-25 3:17PM",
"OptoutDate": "January-16-25 3:17PM",
"Timestamp": "January-16-25 3:17PM"
}
}
Marketing Integrations to Trigger SFMC Email
As actions occur in ES Loyalty, key data tables are updated. Some of these data points are important for marketing usage. Exchange Solutions has built a set of marketing integrations that can synchronize with a marketing provider to facilitate transactional emails and business email campaigns. For SFMC, two primary forms of integration are supported: near-real-time and bulk.
Near Real-Time Integration – Transactional Emails
Certain ES Loyalty actions require an email to be sent to the user shortly after the action occurs. These emails typically act as confirmation or notification of an action, or as a call to action for the member. "External System" refers to a mobile application or a client website.
ES Loyalty transactional email support includes:
| Event | Triggered by | Description |
|---|---|---|
| Email Capture | ES Loyalty | An email address is gathered at the POS for an anonymous (unregistered) account or card. This email is a call to action to register. |
| Redemption Confirmation | ES Loyalty | A member submits a transaction containing a point redemption. This email serves as notification and confirmation of the redemption. |
| Partner Link Onboarding | ES Loyalty | A member links the first partner payment card to their account. |
| Partner Link Offboarding | ES Loyalty | A member unlinks the last partner payment card from their account. |
| Transaction without Partner Swipe | ES Loyalty | A member with at least one linked partner payment card completes a transaction without swiping their linked card, thus missing out on bonus points. |
| Points Transfer | ES Loyalty | A member transfers points to another account. This email serves as notification and confirmation for the source account (not the recipient). |
| Online Account Activation | External System | During initial registration, profile information is collected and an email containing a verification token is sent. This is part of a closed-loop process. In current ES Loyalty flows, this is handled by an external system. |
| Password Reset / Login Lockout / Update Email (optional) | External System | Transactional communications recommended for external systems (for example, apps) that provide access to ES Loyalty account information. None of these are tied directly to ES Loyalty operations. |
Batched Synchronization Processes
In addition to near-real-time data sync, ES Loyalty also supports a batched synchronization method. This mode generates files on a schedule (time- or size-based) and sends them to an SFTP site accessible to the marketing provider.
Push (write) operations:
These integrations let Exchange Solutions write data to the marketing provider, keeping it up to date with changes in ES Loyalty or external systems.
| File | Triggered by | Description |
|---|---|---|
| Targeted Offer Sync | ES Loyalty | Synchronizes member targeted offer information. |
| Member Extended Data Sync | ES Loyalty | Synchronizes member extended data (both CLIENT and INTERNAL) attributes. Note: This is only for SFMC integration and is controlled by the IsExtendedDataEnabled parameter. In the worst case, files are generated but the cryptography service is not configured with the SFMC SFTP provider information. |
Authorization:
Bulk data synchronization can be performed via files and SFTP, or with a bulk API.
- SFTP: A secret contains the SFTP username/password or private key.
- API: Can use a configured secret with a username/password or
client_id/client_secretfor Basic Auth, or it may require usingclient_id/client_secretto negotiate OAuth 2.0 sent as a Bearer token.
For OAuth token authorization, consumers must always be prepared to receive a 401 error if the token has expired, and must then negotiate a new token. See OAuth 2.0 Authorization Token for more information.
Import File (USER_TARGETED_FACTS)
The Import File Activity iterates over the decrypted file and processes each row, mapping it to the USER_TARGETED_FACTS data extension. This data extension stores the target audience of offers created for the client loyalty program.
Generated files must follow this naming convention:
SFMC_TARGETED_OFFERS_V2_YYYYMMDDHHmmssSSS.txt
This convention allows multiple targeted offer files to be processed daily, if required. The AccountID and OfferCode field combination is the primary key of the data extension, and matching values are upserted. This handles both initial promotion inserts and subsequent updates.
Exchange Solutions syndicates all identified fields where possible. There are no default values for this data extension.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | AccountID | Text | 128 | Required. Member Account ID. | |
| X | OfferCode | Text | 128 | Required. Unique ID for the promotion. | |
AcceptanceState | Text | 50 | X | Current acceptance status of the offer if it requires explicit opt-in; otherwise, automatically accepted. Values: ACCEPTED, NONE, COMPLETED, or null. | |
OfferAcceptanceDate | Text (ISO UTC) | 50 | X | UTC timestamp when the offer was accepted. | |
OfferCompletedDate | Text (ISO UTC) | 50 | X | UTC timestamp of when the offer was fully completed. If an offer has max completions of 2, this value is not set when completed for the first time. | |
OfferCompletionCount | Number | X | Number of completions. The max is in the promotion data (the template). Default: 0. | ||
TreatmentType | Text | 50 | X | Whether the offer is assigned for PROGRAM, TEST, or CONTROL. | |
OfferStartDate | Text (ISO UTC) | 50 | X | UTC timestamp when the offer went live. | |
OfferEndDate | Text (ISO UTC) | 50 | X | UTC timestamp when the offer ended. |
For large volumes of targeted offers, Exchange Solutions uses the SFTP site on SFMC with a pipe-delimited file format. Example file rows:
11de4da3-cce0-4def-af61-b71b28b9f8ef|OFFER1|NONE|||0|PROGRAM
34de4da3-cce0-4def-ae11-b71b28b9f8ef|OFFER1|ACCEPTED|2024-08-20T12:20:03.702Z|2024-08-21T12:20:03.702Z|1|PROGRAM|2024-09-21T12:20:03.702Z|2024-12-21T12:20:03.702Z|
For SFMC integration, the file is generated record by record and contains no header. Columns are derived by ordinal numbering. The default delimiter is | but this can be overridden via the SFMC secret.
Storing Extended Member Data Attributes (EXTENDED_MEMBER_DATA)
This data extension stores member extended attributes, primarily derived from analytics solutions in ES Loyalty. The Source attribute has a default value of ES-Loyalty.
Exchange Solutions syndicates all identified fields where possible. The correct Value attribute corresponding to the data type of the EMD attribute is included in the AttributeDomain. For example, STRING in the AttributeDomain field corresponds to a value in the StringValue field.
The encrypted file name for EXTENDED_MEMBER_DATA is:
ESL_EXTENDED_MEMBER_DATA_YYYYMMDDHHmmssSSS.pgp
Except for the primary keys, the fields included in this data extension depend on client requirements. The following is an example definition (PK = Primary Key):
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | AccountID | Text | 128 | Required. Member Account ID. | |
| X | AttributeName | Text | 126 | Required. Name of the EMD attribute. | |
AttributeDomain | Text | 25 | Domain associated with the attribute. | ||
StringValue | Text | 4000 | X | String value of the EMD attribute. | |
NumericValue | Number | X | Numeric value of the EMD attribute. | ||
DecimalValue | Decimal | 18,5 | X | Decimal value of the EMD attribute. | |
BooleanValue | Boolean | X | Boolean value of the EMD attribute. | ||
DateValue | Date | X | Date value of the EMD attribute. | ||
Source | Text | 126 | X | Default: ES-Loyalty. | |
UpdatedTimestamp | Text | 50 | Timestamp of the last update to the EMD value. |
Example:
PUT {{restAPI}}/hub/v1/dataevents/key:MEMBER_EXTENDED_DATA/rows/AccountID:827fc0c4-ab21-44b5-b89d-395a60b93dd2
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"AttributeName": "registrationstatus",
"AttributeDomain": "TEXT",
"StringValue": "Registered",
"Source": "ES-Loyalty",
"UpdatedTimestamp": "2024-12-02T10:16:46.893Z"
}
Storing Partner Link Activity (LOYALTY_PARTNER_LINK_FACTS)
This data extension stores partner link activity in the client program, managed by ES Loyalty. The Source attribute has a default value of ES-Loyalty.
Exchange Solutions syndicates all identified fields where possible.
| PK | Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | AccountId | Text | 128 | Required. Unique identifier for the account. | |
| X | PartnerCode | Text | 128 | Required. Unique identifier for the partner. | |
FirstLinkDate | Text | 50 | X | UTC timestamp when the partner link was first created. | |
LastUnlinkDate | Text | 50 | X | UTC timestamp when the partner link was last unlinked. | |
Source | Text | 50 | Required. Source of the partner link. Default: ES-Loyalty. | ||
Timestamp | Text | 50 | Required. UTC timestamp when the partner link was created. | ||
IsLinked | Boolean | Required. Whether there is currently an active partner link for the account. True or False. | |||
EmailStatus | Text | 50 | Required. Status of whether the email is usable for partner link. Values: ONBOARDED or OFFBOARDED. |
Example:
PUT {{restAPI}}/hub/v1/dataevents/key:LOYALTY_PARTNER_LINK_FACTS/rows/AccountID:827fc0c4-ab21-44b5-b89d-395a60b93dd2
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"PartnerCode": "MEGABANK",
"FirstLinkDate": "2024-08-21T18:09:59.312Z",
"LastUnlinkDate": "2024-08-21T18:09:59.354Z",
"Source": "ES-Loyalty",
"Timestamp": "2024-08-21T18:09:59.924Z",
"IsLinked": true,
"EmailStatus": "ONBOARDED"
}
Response:
{
"keys": {
"AccountId": "827fc0c4-ab21-44b5-b89d-395a60b93dd2",
"PartnerCode": "MEGABANK"
},
"values": {
"FirstLinkDate": "2024-08-21T18:09:59.312Z",
"LastUnlinkDate": "2024-08-21T18:09:59.354Z",
"Source": "ES-Loyalty",
"Timestamp": "2024-08-21T18:09:59.924Z",
"IsLinked": true,
"EmailStatus": "ONBOARDED"
}
}
Tracking Offer Completion (USER_REWARD_TRACKING_FACTS)
This data extension tracks data related to offer completion.
Exchange Solutions syndicates all identified fields where possible.
| PK | Name | Type | Max Length | Nullable | Description |
|---|---|---|---|---|---|
| X | OfferCode | Text | 128 | Required. Unique ID for the promotion. | |
| X | AccountID | Text | 128 | Required. Member Account ID. | |
OfferCompletionDate | Text | 50 | X | UTC timestamp of when the offer was fully completed. If an offer has max completions of 2, this value is not set when completed for the first time. | |
OfferCompletionCount | Number | X | Number of completions. The max is in the promotion data (the template). Default: 0. |
Example:
PUT {{restAPI}}/hub/v1/dataevents/key:USER_REWARD_TRACKING_FACTS/rows/OfferCode:OFFER_001
Authorization: Bearer {{accessToken}}
Content-Type: application/json
{
"AccountID": "827fc0c4-ab21-44b5-b89d-395a60b93dd2",
"OfferCompletionDate": "2024-12-02T10:16:46.893Z",
"OfferCompletionCount": 1
}
Response:
{
"keys": {
"OfferCode": "OFFER_001",
"AccountId": "827fc0c4-ab21-44b5-b89d-395a60b93dd2"
},
"values": {
"OfferCompletionDate": "2024-12-02T10:16:46.893Z",
"OfferCompletionCount": 1
}
}
Triggered Sends
Triggered sends are used to send email communications to a member when specific events occur. Data about the event is included in the request and is used to populate a corresponding email template sent to the member. This lets members be automatically notified whenever one of the specified events occurs.
Three different resource types are required in SFMC for email notifications to work:
- Data extension — Created using the triggered send template.
- Email template — Uses the data extension as its source for populating fields.
- Triggered send — Uses the data extension and email content to send the email.
The triggered sends are:
- EmailCaptureTriggeredSend — Notifies the member when their email address has been captured in the system.
- MemberHouseholdFactsTriggeredSend — Notifies the member of household details when they join a household.
- MemberRegistrationTriggeredSend — Notifies the member that they have been registered in the loyalty program.
- MemberTierFactsTriggeredSend — Notifies the member when their tier level has changed.
- MissedPartnerSwipeTriggeredSend — Notifies the member that they missed rewards due to not swiping a partner's loyalty or payment card.
- PartnerLinkUnlinkTriggeredSend — Notifies the member that a partner link has been established or removed.
- PointsTransferTriggeredSend — Provides the member with details of a points transfer from their account to another account.
- RedemptionTriggeredSend — Provides the member with details of a redemption on their account.
- RewardGameTriggeredSend — Provides the member with a URI to access a gameplay they have been rewarded.
EmailAddress and SubscriberKey are mandatory fields for all triggered sends.
EmailCaptureTriggeredSend
Sends an email to the member when their email address has been captured from the POS system.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Program | Text | 50 | X | Default: LOYALTY. The marketing program with which the email address is associated. |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
Source | Text | 50 | Required. Default: POS. The source of the member's email address. | |
Processed | Boolean | Required. Default: false. Set via an SFMC automation monitoring newly captured emails. |
See EmailCaptureEmail to learn how to create the corresponding email template.
MemberHouseholdFactsTriggeredSend
The email is triggered when a primary member creates or leaves a household (email goes to the primary member), or when a secondary member joins or leaves the household (email goes to both the primary member and the relevant secondary member). It provides information about the household and the affected member's role.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
HouseholdID | Text | 128 | Required. Unique identifier for the household. | |
EventType | Text | 50 | Required. Event associated with this triggered email. For example, INSERT. | |
Role | Text | 50 | Required. Member's role within the household. Values: PRIMARY or SECONDARY. |
See MemberHouseholdFactsEmail to learn how to create the corresponding email template.
MemberRegistrationTriggeredSend
Sends an email informing the member that they have been registered in the loyalty program.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
RegistrationDate | Text (ISO UTC) | 50 | X | Timestamp for when registration occurred. |
LoyaltyID | Text | 50 | X | Loyalty ID assigned to the member account on registration. |
LastName | Text | 50 | X | Last name of the member. |
FirstName | Text | 50 | X | First name of the member. |
BusinessName | Text | 50 | X | Business name of the member. |
RegistrationChannel | Text | 50 | X | The channel through which registration took place. For example, APP. |
See MemberRegistrationEmail to learn how to create the corresponding email template.
MemberTierFactsTriggeredSend
Sends an email when a member's tier level changes.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
AccountID | Text | 128 | Required. In GUID format. | |
ProgramCode | Text | 128 | Required. Unique identifier for the program. | |
TierCode | Text | 50 | Required. Unique alphanumeric code associated with this tier. | |
TierName | Text | 50 | Required. Name of the tier used by the client. | |
TierRank | Number | 8 | Required. Rank associated with this tier. | |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. |
See MemberTierFactsEmail to learn how to create the corresponding email template.
MissedPartnerSwipeTriggeredSend
Sends an email notifying the member that they missed rewards due to not swiping a partner's loyalty or payment card.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
TransactionTimestamp | Text | 50 | Required. Timestamp of the original transaction. | |
TransactionLocation | Text | 128 | X | Location where the transaction occurred. |
TransactionStoreNumber | Text | 50 | X | Unique identifier for the store where the transaction occurred. |
TransactionChannel | Text | 50 | Required. Channel through which the transaction took place. For example, POS or APP. | |
Source | Text | 50 | X | Default: ES-LOYALTY. The source of the member's email address. |
BusinessUnit | Text | 128 | X | Business unit associated with the transaction, if applicable. |
PartnerName | Text | 128 | Required. Name of the partner for the partner link. | |
PartnerCode | Text | 50 | Required. Unique identifier for the partner. | |
Program | Text | 50 | X | Default: LOYALTY. The marketing program associated with this transaction. |
TransactionID | Text | 50 | Required. Unique identifier for the transaction. |
See MissedPartnerSwipeEmail to learn how to create the corresponding email template.
PartnerLinkUnlinkTriggeredSend
Sends an email notifying the member that a partner link has been established or removed.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
Source | Text | 50 | Required. Default: ES-LOYALTY. The source of the member's email address. | |
PartnerName | Text | 128 | Required. Name of the partner for the partner link. | |
PartnerCode | Text | 50 | Required. Unique identifier for the partner. | |
Program | Text | 50 | X | Default: LOYALTY. The marketing program associated with this transaction. |
LinkStatus | Text | 25 | Status of the partner link. |
See PartnerLinkUnlinkEmail to learn how to create the corresponding email template.
PointTransferTriggeredSend
Sends an email providing the member with details of a points transfer from their account to another account.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Program | Text | 50 | X | Default: LOYALTY. The marketing program with which the email address is associated. |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
RecipientAccountID | Text | 50 | Required. Unique identifier for the account receiving the transferred points. | |
PointTransferTimestamp | Text (ISO UTC) | 50 | Required. Timestamp for when the points were transferred. | |
PointTransferPoints | Number | Required. Amount of the transfer in points. | ||
PointTransferAvailableBalance | Number | Required. Balance of points available for transfer. | ||
PointTransferChannel | Text | 50 | X | Channel through which the points transfer was initiated. |
BusinessUnit | Text | 50 | X | Business unit associated with the transfer. |
TransactionID | Text | 50 | Required. Unique identifier for the transfer transaction. | |
BusinessName | Text | 50 | X | Business name associated with the account receiving the transfer, if applicable. |
PointTransferDollars | Decimal | 18,2 | X | Amount of the transfer in dollars. |
Source | Text | 50 | Default: ES-LOYALTY. The source of the member's email address. |
See PointTransferEmail to learn how to create the corresponding email template.
RedemptionTriggeredSend
Sends an email providing the member with details of a redemption on their account.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
EmailAddress | Text | 128 | Required. In email address format. | |
Program | Text | 50 | X | Default: LOYALTY. The marketing program with which the redemption is associated. |
Timestamp | Text (ISO UTC) | 50 | Required. Timestamp for this triggered email send. | |
Source | Text | 50 | Required. Default: ES-LOYALTY. The source of the member's email address. | |
RedemptionPoints | Number | Required. Number of points redeemed. | ||
RedemptionDollars | Number | Required. Value in dollars of the redemption. | ||
RedemptionLocation | Text | 128 | X | Location where the points redemption was initiated. |
RedemptionTimestamp | Text (ISO UTC) | 50 | Required. Timestamp of when the redemption was carried out. | |
TransactionID | Text | 50 | Required. Unique identifier for the redemption transaction. | |
RedemptionStoreNumber | Text | 50 | X | Unique identifier for the store where the redemption was initiated, if applicable. |
RedemptionBalance | Number | 50 | Required. Number of points available for redemption before this redemption event. | |
RedemptionChannel | Text | 50 | X | Channel through which the redemption took place, if applicable. |
RedemptionAvailableBalance | Number | Required. Number of points available for redemption after this redemption event. | ||
BusinessUnit | Text | 50 | X | Business unit associated with the redemption, if applicable. |
See RedemptionEmail to learn how to create the corresponding email template.
RewardGameTriggeredSend
The email is triggered when a member earns a game play. The message includes a URI the member can click to start the game.
| Name | Data Type | Max Length | Nullable | Description |
|---|---|---|---|---|
SubscriberKey | Text | 128 | Required. Unique ID for the subscriber. | |
AccountID | Text | 128 | Required. In GUID format. | |
EmailAddress | Text | 128 | Required. In email address format. | |
GamePlayURI | Text | 512 | Required. URI to access the game play. |
See RewardGameEmail to learn how to create the corresponding email template.
Configuring Emails
Content Builder is the content management application within Salesforce Marketing Cloud™. To create emails, follow these steps:
- Click Create in Content Builder.
- Click Email Message.
- In Define Properties, choose a creation method and complete the fields:
- Template — Choose from a selection of standard templates.
- HTML — Paste your custom HTML code.
- Text Only — Create from text only. You can also use a code snippet.
- Existing Email — Use a Classic or Content Builder saved email.
- Define email properties. Enter text in the required fields (
*) then click Save or Next. - Click Next.
- In Add Content, build your email, then click Next.
- Preview and test your email, then click Save. To send the email, use Email Studio Send Flow.
To send an email, use Journey Builder or Email Studio.
The following emails must be set up. Actual content should be updated to meet business requirements.
EmailCaptureEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member provides their email address (for example, at the POS) to prompt for Loyalty registration.
- Subject — Email Capture/Registration email
- Personalization — Choose New Source >
EmailCaptureTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
Program %%=v(@program)=%%
Timestamp %%=v(@timestamp)=%%
Source %%=v(@source)=%%
Common attributes (required in all emails):
Subscription Center: %%subscription_center_url%%
Profile Center: %%profile_center_url%%
One-click Unsubscribe:%%unsub_center_url%%
Sender address: %%member_busname%% %%member_addr%% %%member_city%% %%member_state%% %%member_postalcode%% %%member_country%%
MemberHouseholdFactsEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member is registered in the Loyalty program.
- Subject — Email Capture/Registration email
- Personalization — Choose New Source >
MemberHouseholdTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
Timestamp %%=v(@timestamp)=%%
HouseholdID %%=v(@householdId)=%%
EventType %%=v(@eventType)=%%
Role %%=v(@role)=%%
(Include common attributes as listed above.)
MemberRegistrationEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member is registered in the Loyalty program.
- Subject — Email Capture/Registration email
- Personalization — Choose New Source >
MemberRegistrationTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
RegistrationChannel %%=v(@registrationChannel)=%%
RegistrationDate %%=v(@registrationDate)=%%
LoyaltyID %%=v(@loyaltyID)=%%
FirstName %%=v(@firstName)=%%
LastName %%=v(@lastName)=%%
BusinessName %%=v(@businessName)=%%
(Include common attributes as listed above.)
MemberTierFactsEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member is registered in the Loyalty program.
- Subject — Email Capture/Registration email
- Personalization — Choose New Source >
MemberTierFactsTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
AccountID %%=v(@accountID)=%%
ProgramCode %%=v(@programCode)=%%
TierCode %%=v(@tierCode)=%%
TierName %%=v(@tierName)=%%
TierRank %%=v(@tierRank)=%%
Timestamp %%=v(@timestamp)=%%
(Include common attributes as listed above.)
MissedPartnerSwipeEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member provides their email address (for example, at the POS) to prompt for Loyalty registration.
- Subject — Missed Partner Swipe Transaction email
- Personalization — Choose New Data Source >
MissedPartnerTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
Timestamp %%=v(@timestamp)=%%
TransactionTimestamp %%=v(@transactionTimestamp)=%%
TransactionLocation %%=v(@transactionLocation)=%%
TransactionStoreNumber %%=v(@transactionStoreNumber)=%%
TransactionChannel %%=v(@transactionChannel)=%%
BusinessUnit %%=v(@businessUnit)=%%
PartnerCode %%=v(@partnerCode)=%%
PartnerName %%=v(@partnerName)=%%
TransactionID %%=v(@transactionID)=%%
(Include common attributes as listed above.)
PartnerLinkUnlinkEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member links or unlinks a partner payment card.
- Subject — Partner Link/Unlink email
- Personalization — Choose New Data Source >
PartnerLinkUnlinkTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
Timestamp %%=v(@timestamp)=%%
Source %%=v(@source)=%%
partnerCode %%=v(@PartnerCode)=%%
partnerName %%=v(@PartnerName)=%%
linkStatus %%=v(@LinkStatus)=%%
Program %%=v(@program)=%%
(Include common attributes as listed above.)
PointTransferEmail
- Location —
ESL_EmailTemplates(recommended) - Description — An email sent when a member provides their email address (for example, at the POS) to prompt for Loyalty registration.
- Subject — Point Transfer email
- Personalization — Choose New Data Source >
PointTransferTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
Timestamp %%=v(@timestamp)=%%
PointTransferTimestamp %%=v(@pointTransferTimestamp)=%%
PointTransferPoints %%=v(@pointTransferPoints)=%%
PointTransferDollars %%=v(@pointTransferDollars)=%%
PointTransferAvailableBalance %%=v(@pointTransferAvailableBalance)=%%
RecipientAccountID %%=v(@recipientAccountID)=%%
PointTransferChannel %%=v(@pointTransferChannel)=%%
BusinessUnit %%=v(@businessUnit)=%%
BusinessName %%=v(@businessName)=%%
TransactionID %%=v(@transactionID)=%%
(Include common attributes as listed above.)
RedemptionEmail
- Location —
ESL_EmailTemplates - Description — An email sent when a member completes a successful redemption.
- Subject — Redemption email
- Personalization — Choose New Data Source >
RedemptionTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
EmailAddress %%=v(@emailAddress)=%%
RedemptionAvailableBalance %%=v(@redemptionAvailableBalance)=%%
Timestamp %%=v(@timestamp)=%%
RedemptionTimestamp %%=v(@redemptionTimestamp)=%%
RedemptionPoints %%=v(@redemptionPoints)=%%
RedemptionDollars %%=v(@redemptionDollars)=%%
RedemptionBalance %%=v(@redemptionBalance)=%%
RedemptionLocation %%=v(@redemptionLocation)=%%
RedemptionStoreNumber %%=v(@redemptionStoreNumber)=%%
RedemptionChannel %%=v(@redemptionChannel)=%%
BusinessUnit %%=v(@businessUnit)=%%
RedemptionLocalTimestamp %%=v(@redemptionLocalTimestamp)=%%
TransactionID %%=v(@transactionID)=%%
(Include common attributes as listed above.)
RewardGameEmail
- Location —
ESL_EmailTemplates - Description — An email sent when a member completes a successful redemption.
- Subject — Redemption email
- Personalization — Choose New Data Source >
RewardGameTriggeredSend
Available attributes from ESL:
SubscriberKey %%=v(@subscriberKey)=%%
AccountID %%=v(@accountID)=%%
LoyaltyID %%=v(@loyaltyID)=%%
GamePlayURI %%=v(@gamePlayURI)=%%
(Include common attributes as listed above.)
Need additional resources? Supporting documentation for this integration is available through your TSA. Reach out to them if you need reference materials beyond what's covered here.