4  Cross sell

Cross sell recommends additional product purchases to the customers. It is a powerful customer development approach that can be complemented with loyalty programmes or other incentive programmes. There are many ways to cross sell; we will focus on segmented collaborative filtering product recommendation approach.

For ‘segment’ part of this section, we will use RFM segmentation and province from the transactions data, which can complement geomarketing approaches.

4.1 Setting it up

In order to cross sell, we need to have two main ingredients:

  • Customer segments

  • Product purchases of the segments

Initially, we compile a list of products the segments have purchased. For the customers within those segments, if they have not purchased products that the segment has purchased, recommend that product.

Then, remove previously purchased products by the customers from the recommendations. Let’s start by creating that dataframe.

4.1.1 Customers’ previously purchased products

df_previously_purchased = df_transactions |>
  distinct(customer_id, stock_code)

df_previously_purchased |> 
  head() |> 
  print.data.frame()
  customer_id stock_code
1       16010    22811AP
2       16010    21713AP
3       16010    22927AP
4       16010    20802AP
5       16010    22052AP
6       16010    22705AP

4.1.2 Set customer segments

# Create segment by concatenating
df_segments = df_transactions |>
  distinct(customer_id, province) |> 
  inner_join(df_customer_rfm_type) |> 
  unite('segment',
        province, customer_type) |> 
  distinct()

df_segments |> 
  head() |> 
  print.data.frame()
  customer_id            segment
1       16010    DKI Jakarta_New
2       17700 DKI Jakarta_Lapsed
3       13675 DKI Jakarta_Lapsed
4       17451    DKI Jakarta_New
5       17404    DKI Jakarta_New
6       16881   DKI Jakarta_Lost

4.1.3 Purchased products for each segment

df_segment_purchased = df_previously_purchased
  inner_join(df_segments) |> 
  distinct(segment, stock_code)

df_segment_purchased |> 
  head() |> 
  print.data.frame()
          segment stock_code
1 DKI Jakarta_New    22811AP
2 DKI Jakarta_New    21713AP
3 DKI Jakarta_New    22927AP
4 DKI Jakarta_New    20802AP
5 DKI Jakarta_New    22052AP
6 DKI Jakarta_New    22705AP

4.1.4 Product recommendations for each customer

df_cross_sell = df_segments |> 
  inner_join(df_segment_purchased) |> 
  anti_join(df_previously_purchased)

df_cross_sell |> 
  head() |>
  print.data.frame()
  customer_id         segment stock_code
1       17451 DKI Jakarta_New    22811AP
2       17404 DKI Jakarta_New    22811AP
3       16184 DKI Jakarta_New    22811AP
4       18242 DKI Jakarta_New    22811AP
5       16661 DKI Jakarta_New    22811AP
6       16233 DKI Jakarta_New    22811AP

Quiz

  • This will result in a lot of recommendations. What are some ways you can each recommendation a score or a ranking for priorities? (hint: when defining df_segment_purchased, distinct() flattens all purchases as ‘equals’)

  • Should the previously purchased units be really be removed from recommendations? What scenarios can you think of where recommending previously purchased products is desirable?