Balanced

How balanced bundles work

The default bundling strategy applies the desired action to the targeted items selecting them in order to ensure a balanced and even distribution across groups (i.e. all groups contribute equally to the single promotional bundles that are recursively identified by the algorithm).

To configure balanced bundles you just need to define the sorting logic within the sort object:

Key
Type
Required
Notes

type

String

If specified, must be "balanced".

sort

Object

Learn more here.

How the balanced algorithm works

  1. The items within each targeted group are sorted according to the sort.direction function applied to the sort.attribute numeric field. The groups are also sorted considering the same logic on the same attribute (adding up its value for all the group's items).

  2. The total quantity of units within each group is calculated by adding up the quantities of each item.

  3. The minimum quantity of units across all group Q is the bottleneck of the algorithm (i.e. Q is the number of balanced bundles that will be created).

  4. Starting from the top of the ordered list generated by the sorting, Q elements from each group are picked to be discounted, thus leading to Q discountable balanced bundles containing one item per group each.

Example

Let's assume that a rule's conditions define the following groups of line items:

The group labeled as t-shirts contains 4 line items for a total of 10 units:

[
  {
    "id": "mnptRLjoXJ",
    "type": "line_items",
    "quantity": 1,
    "unit_amount_cents": 10000,
    "total_amount_cents": 10000,
    "sku": {
      "id": "zTdkkFXdgN",
      "code": "TSHIRT01"
    }
  },
  {
    "id": "jndtDLsoAM",
    "type": "line_items",
    "quantity": 2,
    "unit_amount_cents": 5000,
    "total_amount_cents": 10000,
    "sku": {
      "id": "xCKdTcQFQH",
      "code": "TSHIRT02"
    }
  },
  {
    "id": "AfetSAsqbY",
    "type": "line_items",
    "quantity": 3,
    "unit_amount_cents": 3000,
    "total_amount_cents": 9000,
    "sku": {
      "id": "meKHSeNbyN",
      "code": "TSHIRT03"
    }
  },
  {
    "id": "sjyTdAfrgY",
    "type": "line_items",
    "quantity": 4,
    "unit_amount_cents": 2000,
    "total_amount_cents": 8000,
    "sku": {
      "id": "uKtHCCJpWn",
      "code": "TSHIRT04"
    }
  }
]

Let's consider a simple action that uses only the required parameters to be applied to a set of balanced bundles. The following action applies a 20% discount to all the possible bundles that can be created from the groups above, provided that they contain at least one item per group, prioritizing the items with the higher total amount:

"actions": [
  {
    "type": "percentage",
    "selector": "order.line_items.sku",
    "groups": [ "mugs", "polos", "t-shirts" ],
    "bundle": {
      "sort": {
        "attribute": "total_amount_cents",
        "direction": "desc"
      }
    },
    "value": 0.2
  }
]

1. Sorting

The items of the group are sorted based on their total amount, from the highest to the lowest. On top of that, the groups are sorted based on the sum of the total amount of each group's item, according to the same logic:

SKU
Group
Quantity
Item total amount
Group total amount

POLO02

polos
5

30000

37000

POLO01

polos
1

7000

37000

TSHIRT01

t-shirts
1

10000

37000

TSHIRT02

t-shirts
2

10000

37000

TSHIRT03

t-shirts
3

9000

37000

TSHIRT04

t-shirts
4

8000

37000

MUG02

mugs
1

4000

10000

MUG01

mugs
3

3000

10000

MUG03

mugs
1

3000

10000

TSHIRT01 ranks higher than TSHIRT02 within the t-shirts group even if they have the same total amount (10000) because this is how they are listed in the payload. The same happens to MUG01 and MUG03 within the mugs group. The elements of the polos groups rank higher than the elements of the t-shirts group even if the two groups have the same total amount (37000) because this is how they are listed in the actions.groups array.

2. Total quantity of units

The total quantity of units within each group is:

Group
Units
mugs
5
polos
6
t-shirts
10

3. Bottleneck

The group with the lowest total number of units limits the number of bundles that will be created. In this case the mugs group is the bottleneck, thus the discount will be applied to 5 bundles.

4. Bundles of items to be discounted

We can now pick 5 elements from each group, following the ordered list from top to bottom:

SKU
Group
Quantity
Discounted total amount

POLO02

polos
5

24000

TSHIRT01

t-shirts
1

8000

TSHIRT02

t-shirts
2

8000

TSHIRT03

t-shirts
2

4800

MUG02

mugs
1

3200

MUG01

mugs
3

2400

MUG03

mugs
1

2400

This is equivalent to picking one item per group while mugs units (our bottleneck) last, thus leading to the following 5 bundles to be discounted:

Bundle #1

SKU
Group
Quantity
Discounted unit amount

POLO02

polos
1

4800

TSHIRT01

t-shirts
1

8000

MUG02

mugs
1

3200

Bundle #2

SKU
Group
Quantity
Discounted unit amount

POLO02

polos
1

4800

TSHIRT02

t-shirts
1

4000

MUG01

mugs
1

800

Bundle #3

SKU
Group
Quantity
Discounted unit amount

POLO02

polos
1

4800

TSHIRT02

t-shirts
1

4000

MUG01

mugs
1

800

Bundle #4

SKU
Group
Quantity
Discounted unit amount

POLO02

polos
1

4800

TSHIRT03

t-shirts
1

2400

MUG01

mugs
1

800

Bundle #5

SKU
Group
Quantity
Discounted unit amount

POLO02

polos
1

4800

TSHIRT03

t-shirts
1

2400

MUG03

mugs
1

2400

Wrap-up

The results above confirm some general highlights of the balanced bundling strategy:

  • An equal contribution of each group to the bundle formation is the distinctive feature. It's a quite strict requirement that leaves some items not discounted (in the analyzed case, 1 unit of POLO01, 1 unit of TSHIRT03, and 4 units of TSHIRT04), prioritizing the ones to discount based on the desired sorting logic.

  • Only the elements of the group(s) with the minimum number of total units will be all discounted, and the total number of bundles identified will be equal to the number of total units of the group(s) that with minimum number of total units (in the analyzed case, the mugs group which has a total number of units equal to 5 and turns out to be the bottleneck of the algorithm).

  • The total number of discounted units is given by the number of total units of the group with the minimum number of total units multiplied by the total number of groups (in the analyzed case, 5 * 3 = 15).

Last updated