Solving Magento

Solutions for Magento E-Commerce Platform

by Oleg Ishenko

Magento Bundle Product Type (Part 1)

Bundle is a composite Magento product type with many useful properties, most prominent of which, in my opinion, is its flexibility. Bundles are usually understood as two or more products sold together. Magento’s Bundle product type does that and more. It has features similar to that of other composite types, Grouped and Configurable, but also differs from them significantly.

For example, product grouping is achievable in a simple form with the Grouped product type. Bundle type, however, allows more complex product combinations. There is a two-tier grouping in Bundles. The first tier is comprised of options. Options are grouping entities that have one or several selections (second tier), and each selection is tied to one product. Also, unlike Grouped products, whose children are added to cart and ordered as single products, Bundles behavior in this regard is more like that of Configurable: in quotes and orders Bundles are represented by parent and child items.

When buying a Bundle a customer must configure it but in a different way than a Configurable. Configurable products have one or more attributes whose values can be selected and each selection option is linked to one child product (Simple, Virtual, or Downloadable). Bundles, on the other hand, have no configurable attributes, and their options can offer more than one product to select from. Also, an option can be configured to accept more than one selected product.

Bundle product management in the back-end

With that introduction, let’s look how a Bundle product is composed in the shop back-end. The examples I am using are available in the Magento sample dataset, which can be downloaded here. The product we are about to take a look at has SKU “VGN-TXN27N/BW”. It is a simple bundle – a laptop computer sold together with a warranty. Customers can choose from several warranty options or select none. This is how general properties of a bundle look like in the back-end:


Figure 1. General properties of a bundle product.

The first feature of the Bundle type which attracts attention is that some of the product properties can be set to Dynamic or Fixed. Bundle attributes of this kind are:

  • SKU – when set to Fixed the attribute behavior is the same as with other product types. The Dynamic setting, however, changes the way the SKU is transfered to quote and order items. In this case it is composed of the base SKU of the bundle and of the SKUs of the selected bundle options.
  • WeightFixed weight allows a value to be set to this attribute to bundle products directly. With a Dynamic weight setting a weight value to bundles is impossible. Instead, weight is calculated from the selected bundle options.
  • PriceFixed price allows bundles to have a base price (and taxes applied to it). In this case it is possible to set surcharges to bundle options which should influence the total price when selected. Dynamic price setting disables bundle price and tax attributes. The total price is composed from the product prices of the option items. These prices are different from the option surcharges defined on the bundle level, because they are read from the sub-product price attributes.

As a composite type, Bundle has an extra tab where its components are defined. Switch to he Bundle Items tab.


Figure 2. Options a bundle product.

In the top you see a drop-down select box that lets you define if the options are shipped separately or together. This attribute’s value will be transfered along with other product data to quote and order items. When creating a shipment in the back-end you’ll notice that the form allows splitting bundle order items in separate shipments if their parent bundle product has separate shipping enabled.

The “Bundle Items” group contains bundle options. The first option represents a laptop computer. It is a required one and customers can’t change its default quantity of 1. The second option represents a warranty. It includes three warranty products whose quantity is also fixed. These products have different prices which will be visible to the customer in the front-end. The warranty option is not required, which allows a customer to choose not buying any (there will be a radio button labeled “None” in the front-end). On a product details page these options look like this:


Figure 3. Options a bundle product in the front-end.

Since this bundle has a Dynamic price, the prices next to each item are taken from the respective products. Changing the selection affects the price shown under “Price as configured”. While customers can’t alter the quantity of individual options, the quantity of the bundle as a whole (see input field “Qty” next to the “Add to Cart” buton) can be changed just like any other product’s.

Creating a Bundle product in Magento

To take a deeper look at the possibilities offered by Magento’s Bundles, let’s create a product of our own. This will be a desktop computer, and customers should be able to select its parts. In the back-end under Catalog > Manage Products click the “Add Product” button. In the next step leave the “Attribute Set” selection at Default – it doesn’t play a defining role like with the Configurable type. Select Bundle Product under the “Product Type” and click “Continue”.

In the General tab set the attributes to the following values:

  • Name: Custom Desktop Computer
  • SKU: Dynamic, cdcomputer
  • Weight: Dynamic
  • Status: enabled
  • Visibility: Catalog, Search

The Tax Class attribute is disabled at the moment because the bundle price is dynamic by default. In our example, we set the Price attribute to Fixed. This will enable the Tax Class attribute and we set its value to Taxable Goods.

Switch to the Prices tab to see that the Price attribute’s model is set to Fixed and enter 200 as the starting price. As I’ve already mentioned, a bundle with a fixed price can have option surcharges whose selection can influence the total price. This works similar to the pricing options of a Configurable product: they are defined on the parent product’s level and are not connected to the prices of the child products. In the Prices tab we have to select another required attribute: Price View. It has two options:

  • Price Range means that the bundle price is displayed in the front-end as two values. The lower one equals the total price of the cheapest option selection. The higher one represents the priciest combination.
  • As low as displays only one value which is the price of the cheapest combination of the bundle’s options.

In our example, we set the price display to Price Range.

To finish the product creation, fill out other required options, such as Description and Short Description. Also, assign a product to a website in the Websites (“Main Website”) tab and to a Category (“Electronics > Computers > Build Your Own”). In the Inventory tab make sure that the Stock Availability is set to In Stock. With this formalities done, click “Save and Continue Edit”, which should create a bundle product without options. To add them, switch to the Bundle Items tab.

Clicking the “Add New Option” button displays a bundle option form. In this form we can set the following options:

  • Default Title – option title which will be displayed next to it in the front-end. This value is assigned to the default store view of the main website. If you need to set different option titles in different stores, switch to the respective store, and an additional input field will appear where you can enter a store-specific value. In our example, the first option is called “CPU”
  • Input Type – here you can define what input elements should control the item selection within the option form. If your option can have only one item selected, you must choose either a Drop-down or Radio button. Setting Check box or Multiple select makes it possible for a customer to select more than one item. For our “CPU” option we select a Drop-down input type.
  • Is Required – this property defines if the option must be configured before adding the product to cart. If it is set to yes, the front-end form will use Java-Script validation to ensure that a value is set. The Bundle product type methods will check it server-side as well. We set our “CPU” option’s property Is Required to yes.
  • Position – you can use this property if you need to specify a particular order in which bundle options must be displayed. The sorting is done in an ascending order. Enter 10 for our option. In order for the “CPU” option to be displayed the first, we will have to set higher values to the other options’ positions.

To add product items to our option, click “Add Selection”. This will display the following grid (click “Search” to load products into it):


Figure 4. Products available for option selection.

In order to be set as a bundle selection item a product must fulfill the following conditions:

  • Its property required_options must be set to 0 or null. Products with this property set to 1 are either composite products or have options that must be configured before a product can be converted into a quote item. This applies to Downloadable products with links that can be purchased separately and to Simple products with a required custom option.
  • The product’s type must be listed among the “types allowed to bundle”. In the standard Magento configuration these types are Simple and Virtual. This is defined in the Mage_Bundle module’s config file:

    Listing 1. Allowed product type configuration, /app/code/core/Mage/Bundle/etc/config.xml, line 103

To find a specific product for your selection item, you can set filters to refine the list. In our case, it makes sense to select CPUs in the “Attrib. Set Name”, which would produce a list of CPU products. Checking a checkbox in each row adds the respective product to the selection after you click the “Add Selected Product(s) to Option” button. Optionally, you can enter a value into the “Qty to Add” box which will be transferred as Default Value to the selection. If you don’t do it, the Default Value will be set to 1. You can control the following properties of selection items:

  • Price and Price Type – these two properties can be manipulated only if a bundle product has the Fixed price model. In case of the Dynamic price model, selection items use prices set for their respective simple products. With a “fixed” price we can set selection prices to act as surcharges to the base price of the bundle. The selection price in turn can be either Fixed or Percent. In the former case the selection price value is applied as is. In our example, setting 50 as a fixed selection price would result in the total bundle price of $250 if this option is selected ($200 plus $50, $200 being the base bundle product price). If the surcharge is set to Percent, then entering a value of 30 would result in the total price of $260 ($200 plus 30% of $200). For more details on the price calculations see Listing 4.
  • Default Value – as I’ve already mentioned, this property corresponds to the quantity of the selection product that is added to cart when a customer selects this option.
  • User Defined Qty – if set to yes, customers can choose their own quantity. You must be careful with that. If a fixed price bundle has an option with surcharge 0, customers can potentially get any number of this product for free. If there is a non-zero surcharge then the total price is calculated with respect to the customer-supplied quantity. Note that this property is only available for options of Drop-down or Radio Buttons type.
  • Position – similar to the position property of bundle options, this one can be used to sort selection items in an ascending order.
  • Default – you can use this property to make one of the selection items appear pre-selected when the options from is loaded.

I’ve set values to the Price and Price Type properties of the CPU selection items. The first two have fixed $50 and $40 surcharges, while the third and the fourth items have 30% and 20% surcharges. Presently the options form of our bundle product looks like this (I’ve circled the percent calculated surcharges red):


Figure 5. Selection items with surcharges.

While a Magento Bundle with just one option is a perfectly valid product, the same result is achievable with a Configurable product: one option to configure, one product to buy. Bundles are useful with more than one option. Let’s add a second one to our test product.

This time we are adding an option of type Checkbox so that a customer can choose more than one selection item. We name this option “RAM”, set it as not required and add three products of the “RAM” attribute set. After that the Bundle Items tab should look like this:


Figure 6. Two bundle options and their selection products.

Since the second option is of the Checkbox type, its selection items don’t have property User Defined Qty. The front-end options form has no such input for the RAM products:


Figure 7. Checkbox type option.

Front-end display of the Bundle type products

The Mage_Bundle module defines a layout update configuration that manages the front-end output of bundle products. This configuration is contained in file bundle.xml which you can find under /app/design/frontend/base/default/layout folder assuming your shop doesn’t use an alternative bundle layout updates file provided by a custom design package or theme. The bundle layout updates can be grouped into the following four categories:

  • rendering of bundle options in the product detail view,
  • displaying bundle prices in product lists,
  • rendering bundle products as shopping cart items,
  • rendering bundle products as order, shipment, creditmemo, or invoice items.


Rendering of bundle options in the product detail view

Just like with the Grouped or Configured types, the Bundle type defines a custom form within the product details page, where it outputs options and selections defined for the bundle product. The layout configuration is as follows:

<PRODUCT_TYPE_bundle translate="label" module="bundle">
    <label>Catalog Product View (Bundle)</label>
    <reference name="head">
        <action method="addItem"><type>skin_js</type><name>js/bundle.js</name></action>
    <reference name="">
        <block type="bundle/catalog_product_view_type_bundle" name=""
                            as="product_type_data" template="bundle/catalog/product/view/type/bundle.phtml">
            <action method="addPriceBlockType">
            <block type="bundle/catalog_product_price" name="bundle.prices" as="bundle_prices"
                <action method="setMAPTemplate">
    <reference name="">
        <block type="bundle/catalog_product_view_type_bundle" name=""
                            as="type_bundle_options" template="bundle/catalog/product/view/type/bundle/options.phtml">
            <action method="addRenderer">
            <action method="addRenderer">
            <action method="addRenderer">
            <action method="addRenderer">
        <action method="insert"><block></block></action>
    <reference name="">
        <remove name="product.tierprices" />
        <block type="bundle/catalog_product_view" name="bundle.tierprices" as="tierprices"
                            before="-" template="bundle/catalog/product/view/tierprices.phtml"/>
        <block type="cataloginventory/qtyincrements" name=""
                            before="-" template="cataloginventory/qtyincrements.phtml"/>
    <reference name="product.clone_prices">
        <action method="addPriceBlockType">

Listing 2. Layout configuration of the bundle product type options form, /app/design/frontend/base/default/layout/bundle.xml, line 199

This configuration updates several areas in the product view page:

  1. Sets a customized price block for the Bundle product type. The block bundle/catalog_product_price is responsible for outputting the bundle price in one of the two pre-configured formats: “as low as” or “from/to”. The former displays the price of the cheapest possible bundle option configuration, the latter displays highest and lowest possible prices.
  2. Outputs option selection forms using the bundle/catalog_product_view_type_bundle block and custom renderers for different options types: drop-down list, multi-select list, radio buttons, and checkboxes.
  3. Alters the product options’ bottom wrapper block by replacing the standard tier prices block with one that uses a custom bundle tier prices template, and adds a block for displaying quantity increments settings. A few words about quantity increments: it is possible to sell products in predefined increments, like by a dozen. In this case any quantity that is not a whole number of dozens (e.g., not a 12, 24, 36, etc) will not be accepted. The quantity increments block shows what quantity increment is set for a product, if quantity increments are enabled for the said product.
  4. References product.clone_prices to set a block outputting the final configured price that uses a bundle-specific template.

Note that this configuration also injects a JavaScript file bundle.js (/skin/frontend/base/default/js/bundle.js) that adds interactivity to the options form. Similar to the configurable.js of the Configurable product type, bundle.js is responsible for updating options and selections elements when a customer configures a bundle. The JavaScript object declared in this file is instantiated in the bundle options template:

<?php $_product = $this->getProduct() ?>

<?php if($_product->isSaleable()): ?>
<script type="text/javascript">
        var bundle = new Product.Bundle(<?php echo $this->getJsonConfig() ?>);
<?php endif; ?>

Listing 3. Instantiating a JavaScript bundle configuration, /app/design/frontend/base/default/template/bundle/catalog/product/view/type/bundle.phtml, line 28

The parameter used to create an instance of the Product.Bundle object is a JSON encoded array of bundle options, selections, and other settings. It is produced by method getJsonConfig of the Mage_Bundle_Block_Catalog_Product_View_Type_Bundle class. An example of this object created for one of the products from the sample data, SKU “mycomputer”, is as follows (some options and selections elements omitted for brevity):

                                        "name":"Apevia Black X-Cruiser Case ATX Mid-Tower Case (Default)",

Figure 8. Output of a sample JSON of a bundle product configuration.

The configuration object is composed of the bundle’s options and their selections. The current product, “mycomputer” has 5 options (only 1 shown in the example above). Each of the options is an array of three elements:

  • title – the title of the option
  • isMulti – a flag indicating if the option is represented by list of checkboxes or a multiselect list.
  • selections – an array composed of the option’s selection items.

The selections array gets data from the option’s internal property selections, which contains instances of Mage_Catalog_Model_Product objects representing product items associated with the bundle option. These objects are extended with properties specific to bundle selection items, such as customQuantity, priceType, etc. The prices of the selection items are calculated by method getSelectionFinalTotalPrice() of the Mage_Bundle_Model_Product_Price class:

public function getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
    $multiplyQty = true, $takeTierPrice = true)
    if (is_null($selectionQty)) {
        $selectionQty = $selectionProduct->getSelectionQty();

    if ($bundleProduct->getPriceType() == self::PRICE_TYPE_DYNAMIC) {
        $price = $selectionProduct->getFinalPrice($takeTierPrice ? $selectionQty : 1);
    } else {
        if ($selectionProduct->getSelectionPriceType()) { // percent
            $product = clone $bundleProduct;
                array('product' => $product, 'qty' => $bundleQty)
            $price = $product->getData('final_price') * ($selectionProduct->getSelectionPriceValue() / 100);

        } else { // fixed
            $price = $selectionProduct->getSelectionPriceValue();

    if ($multiplyQty) {
        $price *= $selectionQty;

    return min($price,
        $this->_applyGroupPrice($bundleProduct, $price),
        $this->_applyTierPrice($bundleProduct, $bundleQty, $price),
        $this->_applySpecialPrice($bundleProduct, $price)

Listing 4. Calculating a bundle selection price (surcharge), /app/code/core/Mage/Bundle/Model/Product/Price.php, line 424.

This method checks the bundle product’s price type first. If the bundle’s price model is dynamic, then the selection item surcharge is set to the price of the selection product. Otherwise the system calculates the surcharge from the selection settings. If the bundle price model is “fixed” selection item surcharges are defined either as fixed amounts or as percentages of the bundle product’s price. In the latter case the system has to get a price from the bundle product and apply catalog rules if there are any matching ones. To do that, a clone of the bundle product is created and its property final_price gets a value. A catalog_product_get_final_price event is dispatched that triggers an observer of the Mage_CatalogRule module, which adjusts the price of the cloned object is necessary. The selection item’s price is then calculated according to the percentage value set for that item.

Besides the arrays of options and selection the JSON configuration includes the following information:

  • selected – an array of pre-configured options if any are defined for the bundle product.
  • bundleIdentity_id of the bundle product;
  • priceFormat – price formatting settings;
  • basePrice – bundle product’s price (for “fixed price” bundles only);
  • priceType – bundle price type, 0 for “DYNAMIC” and 1 for “FIXED”;
  • specialPrice – special price if any is set for the bundle product’s special_price attribute;
  • includeTax – tax price part inclusion as defined in the shop configuration;
  • isFixedPricetrue if the bundle price type is “FIXED”;
  • isMAPAppliedDirectlytrue if a Minimum Advertise price can be applied to the product.


Displaying bundle prices in product lists

Product lists may consist of products of different types including bundles. The layout updates defined in the Mage_Bundle module ensure that in such cases bundle prices are displayed correctly. To achieve that, a block of type Mage_Bundle_Block_Catalog_Product_Price is injected into product list blocks in handles such as:

  • catalog_category_default, block product_list,
  • catalog_category_view, block product_list,
  • catalog_category_layered, block product_list,
  • catalog_product_compare_index, block,
  • catalogsearch_result_index, block search_result_list,
  • catalogsearch_advanced_result, block search_result_list,
  • tag_product_list, block search_result_list,
  • tag_customer_view, block search_result_list,
  • default, blocks wishlist_sidebar and catalog_product_price_template,
  • catalog_product_view, block catalog.product.related,
  • PRODUCT_TYPE_simple, block,
  • checkout_cart_index, block checkout.cart.crosssell.

For more details on the configuration of the bundle price block injections see the bundle.xml file lines 35 – 117.

The bundle price block uses a template file bundle/catalog/product/price.phtml. The template is responsible for outputting all possible bundle price configurations, which is influenced by the following settings:

  • bundle price model: dynamic or fixed,
  • price display mode: “from/to” or “as low as”,
  • tax display configuration: with tax, without tax, or both.

The same price block and template are used in bundle product detail page as defined in the configuration in Listing 2.

Rendering bundle products as shopping cart items

Displaying composite products in a shopping cart requires a custom item renderer block. Bundle shopping cart items may contain one or several configured options, each having one or several (in case of multi-select options) products. Here is an example of such bundle configuration in a shopping cart (compare the view to that of a simple product, a cell phone):


Figure 9. A bundle and a simple product in a cart.

Note that the last option of the bundle cart item, “Peripherals”, has multiple selected products. In this example both cart items are outputted using the same template checkout/cart/item/default.phtml. But since the bundle item employs a custom block class, Mage_Bundle_Block_Checkout_Cart_Item_Renderer, it is displayed with all its configured options.

You will find the layout configuration for bundle cart items in file bundle.xml lines 146 – 193.

Rendering bundle products as order, shipment, creditmemo, or invoice items

A similar task of rendering a custom output for bundle items must be performed in item lists of orders, shipments, creditmemos, and invoices. This is the task of the Mage_Bundle_Block_Sales_Order_Items_Renderer. The templates it uses are bundle-specific. They can be found under bundle/sales/order in your template folder. This is how a bundle order item is rendered in an order review page in customer account:bundle_order

Figure 10. A bundle and a simple product items in an order item list.

The layout updates dealing with bundle order items rendering are defined in bundle.xml lines 295 -360.


This has been the first of two posts on Magento’s Bundle product type. We have discussed the main features of bundle products in Magento and looked at how they are created and managed in the back-end. We’ve also talked about layout updates introduced by the Mage_Bundle module and specifics of bundle option display in the front-end. In the next post we will look deeper at the functionality of the Bundle product type class as well as other classes representing bundle options and selections entities.

16 thoughts on “Magento Bundle Product Type (Part 1)

  1. Pingback: Magento Bundle Product Type (Part 2) | Solving Magento

  2. Pingback: Magento Bundle Product Type Tutorial | Solving Magento

  3. Pingback: Magento Downloadable Product Type (Part 2) | Solving Magento

  4. Hi,
    With this products it’s possible that when one of required item product is not available (without stock) all the product can’t buy?

    • Hi Cristina,

      If a bundle option is set to “required” and that option’s product is not available, then the entire bundle becomes not salable. If options of a bundle are not “required”, then the bundle is salable as long as at least one option is available.

      Simply put, make all bundle options required – then if one item gets out of stock the bundle becomes not available.

  5. sir i am new in magento. i want to create custom build own cumputer. there should module like first bundle product load and then next bundle product and then add to to get bundle item in separate page?

  6. is it possible to bring the name of the products through to the price range. By modifying price.phtml in some way?

    eg. From: $1 per duck To: $5 per chicken.

  7. Hi,
    Thank you for the great post.
    I have some bundle products with some simple products (with long names) bundled in to them. Is it possible to have the SKU or any other attribute of those simple products show up in bundle product dropdown instead of the the name of the simple products? should I make some changes in the bundle.xml file?

    Any help would be really appreciated.
    Thank you

  8. Great article! Quick question. I’m trying to figure out if Bundle Products will work for my needs.

    My products are magazines subscriptions to three different publications. Pricing depends on whether a customer subscribes to 1, 2 or all 3 mags, in addition to whether they subscribe for 1, 2 or 3 years.

    My pricing structure is like this:
    – For a 1 year subscription to one publication, the price is $32.95.
    – For a 2 year subscription to one publication, or 2 1-year subscriptions to 2 of the publications, the price is $55.90 ($27.95 each).
    – For a 3 year subscription to one pub, or a 1-year to each of the three, the cost is $68.85 ($22.95).

    Furthermore, any other purchase for more than 3 total years equals $22.95 per year. So for example, if someone orders 2 years of pub A, and 2 years of pub B, they have committed to 4 total years X $22.95 = $91.80

    Can this kind of calculation be set up using Bundle products? Or Configurable? Or Group? Or am I going to need some custom Javascript to generate my own form? I would like to make this as simple as possible for the customer. I picture 3 checkboxes where the customer decides which publications they want, then a drop down menu where they choose 1, 2 or 3 years, and based on their selections, the pricing is calculated.

    Then there is the issue of shipping addresses. I’d like each magazine subscription to appear in the shopping cart as a separate item, so that a customer could assign different shipping addresses to each if they want.

    Thanks for your help!

  9. Hi there, I’m getting the strangest thing on my site.

    I’m trying to used the “Fixed” price type so I can specify custom prices for my bundle items. When I create the parent product, I add the minimum amount of details and save the product.

    I then go back in and add my bundle products… The strange thing is that there’s no “Price” column for each item. When I save the whole product, the price type switches to “Dynamic”… what’s happening?

  10. Hello, I was so happy to find your site. I (by sheer conincidence) have my bundle product set up exactly as you described. I have a simple product as the “base” and have it required – this is the laptop. So this is the minimum price that will always display. Then I have the peripherals like RAM, HDD etc added as options. These also have their own prices (different prices for customer groups) and inventory. When the user selects an upgrade the price increases. It works pretty well… *except* I cannot figure out how to make a special or sale price display here. Essentially if the base price (of the simple item) is on sale, I want to display the strike-through old price and then the sale price… Is this even possible?! I know you are busy but I would be forever grateful if you could answer!

  11. Hi, how do you apply a discount to a bundle product so it appears as a total discount on price in product catalog please?

  12. Hello. We have an Athlete Box on our website that allows the customer to choose 5 items to receive monthly at a discount. They can mix and match available products and numbers as long as the total order comes out to 5 items. Right now all items come across individually in the backend. I would like to create a single line item for the athlete box so there is one product that goes into the order database. Would it be better to use bundled, grouped or configurable to do this?

Leave a Reply to uday Cancel reply

Your email address will not be published. Required fields are marked *

Theme: Esquire by Matthew Buchanan.