Maximizing Loyalty Points

Author

Christian Jaehnert

Published

December 8, 2023

Situation at Checkout

Imagine yourself at the checkout counter of a supermarket with a long line of unpatient customers behind you. The register shows your total as €31.28.

Source: DALL•E

In this situation, which coupon of the following would you choose in order to maximize your loyalty points with the supermarket (normally, you get one point for every cent)?

  • Triple points for a purchase of 15 Euros or more

  • 5,000 extra points for a purchase of 20 Euros or more

  • Quintuple points for a purchase of 25 Euros or more

  • 10,000 extra points for a purchase of 30 Euros or more

Would you be tempted to select the coupon offering 10,000 extra points, simply because the number of extra points is impressively large and you’ve met the required threshold? Alternatively, is the quintuple points option a smarter choice? Quick calculations could resolve this dilemma, but remember, a queue of customers is already eyeing you impatiently from behind. Their expectant gazes add pressure to your decision-making process.

Oh yes, these coupons are actually available at a supermarket right now. I didn’t make that up. 😉
But I experienced this situation firsthand.

Today, we’ll delve into a graphical solution of the question and, as an added benefit, examine a calculated decision tree designed to guide you in selecting the most suitable coupon for this particular scenario. Lets jump into the quick and practical analysis!

Identifying the Best Coupon

First, let’s create a dataframe populated with values ranging from €0 to €100, in increments of €0.01. As mentioned already, the number of loyalty points typically awarded corresponds to the payment amount in cents. Then, I will define the four coupons as variables by applying the math of the mechanic. At the end, I determine the best coupon for each purchase value and store it in another variable.

Click here to unhide/hide the code.
wert <- tibble(purchase_value = seq(0.01, 100,0.01))
wert <- wert %>% 
  mutate(points = purchase_value * 100) %>% 
  mutate(points_5000_from_20 = if_else(purchase_value >=20, points + 5000, points),
         points_10000_from_30 = if_else(purchase_value >=30, points + 10000, points),
         points_5x_from_25 = if_else(purchase_value >= 25, 5*points, points),
         points_3x_from_15 = if_else(purchase_value >=15, 3*points, points)) %>% 
  mutate(best_value = pmax(points_5000_from_20, points_10000_from_30, points_5x_from_25, points_3x_from_15))

Lets have a glimpse on the data frame.

Rows: 10,000
Columns: 7
$ purchase_value       <dbl> 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0…
$ points               <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
$ points_5000_from_20  <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
$ points_10000_from_30 <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
$ points_5x_from_25    <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
$ points_3x_from_15    <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…
$ best_value           <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15…

That’s all we need. I’ve now plotted the loyalty points against purchase value to visually illustrate how each coupon performs. Let’s take a graphical look at the effectiveness of each offer!

In the plot, the dashed line represents loyalty points earned per purchase value without using a coupon.

Now, let’s delve into the coupon details – it’s quite intriguing!

Surprise: The coupon offering ‘10,000 extra points for purchases over €30’ (indicated by the red line) is not advantageous for any purchase value. 💡 Hence, one might consider discarding this coupon right away, especially if new coupon booklets are regularly available.

The coupons providing ‘Triple points for a purchase of 15 Euros or more’ (blue line) and ‘5,000 extra points for purchases over €20’ (green line) benefits customers only within a very narrow spending range of €5. Let’s take a brief look at the intersection around €25, where both lines intersect. Is it irrelevant which coupon one uses there? (Keep in mind, this post is a goldmine for those on a mission to supercharge their loyalty points! 🚀😉)

The answer: Not at all! The zoom shows that. Also, just before the next threshold, the coupon ‘5,000 extra points for purchases over €20’ is preferable. At a spend value of €24.99 this coupon gives 2 loyalty points more 😉

From €25 on the coupon ‘Quintuple points for a purchase of 25 Euros or more’ is the best option!

Decision Tree

That’s of course all too complicated to remember. Therefore, as a bonus, we now turn to the decision tree.

Click here to unhide/hide the code.
library(rpart)
library(rpart.plot)


tree <- rpart(best_option ~ purchase_value, 
              data = wert , 
              method = "class")


rpart.plot(tree, fallen.leaves = TRUE, under = TRUE, type = 5, legend.y = NA)

Have fun cutting the decision tree out and tucking them into your wallet 😃

Until next time! 🙋‍♂️