Search

Are you looking for test card numbers?

Would you like to contact support?

Omnichannel icon

Payment-linked loyalty program

Offer a loyalty program without a separate loyalty card or app.

You can use customer recognition to make your existing loyalty program more frictionless for your customers by removing the need for a traditional loyalty card or app. In this tutorial, we'll explain how you can link your loyalty system to their customer profile. When they make a payment in your online or physical store, you can automatically recognize them, and award them with points, discounts, or a reward.

When you offer a payment-linked loyalty, you also give your customers an extra incentive to provide you their contact details, which you can also use to create a customer profile.

Before you begin

To use payment-linked loyalty, make sure that:

  1. You can already create customer profiles and recognize returning customers across your sales channels.
  2. You have a loyalty system that keeps track of customer registration, as well as other data such as points balance and rewards eligibility.

Online loyalty

When your customer makes a purchase in your web or in-app store, attempt to recognize them, and check whether they have already enrolled in your loyalty program.

From here, you can either ask them to register for your loyalty program, or check whether they are eligible for a loyalty reward, before continuing with the transaction.

Step 1: Recognize customer

Before making a purchase, your customer will provide you with their contact details, such as an email address or phone number (for example, when creating or signing in to their account, or through your guest checkout).

To recognize whether this is a returning customer:

Step 2: Request customer input

After you've determined if they are a returning customer, query your loyalty system database using the shopperEmail and check their loyalty program status. Next, present a relevant message in your UI:

  • If they are not a member of your loyalty program, this message should ask them to register.
  • If they are already a member, you could inform them how close they are to receiving a reward or, if they have enough points, ask them whether they want to redeem their reward.

Step 3: Continue with payment

Continue with the purchase by initiating a payment. Here is how you can make a payment for a customer shopperEmail john_smith@example.com with a correspondingshopperReference john_smith.

  1. Make a POST /payments request.

    Payments request
    {
        "amount": {
        "currency": "EUR",
        "value": 500
        },
        "reference": "YOUR_ORDER_NUMBER",
        "paymentMethod": {
            "type": "scheme",
            "encryptedCardNumber": "test_4111111111111111",
            "encryptedExpiryMonth": "test_03",
            "encryptedExpiryYear": "test_2030",
            "encryptedSecurityCode": "test_737"
        },
        "shopperReference": "john_smith",
        "returnUrl": "https://your-company.com/...",
        "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
    }

    The response includes:

    • pspReference: Our unique identifier for this payment.
    • resultCode: Authorised

    The following example shows a successful response with a PSP reference of 881468919096134D.

    {
        "pspReference": "881468919096134D",
        "resultCode": "Authorised"
    }
  2. In your loyalty system database, update the loyalty points in your record forshopperEmail john_smith@example.com.

Once you've set up a loyalty system for your online transactions you can do the same for in-store transactions.

In-store loyalty

There are two flows you can use to perform payment-linked loyalty using your point-of-sale integration.

  • Synchronous: Using data you receive from Adyen before the payment is initiated.

    With this flow, you use the data that you receive from Adyen to query your loyalty system database. You then present loyalty information, such as a points balance or a personalized message, to your customer while they are making their purchase.

  • Asynchronous: Using data you receive from a webhook notification after the payment has been processed.

    This flow requires less integration work, but you will not be able to present real-time loyalty information to your customer. You update your loyalty system at a later time with the information that you receive from notification webhooks.

To implement any of these flows, select a tab below:

Synchronous in-store loyalty

By using a synchronous loyalty flow, you'll be able to present your loyal customers with information such as points balance and redeemable rewards while they are making a purchase.

We'll explain how you can use your terminal's built-in touchscreen to interact with your customers. We'll cover how you can ask them to register in your loyalty program, present customized messaging, and inform them when they are due to receive a loyalty reward.

When your customer makes an in-store purchase, check whether they are registered in your loyalty program. From here, you can either ask them to register, or check whether they are eligible for a loyalty reward, before continuing with the transaction.

Step 1: Recognize customer

To determine whether your customer is a member of your loyalty program, attempt to recognize them with a card acquisition request.

When the customer makes an in-store purchase:

  1. Make a card acquisition request to recognize the customer.

    The example below shows how you would attempt to recognize a customer who is making a 10.99 EUR purchase.

    Card acquisition request
    {
    "SaleToPOIRequest": {
        "MessageHeader":{
            "ProtocolVersion":"3.0",
            "MessageClass":"Service",
            "MessageCategory":"Payment",
            "MessageType":"Request",
            "SaleID":"POSSystemID12345",
            "ServiceID":"0207111104",
            "POIID":"V400m-324688179"
        },
        "CardAcquisitionRequest": {
            "SaleData": {
                "SaleTransactionID": {
                    "TransactionID": "15890",
                    "TimeStamp": "2019-12-04T12:02:49.000Z"
                },
                "TokenRequestedType": "Customer"
            },
            "CardAcquisitionTransaction": {
                "TotalAmount": 10.99
            }
        }
    }
    }

    You receive a response that includes an AdditionalResponse object, with a base64-encoded string that you need to decode to get a JSON object, or a string of form-encoded key-value pairs. In our examples, we use form-encoded key-value pairs.

    The example response below includes an AdditionalResponse object.

    Card acquisition response
    {
    "SaleToPOIResponse": {
        "CardAcquisitionResponse": {
            "POIData": {
                "POITransactionID": {
                    "TimeStamp": "2019-12-04T12:02:49.000Z",
                    "TransactionID": "4rVu001575460969123"
                },
                "POIReconciliationID": "1000"
            },
            "SaleData": {
                "SaleTransactionID": {
                    "TimeStamp": "2019-12-04T12:02:49.000Z",
                    "TransactionID": "15890"
                }
            },
            "PaymentInstrumentData": {...},
            "Response": {
                "Result": "Success",
                "AdditionalResponse":"...shopperReference=john_smith&shopperEmail=john.smith@email.com..."
            }
        },
        "MessageHeader": {...}
    }
    }
  2. Check if the AdditionalResponse object contains a shopperReference.

    • If it contains a shopperReference, they are a returning customer. If you have previously stored the shopperEmail with Adyen, this is also provided in this response.
    • If it does not contain a shopperReference, the customer's card is not recognized.

      This usually means that the customer is new, and has not purchased with you before. However, they could also be a returning customer using a new card.

    To confirm, you can collect their email address, then check whether this matches a shopperEmail stored in your customer database:

    • If the email matches a shopperEmail in your database, they are a returning customer. Ask them if they want to save their new card. If they do, tokenize their new card using their shopperReference from your database when you make a payment.
    • If the email is not your database, they are a new customer. Proceed to step 2 to ask them to register them in your loyalty program.
  3. If you have recognized a returning customer, query your loyalty system database using the shopperEmail. Get information about whether the customer has already registered in your loyalty program, how many points they have, and if they are eligible for a reward.

Step 2: Request customer input

After you've determined if they are a new or returning customer, present a relevant message on the terminal screen:

Register loyalty member

If your customer is not a member of your loyalty program, you can register them directly from your Adyen terminal.

When you register a new loyalty member, we recommend collecting their email address. This makes it easier for you to link their online and in-store loyalty, as well as send them email updates. You can also use this email address to send them an e-receipt for their in-store transaction. If collecting an email address is not possible, you can collect their phone number, or another unique identifier for the customer instead.

To register a customer into your loyalty scheme:

  1. Make a GetConfirmation input request from your cash register, asking whether the customer wants to register for your loyalty program.

    The example below shows how you would present Would you like to join our loyalty program? on the terminal display, as well as the options Yes and No.

    GetConfirmation input request
    {
       "SaleToPOIRequest":{
          "MessageHeader":{
             "ProtocolVersion":"3.0",
             "MessageClass":"Service",
             "MessageCategory":"Payment",
             "MessageType":"Request",
             "ServiceID":"0207112310",
             "SaleID":"POSSystemID12345",
             "POIID":"V400m-324688179"
          },
          "InputRequest":{
             "DisplayOutput":{
                "Device":"CustomerDisplay",
                "InfoQualify":"Display",
                "OutputContent":{
                   "OutputFormat":"Text",
                   "PredefinedContent":{
                      "ReferenceID":"GetConfirmation"
                   },
                   "OutputText":[
                      {"Text":"Welcome stranger!"},
                      {"Text":"Would you like to join our loyalty program?"},
                      {"Text":"No"},
                      {"Text":"Yes"}
                   ]
                }
             },
             "InputData":{
                "Device":"CustomerInput",
                "InfoQualify":"Input",
                "InputCommand":"GetConfirmation",
                "MaxInputTime":30
             }
          }
       }
    }

    Your message is shown on the terminal display. The customer indicates whether they would like to register.

    When they are done selecting their option, you receive the input response that contains an Input.ConfirmedFlag. If this is true, proceed to the next step to register your customer to your loyalty program. Otherwise, you can continue processing the transaction.

    GetConfirmation input response
    {
      "SaleToPOIResponse": {
        "InputResponse": {
          "InputResult": {
            "Device": "CustomerInput",
            "InfoQualify": "Input",
            "Response": {
              "Result": "Success",
              "AdditionalResponse": "..."
            },
            "Input": {
              "ConfirmedFlag": true,
              "InputCommand": "GetConfirmation"
            }
          },
          "OutputResult": {
            "Device": "CustomerDisplay",
            "InfoQualify": "Display",
            "Response": {
              "Result": "Success"
            }
          }
        },
        "MessageHeader": {...}
      }
    }
  2. If the customer indicated that they would like to register, and you do not already have their email address, make a GetText input request from your cash register. This should ask the customer to enter their email address.

    The example GetText request below would present the message Enter your email address on the terminal display. An on-screen keyboard also appears on the terminal.

    GetText input request
    {
      "SaleToPOIRequest": {
        "MessageHeader": {
            "ProtocolVersion":"3.0",
            "MessageClass":"Service",
            "MessageCategory":"Payment",
            "MessageType":"Request",
            "SaleID":"POSSystemID12345",
            "ServiceID":"0207112311",
            "POIID":"V400m-324688179"
        },
        "InputRequest": {
          "DisplayOutput": {
            "Device": "CustomerDisplay",
            "InfoQualify": "Display",
            "OutputContent": {
              "OutputFormat": "Text",
              "PredefinedContent": {
                "ReferenceID": "GetText"
              },
              "OutputText": [
                {"Text": "Enter your email address"}
              ]
            }
          },
          "InputData": {
            "Device": "CustomerInput",
            "InfoQualify": "Input",
            "InputCommand": "TextString",
            "MaxInputTime": 120,
            "DefaultInputString": "name@domain.com"
          }
        }
      }
    }

    The customer enters their email address on the terminal. When they are done typing in their email address, you receive an input response, with the customer's email address provided in the Input.TextInput.

    The example below shows what this response would look like if the customer entered the email address john.smith@example.com.

    GetText input response
    {
      "SaleToPOIResponse": {
        "InputResponse": {
          "InputResult": {
            "Device":"CustomerInput",
            "InfoQualify":"Input",
            ...
            },
            "Input": {
              "TextInput":"john.smith@example.com",
              "InputCommand":"TextString"
            }
          },
          "OutputResult": {
            "Device":"CustomerDisplay",
            "InfoQualify":"Display",
            "Response": {
              "Result":"Success"
            }
          }
        },
        "MessageHeader": {...}
      }
    }
  3. Get the email address and include it when you continue with the payment.

    As a courtesy, you may want to send an email to your customer, confirming their registration in your loyalty program and explaining how it works.

Redeem loyalty reward

If your customer has earned a loyalty reward, you can use your Adyen terminal to inform them and give them the option to redeem their reward. If the customer agrees to redeem their reward, you can then adjust the value of the transaction before you make a payment.

To ask if a customer wants to redeem their loyalty points:

  1. Make a GetConfirmation input request, to ask your customer whether they would like to redeem their loyalty points with this transaction.

    The example below shows how you would present a prompt for a free coffee on the terminal display, asking the customer whether they would like to redeem it now.

    GetConfirmation input request
    {
       "SaleToPOIRequest":{
          "MessageHeader":{
             "ProtocolVersion":"3.0",
             "MessageClass":"Service",
             "MessageCategory":"Payment",
             "MessageType":"Request",
             "ServiceID":"0207112311",
             "SaleID":"POSSystemID12345",
             "POIID":"V400m-324688179"
          },
          "InputRequest":{
             "DisplayOutput":{
                "Device":"CustomerDisplay",
                "InfoQualify":"Display",
                "OutputContent":{
                   "OutputFormat":"Text",
                   "PredefinedContent":{
                      "ReferenceID":"GetConfirmation"
                   },
                   "OutputText":[
                      {"Text":"You've earned a free coffee!"},
                      {"Text":"Would you like to have it now?"},
                      {"Text":"No"},
                      {"Text":"Yes"}
                   ]
                }
             },
             "InputData":{
                "Device":"CustomerInput",
                "InfoQualify":"Input",
                "InputCommand":"GetConfirmation",
                "MaxInputTime":30
             }
          }
       }
    }

    Your message is shown on the terminal display. The customer indicates whether they would like to redeem their loyalty points for a reward.

    When they are done selecting their option, you receive the input response that contains an Input.ConfirmedFlag. If this is true, proceed to the next step to give the reward to your customer. Otherwise, continue processing the transaction.

    GetConfirmation input response
    {
      "SaleToPOIResponse": {
        "InputResponse": {
          "InputResult": {
            "Device": "CustomerInput",
            "InfoQualify": "Input",
            "Response": {
              "Result": "Success",
              "AdditionalResponse": "..."
            },
            "Input": {
              "ConfirmedFlag": true,
              "InputCommand": "GetConfirmation"
            }
          },
          "OutputResult": {
            "Device": "CustomerDisplay",
            "InfoQualify": "Display",
            "Response": {
              "Result": "Success"
            }
          }
        },
        "MessageHeader": {...}
      }
    }
  2. When a customer indicates they want to redeem their points, your cash register should calculate the redemption as a discount or partial payment. Continue to the next step to continue with the payment for the outstanding balance.

Step 3: Continue with payment

Continue with the purchase by making a payment request:

  1. Make a POST request from your cash register to initiate the payment. If you are registering a new customer for your loyalty program, also include parameters described in the Create customer profiles documentation.

    Here is how you can make a 10.99 EUR payment for a known customer.

    Terminal API request
    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"0207111105",
                "POIID":"V400m-324688179"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"15887",
                        "TimeStamp":"2019-12-04T12:02:49.000Z"
                    }
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":10.99
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TransactionID":"oLkO001528797935000",
                        "TimeStamp":"2019-12-04T12:02:49.000Z"
                    }
                }
            }
        }
    }

    You receive a response that includes an AdditionalResponse object, with a base64-encoded string that you need to decode to get a JSON object, or a string of form-encoded key-value pairs. In our examples, we use form-encoded key-value pairs.

    Payment response
    {
      "SaleToPOIResponse":{
        "MessageHeader":{...},
        "PaymentResponse":{
          "POIData":{
            "POITransactionID":{
              "TransactionID": "oLkO0012498220087567.991517998212382C"
            },
            ...
          },
          "Response":{
            "Result":"Success",
            "AdditionalResponse":"...shopperReference=john_smith&shopperEmail=john.smith@example.com..."
          },
          ...
        },
        "PaymentReceipt":{...}
      }
    }
  2. If the transaction is successful, update the customer's loyalty balance in your database to reflect their purchase.

You may also want to use a DisplayRequest to present a message on the terminal screen, welcoming them to your loyalty program, informing them of their points balance, or congratulating them on their loyalty reward.

Asynchronous in-store loyalty

As a simpler way of integrating payment-linked loyalty, you may prefer to use the data you receive webhook notifications. You then make all loyalty adjustments retrospectively. This is done by receiving a webhook notification, plugged directly into your CRM.

This requires less integration work, but this means that you will not be able to present real-time information to your customer while they're in your store (for example, to inform them of their loyalty balance, or let them know they are due for a reward). By using this flow, you will need to figure out a way of giving the customer a way of registering for your loyalty program, and recording this in your customer database.

To implement an asynchronous flow:

  1. Make a POST request from your cash register to initiate the payment. If you are creating a profile for a new customer, also include parameters described in the Create customer profiles documentation.

    Here is how you can make a 10.99 EUR payment for a known customer.

    Terminal API request
    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"0207111105",
                "POIID":"V400m-324688179"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TransactionID":"15887",
                        "TimeStamp":"2019-12-04T12:02:49.000Z"
                    }
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":10.99
                    }
                },
                "PaymentData":{
                    "CardAcquisitionReference":{
                        "TransactionID":"oLkO001528797935000",
                        "TimeStamp":"2019-12-04T12:02:49.000Z"
                    }
                }
            }
        }
    }

    If the payment was successful, you receive a payment response containing Result Success.

    Payment response
    {
      "SaleToPOIResponse":{
        "MessageHeader":{...},
        "PaymentResponse":{
          "POIData":{
            "POITransactionID":{
              "TransactionID": "oLkO0012498220087567.991517998212382C"
            },
            ...
          },
          "Response":{
            "Result":"Success",
            "AdditionalResponse":"...shopperEmail=john.smith@example.com..."
          },
          ...
        },
        "PaymentReceipt":{...}
      }
    }
  2. After the payment has been processed, Adyen sends a notification webhook to your server.

    AUTHORISATION notification
    {
    "notificationItems":[
      {
         "NotificationRequestItem":{
            "additionalData":{
               ...
               "shopperInteraction":"POS",
               "shopperEmail":"john.smith@example.com",
               "shopperReference":"john_smith"
            },
            "amount":{
               "currency":"EUR",
               "value":10.99
            },
             ...
            "eventCode":"AUTHORISATION",
            "merchantAccountCode":"YOUR_MERCHANT_ACCOUNT",
            "merchantReference":"YOUR_REFERENCE",
            "pspReference":"882589522806623K",
            "success":"true"
         }
      }
    ]}

    If your customer has been recognized this notification contains:

    • shopperReference: Your unique reference for this customer.
    • shopperEmail: The customer's email address.
  3. In your loyalty system database, update the loyalty points in your record forshopperEmail john_smith@example.com.

After you've adjusted their loyalty points, you may want to reach out to the customer (using an app, email, or other communication) to let them know their new points balance, or if they're eligible to redeem a reward.

Next steps