Create Product Bundles Without The App
- Duplicate the live theme
- Actions + Edit Code
- Sections product-template.liquid
- Search for unless product equals empty
- 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 %}
- 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>
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 = ‘530×530’ -%}
<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 %}
- 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 %}