How to calculate the profitability of BOGOF and multibuy promotions

Multibuy promotions and Buy One, Get One Free or BOGOF deals are widely used in ecommerce. Here's how to understand which one is most profitable for your product based on its margin.

How to calculate the profitability of BOGOF and multibuy promotions
Picture by Cottonbro, Pexels.
17 minutes to read

Buy One Get One Free or BOGOF promotions, and similar multibuy promotions that provide a free item when customers purchase over a specified amount are very common in retailing, including in ecommerce.

They can be used to meet a variety of sales objectives, including winning a sale, or encouraging customers to purchase more than they otherwise would. However, selecting the right multibuy discount to use depends on your objective and the product margin. It’s something that confuses many marketers.

In this really simple project I’ll show you how you can create a Python function to calculate the profitability of different multibuy promotions. We’ll go over some commonly seen multibuy promotions and look at their profitability and see how they compare to offering a standard percentage discount. It’s dead easy.

What are the benefits of multibuy promotions?

Not all multibuy promotions work in the same way. The Buy One, Get One Free or BOGOF deal is designed to increase conversion rate by purchasing a product, rather than to increase basket size or AOV. It’s a popular one when brands want to encourage customers to switch to a different brand or trial a product.

Other multibuy deals, such as the 3 for 2 and any others where you buy more than a single unit, are primarily designed to make customers buy more units, which aids increasing the average order value. Compared to other product promotions, such as markdown sales, the use of multibuy deals does have some notable pros and cons.

Benefit Description
They can increase AOV Most multibuy deals can increase AOV, either by encouraging customers to buy a product they otherwise wouldn't have bought, or by persuading them to buy a larger number of units.
The discount is based on product cost While you end up giving away discount in the form of free products, you're only giving a way what the free products cost you to purchase, not their full retail value.
Discounts only go to bulk buyers Depending on the multibuy discount used, you can also use promotions to provide a discount only to those who purchase more items. Rather than discounting every order and quantity, as you would if you just marked the price down.
Offers have a high perceived value Since you're giving away that may cost you a fraction of its retail price, customers can perceive the discount to be greater than some cash discounts.

The multibuy promotion you select will depend on your aims. For example, do you want to drive sales of a new product, or encourage customers to trial a more profitable alternative? If so, then you may wish to select one with a low barrier to entry and a high perceived discount.

Do you want to use a multibuy promotion to increase basket size and AOV? If so, you’re better off examining the average number of units purchased for the given product (ideally using an approach such as Fisher Jenks Natural Classification, rather than the average itself) and then setting the threshold just ahead of the average.

For example, maybe you sell trout fishing flies and the average person buys 3 of each type. Offering a multibuy deal of Buy Five, Get One Free or slightly greater might push the average quantity up and offset what you give away in discount?

Create a multibuy or BOGOF calculator

To allow you to analyse the profitability of a range of different multibuy promotion scenarios, we’ll create a Python function to do the maths for us. This is quite long, but the maths inside it is pretty simple. The function takes four arguments: unit_sale_price_net (the retail price of the item), unit_cost_price_net (the cost price of the item), buy_x_units (the number of units the customer needs to buy to qualify, i.e. 1 for a BOGOG), and get_x_units_free (the number of units they get free).

Using these four variables, we can then calculate the gross profit and percentage margin made on each unit sold at full price, and the gross profit and margin made when we’re giving away free units. We’ll also compare what we’d get if we’d sold the same volume of units at full price and look at the perceived discount the customer gets.

def buy_x_get_x_free(unit_sale_price_net, unit_cost_price_net, buy_x_units, get_x_units_free):
    """Return data on the profitability of a Buy X Get X Free promotional offer. 
    
    Args: 
        unit_sale_price_net (float): The net selling price of a single unit
        unit_cost_price_net (float): The net cost price of a single unit
        buy_x_units (int): The number of units being purchased
        get_x_units_free (int): The number of additional units provided free of charge
    
    Returns: 
        data (dict): Dictionary containing a breakdown of costs, revenue, and profit for the
        given promotional offer scenario. 
    """
    
    # Promotion details
    units_received = (buy_x_units + get_x_units_free)
    
    # Margin data for a single unit sold at full price
    unit_gross_profit = unit_sale_price_net - unit_cost_price_net
    unit_gross_margin_pc = (unit_gross_profit / unit_sale_price_net) * 100

    # Margin data if same volume sold at full price
    unpromoted_sale_price_net = unit_sale_price_net * units_received
    unpromoted_cost_price_net = unit_cost_price_net * units_received    
    
    # Margin data if units are sold in this promotion    
    promotional_sale_price_net = unit_sale_price_net * buy_x_units
    promotional_cost_price_net = unit_cost_price_net * units_received
    promotional_gross_profit = promotional_sale_price_net - promotional_cost_price_net
    promotional_gross_margin_pc = (promotional_gross_profit / promotional_sale_price_net) * 100
    promotional_cost = get_x_units_free * unit_cost_price_net
    promotional_saving_net = (unpromoted_sale_price_net - promotional_sale_price_net)
    promotional_saving_pc = ((unpromoted_sale_price_net - promotional_sale_price_net) / unpromoted_sale_price_net) * 100
    
    data = {
        # Margin data for a single unit sold at full price
        'unit_sale_price_net': unit_sale_price_net,         
        'unit_cost_price_net': unit_cost_price_net, 
        'unit_gross_profit': unit_gross_profit, 
        'unit_gross_margin_pc': unit_gross_margin_pc,

        # Promotion details
        'buy_x_units': buy_x_units, 
        'get_x_units_free': get_x_units_free, 
        'units_received': units_received, 
        
        # Margin data if all units were sold at full price
        'unpromoted_sale_price_net': unpromoted_sale_price_net, 
        'unpromoted_cost_price_net': unpromoted_cost_price_net,
        'unpromoted_gross_profit': unit_gross_profit, 
        'unpromoted_gross_margin_pc': unit_gross_margin_pc,        
        
        # Margin data if units are sold in this promotion
        'promotional_sale_price_net': promotional_sale_price_net, 
        'promotional_cost_price_net': promotional_cost_price_net,
        'promotional_gross_profit': promotional_gross_profit, 
        'promotional_gross_margin_pc': promotional_gross_margin_pc,
        'promotional_cost': promotional_cost,
        'promotional_saving_net': promotional_saving_net,
        'promotional_saving_pc': promotional_saving_pc
    }
    return data

Selling at full price

First, we’ll see what happens when we sell an item at full price. We’ll use a net sale price of £10 and a unit cost price of £4 in all the examples. Running the function shows that this gives us a gross profit of £6 per unit and a 60% gross margin.

Clearly, while some people will be happy to purchase at full price, due to the concept of Price Elasticity of Demand, offering multibuy promotions or similar discounts can encourage customers to purchase more items in return for a free item. We can, therefore, expect higher sales but a lower profit per unit when we run a multibuy promotion.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=1, get_x_units_free=0)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 1,
 'get_x_units_free': 0,
 'units_received': 1,
 'unpromoted_sale_price_net': 10,
 'unpromoted_cost_price_net': 4,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 10,
 'promotional_cost_price_net': 4,
 'promotional_gross_profit': 6,
 'promotional_gross_margin_pc': 60.0,
 'promotional_cost': 0,
 'promotional_saving_net': 0,
 'promotional_saving_pc': 0.0}

Buy One, Get One Free

First, let’s look at the classic Buy One, Get One Free or BOGOF promotion. Purchasing a single unit for £10 gets the customer two units worth £20 for the price of one, providing a perceived promotional saving of 50% or £10 off.

The retailer sees the gross margin percentage fall from the original 60% to just 20% and the gross profit fall from £6 on a single unit sold at full price to £2, because they’re providing an item worth £4 for free.

Clearly, a Buy One, Get One Free promotion is only going to be profitable if the perceived discount the customer gets encourages many more customers to purchase the item than otherwise would, effectively generating a higher gross profit at a much lower margin.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=1, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 1,
 'get_x_units_free': 1,
 'units_received': 2,
 'unpromoted_sale_price_net': 20,
 'unpromoted_cost_price_net': 8,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 10,
 'promotional_cost_price_net': 8,
 'promotional_gross_profit': 2,
 'promotional_gross_margin_pc': 20.0,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 50.0}

Buy One, Get Two Free

A Buy One, Get Two Free promotion means that the customer pays £10 for a single unit and then gets two additional units for free, giving them a saving of £20 and a perceived 66.66% discount.

This offer isn’t profitable for the retailer, because the £8 promotional cost is £2 higher than the £4 in gross profit generated from the sale, resulting in a £2 loss for selling at a -20% gross margin.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=1, get_x_units_free=2)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 1,
 'get_x_units_free': 2,
 'units_received': 3,
 'unpromoted_sale_price_net': 30,
 'unpromoted_cost_price_net': 12,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 10,
 'promotional_cost_price_net': 12,
 'promotional_gross_profit': -2,
 'promotional_gross_margin_pc': -20.0,
 'promotional_cost': 8,
 'promotional_saving_net': 20,
 'promotional_saving_pc': 66.66666666666666}

Buy Two, Get One Free (or 3 for 2)

A Buy Two, Get One Free multibuy promotion is the same as the popular 3 for 2 promotion. This means the customer pays for two units and gets the third one free, in this case spending £20 and getting a £10 saving on £30 worth of products, effectively providing 33.33% or one third off.

This offer has a promotional cost of £4 (the price of the single free unit given away) and generates £8 in gross profit from costs of £12, resulting in the percentage gross margin falling from 60% to 40%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=2, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 2,
 'get_x_units_free': 1,
 'units_received': 3,
 'unpromoted_sale_price_net': 30,
 'unpromoted_cost_price_net': 12,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 20,
 'promotional_cost_price_net': 12,
 'promotional_gross_profit': 8,
 'promotional_gross_margin_pc': 40.0,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 33.33333333333333}

Buy Three, Get One Free

For a Buy Three, Get One Free promotion the customer gets a perceived saving of 25% off and we see the gross margin percentage fall from our original 60% down to 46.66%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=3, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 3,
 'get_x_units_free': 1,
 'units_received': 4,
 'unpromoted_sale_price_net': 40,
 'unpromoted_cost_price_net': 16,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 30,
 'promotional_cost_price_net': 16,
 'promotional_gross_profit': 14,
 'promotional_gross_margin_pc': 46.666666666666664,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 25.0}

Buy Four, Get or One Free

A Buy Four, Get One Free deal is the same as offering 25% off the product price (but only when the customer buys four units). This sees the gross margin percentage fall from 60% to 50%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=4, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 4,
 'get_x_units_free': 1,
 'units_received': 5,
 'unpromoted_sale_price_net': 50,
 'unpromoted_cost_price_net': 20,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 40,
 'promotional_cost_price_net': 20,
 'promotional_gross_profit': 20,
 'promotional_gross_margin_pc': 50.0,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 20.0}

Buy Five, Get One Free

A Buy Five, Get One Free promotion gives the customer a perceived discount of 16.66% off when they buy five units. This sees gross margin percentage fall from 60% to 52% for our product.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=5, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 5,
 'get_x_units_free': 1,
 'units_received': 6,
 'unpromoted_sale_price_net': 60,
 'unpromoted_cost_price_net': 24,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 50,
 'promotional_cost_price_net': 24,
 'promotional_gross_profit': 26,
 'promotional_gross_margin_pc': 52.0,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 16.666666666666664}

Buy Six, Get One Free

The Buy Six, Get One Free deal gives the customer a perceived discount of 14.28% off when they purchase six items and sees the gross margin percentage drop from 60% to 53.33%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=6, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 6,
 'get_x_units_free': 1,
 'units_received': 7,
 'unpromoted_sale_price_net': 70,
 'unpromoted_cost_price_net': 28,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 60,
 'promotional_cost_price_net': 28,
 'promotional_gross_profit': 32,
 'promotional_gross_margin_pc': 53.333333333333336,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 14.285714285714285}

Buy Seven, Get One Free

A Buy Seven, Get One Free promotion gives a perceived discount of 12.5% off when purchasing 7 items and sees gross margin percentage fall from 60% to 54.28%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=7, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 7,
 'get_x_units_free': 1,
 'units_received': 8,
 'unpromoted_sale_price_net': 80,
 'unpromoted_cost_price_net': 32,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 70,
 'promotional_cost_price_net': 32,
 'promotional_gross_profit': 38,
 'promotional_gross_margin_pc': 54.285714285714285,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 12.5}

Buy Eight, Get One Free

A Buy Eight, Get One Free promotion results in a perceived discount of 11.11% off when buying 8 units and sees the gross margin percentage fall from 60% to 55%.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=8, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 8,
 'get_x_units_free': 1,
 'units_received': 9,
 'unpromoted_sale_price_net': 90,
 'unpromoted_cost_price_net': 36,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 80,
 'promotional_cost_price_net': 36,
 'promotional_gross_profit': 44,
 'promotional_gross_margin_pc': 55.00000000000001,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 11.11111111111111}

Buy Nine, Get One Free

Finally, we can check out what happens when we do a Buy Nine, Get One Free multibuy promotion. As you have now hopefully managed to figure out, this is the same as a 10% off markdown, but will only offer the discount to those who purchase 9 units.

buy_x_get_x_free(unit_sale_price_net=10, unit_cost_price_net=4, buy_x_units=9, get_x_units_free=1)
{'unit_sale_price_net': 10,
 'unit_cost_price_net': 4,
 'unit_gross_profit': 6,
 'unit_gross_margin_pc': 60.0,
 'buy_x_units': 9,
 'get_x_units_free': 1,
 'units_received': 10,
 'unpromoted_sale_price_net': 100,
 'unpromoted_cost_price_net': 40,
 'unpromoted_gross_profit': 6,
 'unpromoted_gross_margin_pc': 60.0,
 'promotional_sale_price_net': 90,
 'promotional_cost_price_net': 40,
 'promotional_gross_profit': 50,
 'promotional_gross_margin_pc': 55.55555555555556,
 'promotional_cost': 4,
 'promotional_saving_net': 10,
 'promotional_saving_pc': 10.0}

Matt Clarke, Wednesday, July 20, 2022

Matt Clarke Matt is an Ecommerce and Marketing Director who uses data science to help in his work. Matt has a Master's degree in Internet Retailing (plus two other Master's degrees in different fields) and specialises in the technical side of ecommerce and marketing.

Marketing Analytics in Spreadsheets

Learn how to ensure clean data entry and build dynamic dashboards to display your marketing data.

Start course for FREE