Shopify Blog

Create Product Bundles Without The App - 2021 Easy Shopify Tutorial!

Andrew Durot
8 min read

Product Bundles are a great way for businesses to increase sales by offering more than one product. This way, you can add more popular products to less popular ones as a bundle to be sold together. As such, you also increase the sales of less popular ones.

Product bundles are several individual goods or services that are sold to consumers as one combined package. Sometimes called "package deals," product bundles are generally made up of complementary items or, less frequently, similar items.

usually we offer discounted price for bundle products so the customers are more likely to make a purchase.

  1. Duplicate the live theme
  2. Actions + Edit Code
  3. Sections  product-template.liquid
  4. Search for unless product equals empty
  5. Paste the following code just above that line

{% include 'product-bundle-collection', bundle_list_title: 'Choose a bundle that works best for you', columns: 3 %}
  1. Add a new snippet - product-bundle-card.liquid

Remove all the content and paste the following code


<style>

  .product-bundle{

background-color: #FFFFFF!important;

    border-radius: 8px!important;

    box-shadow: 0px 0px 10px 0px #c4c4c4 !important;

    padding: 20px 0;

  }

 

  .product-bundle:hover{

    border: 4px solid #d33;

  }

  .product-bundle__title{

    font-size: 1.5em;

    text-align: center;

    padding: 10px;

  }

  .product-bundle__image{

width: 100%;

  }

 

  .product-bundle__meta{

    text-align: center;

    font-size: 1.3em;

    padding: 15px 0;

  }

 

  .product-bundle__form{

text-align: center;

  }

  .product-bundle__submit{

    width: 80%;

    height: 50px;

    font-size: 1.3em;

    background-color: #d33;

    color: #fff;

    font-weight: bold;

    border-radius: 30px;

  }

 

  .product-bundle-selector-wrapper{

    width: 100%;

    padding: 10px;

  }

 

  .product-bundle-selector-wrapper select{

    width: 100%;

  }

 

  .product-bundle-form__variants{

    display: none;

  }

 

  .product-bundle {

    background-color: #ffffff !important;

    border-radius: 8px!important;

    box-shadow: 0px 0px 10px 0px #c4c4c4 !important;

    color: #282829;

    padding: 20px 0;

  }

</style>

 

<div class="product-bundle {% unless product.available %} product-bundle--sold-out{% endunless %}">

  <a class="product-bundle__link" href="{{ product.url | within: collection }}">

    <div class="h4 product-bundle__title">{{ product.title }}</div>

    <img class="product-bundle__image" src="{{ product.featured_image.src | img_url: '500x', scale: grid_image_scale }}" alt="{{ product.featured_image.alt }}">

    <div class="product-bundle__meta">

        {% include 'product-bundle-price' %}

    </div>

  </a>

   <form action="/cart/add" method="post" enctype="multipart/form-data" class="product-bundle__form product-form--hide-variant-labels" >

     {% unless product.options.size == 1 and product.variants[0].title == 'Default Title' %}

     {% for option in product.options_with_values %}

     <div class="product-bundle-selector-wrapper product-bundle-form__item">

       <select class="product-bundle-single-option-selector product-bundle-form__input" id="SingleOptionSelector-{{ forloop.index0 }}" data-index="option{{ forloop.index }}">

         {% for value in option.values %}

         <option value="{{ value | escape }}"{% if option.selected_value == value %} selected="selected"{% endif %}>{{ value }}</option>

         {% endfor %}

       </select>

     </div>

     {% endfor %}

     {% endunless %}

 

     <select name="id" class="product-bundle-form__variants">

       {% for variant in product.variants %}

       {% if variant.available %}

       <option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">

         {{ variant.title }}

       </option>

       {% else %}

       <option disabled="disabled">{{ variant.title }} - {{ 'products.product.sold_out' | t }}</option>

       {% endif %}

       {% endfor %}

     </select>

 

      <input type="hidden" id="Quantity" name="quantity" value="1" min="1" class="product-form__input" pattern="[0-9]*">

 

      <input type="submit" value="Add to cart" class="product-bundle__submit" />

  </form>

</div>

 

 

7. Add a new snippet - product-bundle-collection.liquid

Remove all the content and paste the following code

 

 

<style>

 

.bundle_collection__title{

  text-align:center;

  padding: 20px;

  font-size: 1.8em;

  color: #111;

}

.bundle_item {

  float: left;

  width: 100%;

  margin-bottom: 20px;

}

@media only screen and (min-width: 750px) {

  .bundle_item {

    {% if columns == 4 %}

    width: 25%;

margin-bottom: 0;

    {% else %}

    {% if columns == 3 %}

    width: 33%;

    margin-bottom: 0;

    {% else %}

    width: 50%;

    margin-bottom: 20px;

    {% endif %}

    {% endif %}

    padding-left: 30px;

  }

}

</style>

{% assign bundle_tag = ""  %}

{% for tag in product.tags %}

{% if tag contains "bundle-" %}

{% assign bundle_tag = tag  %}

{% endif %}

{% endfor %}

<script>

  var bundleProducts = [];

</script>

{% assign has_bundle = false  %}

{% for product in collections.all.products %}

{% if product.tags contains bundle_tag %}

{% assign has_bundle = true  %}

{% endif %}

{% endfor %}

{% if has_bundle %}

<div class="page-width" id="Collection" style="margin-top: 50px;">

  <p class="bundle_collection__title"> {{ bundle_list_title }} </p>

  {%- assign grid_item_width = 'medium-up--one-third' -%}

  {%- assign image_size = '530x530' -%}

 

  <div class="bundle_collection">

  {% assign has_bundle = false  %}

  {% for product in collections.all.products %}

{% if product.tags contains bundle_tag %}

    <script>

      bundleProducts.push({{ product | json }});

    </script>

    <div class="bundle_item" id="{{ product.id }}">

      {% include 'product-bundle-card' %}

    </div>

    {% endif %}

  {% endfor %}

  </div>

</div>

<script>

  var bundleProductMapping = {};

  bundleProducts.forEach(function(p){

    if (!bundleProductMapping[p.id])

      bundleProductMapping[p.id] = {};

    p['variants'].forEach(function(v){

      bundleProductMapping[p.id][v.title] = {

        "price": v.price/100.0,

        "compare_at_price": v. compare_at_price/100.0,

        "id": v.id

      }

    })

  })

 

   $(document).ready(function(){

    $('.product-bundle-single-option-selector').change(function(e){

      var selectedVariants = [];

 

      $(e.target).closest('.product-bundle__form').find('.product-bundle-single-option-selector').each(

        function(el){

          selectedVariants.push($(this).val());

        }

      )

      var variantsString = selectedVariants.join(" / ");

      var productId = $(e.target).closest('.bundle_item').attr('id');

      var variant = bundleProductMapping[productId][variantsString];

      if (variant){

        var finalPrice = variant.compare_at_price || variant.price ;

        $(e.target).closest('.product-bundle').find('.product-bundle__meta .product-bundle-price__price').html('$'+finalPrice);

        $(e.target).closest('.product-bundle').find('.product-bundle__meta .product-bundle-price__sale').html('$'+variant.price);

        $(e.target).closest('.product-bundle__form').find(".product-bundle__submit").removeAttr("disabled");

        $(e.target).closest('.product-bundle__form').find('[name="id"]').val(variant.id);

      }else{

        $(e.target).closest('.product-bundle').find('.product-bundle__meta .product-bundle-price__price').html("");

        $(e.target).closest('.product-bundle').find('.product-bundle__meta .product-bundle-price__sale').html("");

        $(e.target).closest('.product-bundle__form').find(".product-bundle__submit").attr("disabled", "disabled")

      }

    })

  })

</script>

{% endif %}

 

 

8. Add a new snippet - product-bundle-price.liquid

Remove all the content and paste the following code

  

<style>

  .product-bundle__price_title{

font-size: 1em;

    font-weight: bold;

text-align: center;

padding: 10px;

    color: #666;

  }

 

  {% if compare_at_price > price %}

  .product-bundle-price__price{

    color: #bbb;

    font-size: 1em;

  }

  {% else %}

  .product-bundle-price__price{

    color: #111;

    font-size: 1.1em;

  }

  {% endif %}

  .product-bundle-price__sale{

    color: #111;

    font-weight: bold;

    font-size: 1.1em;

  }

 

</style>

{% if product.title %}

  {%- assign compare_at_price = product.compare_at_price -%}

  {%- assign price = product.price -%}

  {%- assign price_varies = product.price_varies -%}

  {%- assign available = product.available -%}

{% else %}

  {%- assign compare_at_price = 1999 -%}

  {%- assign price = 1999 -%}

  {%- assign price_varies = false -%}

  {%- assign available = true -%}

{% endif %}

 

{%- assign money_price = price | money -%}

 

<div class="product-bundle__price_title"> Bundle Price: </div>

{% if compare_at_price > price %}

  {% if price_varies %}

    <span class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>

    <s class="product-bundle-price__price">{{ compare_at_price | money }}</s>

    <span class="product-bundle-price__price product-bundle-price__sale">

      {{ money_price }}

    </span>

  {% else %}

    <span class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>

    <s class="product-bundle-price__price">{{ compare_at_price | money }}</s>

    <span class="product-bundle-price__price product-bundle-price__sale">

      {{ money_price }}

    </span>

  {% endif %}

{% else %}

 

  {% if price_varies %}

    <span class="product-bundle-price__price">{{ money_price }}</span>

  {% else %}

    <span class="visually-hidden">{{ 'products.product.regular_price' | t }}</span>

    <span class="product-bundle-price__price">{% if product.variants.size > 1 %}from {% endif %}{{ money_price }}</span>

  {% endif %}

{% endif %}

Next we will show how to create the bundle products. For example we would like to create some bundle products for one of my products called. first we will need to create a tag for this product and use the same tag for all the bundle products.

make sure the tag name is prefixed with the word bundle and a dash.

also make sure the tag is different for different types of products.

then we need to duplicate the product to make the bundled products. for each duplicated bundle product we need to change the title and update the prices for each variants.

now we have created three bundle products let's check out the product page.

scroll down you can see the bundled products section.

if we select different variants for the bundle product we will see the price is updated

finally let's try to add one bundle into our shopping cart.

Leave a comment

Guides

Leave a comment