Skip to content
Tiered Quantity Discounts - Free Tutorial
Browse other ways to boost conversion rate & profit

Tiered Quantity Discounts - Free Tutorial

In this tutorial, we add section block for a tiered quantity selector with discounts displayed. This upgrade can boost your AOV and conversion rate by making the discounts front and center while also simplifying their buying process.

Compatible Themes: This code should work on all free Shopify themes (Dawn, Refresh, Craft, Studio, Publisher, Crave, Origin, Taste, Colorblock, Sense, Ride, Spotlight).

 

Update main-product.liquid

    {%- when 'tiered_quantity_selector' -%}
      {% render 'tiered-quantity-selector-custom', block: block, section: section %}
    {
      "type": "tiered_quantity_selector",
      "name": "Tiered Quantity Selector",
      "limit": 1,
      "settings": [
        {
          "type": "header",
          "content": "Option 1 Settings"
        },
        {
          "type": "text",
          "id": "option_1_label",
          "label": "Option 1 Label",
          "default": "1 Pack"
        },
        {
          "type": "number",
          "id": "option_1_quantity",
          "label": "Option 1 Quantity",
          "default": 1
        },
        {
          "type": "range",
          "id": "option_1_discount_percentage",
          "label": "Option 1 Discount Percentage",
          "default": 0,
          "min": 0,
          "max": 100
        },
        {
          "type": "checkbox",
          "id": "option_1_badge_enable",
          "label": "Enable Badge for Option 1",
          "default": false
        },
        {
          "type": "text",
          "id": "option_1_badge_text",
          "label": "Option 1 Badge Text",
          "default": "Most Popular"
        },
    
        {
          "type": "header",
          "content": "Option 2 Settings"
        },
        {
          "type": "text",
          "id": "option_2_label",
          "label": "Option 2 Label",
          "default": "3 Pack"
        },
        {
          "type": "number",
          "id": "option_2_quantity",
          "label": "Option 2 Quantity",
          "default": 3
        },
        {
          "type": "range",
          "id": "option_2_discount_percentage",
          "label": "Option 2 Discount Percentage",
          "default": 10,
          "min": 0,
          "max": 100
        },
        {
          "type": "checkbox",
          "id": "option_2_badge_enable",
          "label": "Enable Badge for Option 2",
          "default": true
        },
        {
          "type": "text",
          "id": "option_2_badge_text",
          "label": "Option 2 Badge Text",
          "default": "Most Popular"
        },
    
        {
          "type": "header",
          "content": "Option 3 Settings"
        },
        {
          "type": "text",
          "id": "option_3_label",
          "label": "Option 3 Label",
          "default": "5 Pack"
        },
        {
          "type": "number",
          "id": "option_3_quantity",
          "label": "Option 3 Quantity",
          "default": 5
        },
        {
          "type": "range",
          "id": "option_3_discount_percentage",
          "label": "Option 3 Discount Percentage",
          "default": 20,
          "min": 0,
          "max": 100
        },
        {
          "type": "checkbox",
          "id": "option_3_badge_enable",
          "label": "Enable Badge for Option 3",
          "default": false
        },
        {
          "type": "text",
          "id": "option_3_badge_text",
          "label": "Option 3 Badge Text",
          "default": "Most Popular"
        },
    
        {
          "type": "header",
          "content": "General Settings"
        },
        {
          "type": "checkbox",
          "id": "show_quantity_label",
          "label": "Show Quantity Selector Label",
          "default": true
        },
        {
          "type": "text",
          "id": "quantity_label_text",
          "label": "Quantity Selector Label Text",
          "default": "Select Quantity"
        },        
        {
          "type": "text",
          "id": "per_unit_label",
          "label": "Per Unit Label",
          "default": "unit"
        },
        {
          "type": "checkbox",
          "id": "show_strikethrough",
          "label": "Show Strikethrough Pricing",
          "default": true
        },
        {
          "type": "checkbox",
          "id": "show_total_pricing",
          "label": "Show Total Pricing",
          "default": true
        },
        {
          "type": "checkbox",
          "id": "show_per_unit",
          "label": "Show Per Unit Pricing",
          "default": true
        },
        {
          "type": "checkbox",
          "id": "show_savings_labels",
          "label": "Show Savings Labels (All)",
          "default": true
        },
        {
          "type": "checkbox",
          "id": "show_zero_percent_savings",
          "label": "Show 0% Savings Label",
          "default": true
        },
        {
          "type": "header",
          "content": "Formatting Settings"
        },
        {
          "type": "range",
          "id": "border_radius",
          "label": "Border Radius",
          "default": 0.5,
          "min": 0,
          "max": 2,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "range",
          "id": "option_bottom_spacing",
          "label": "Option Bottom Spacing",
          "default": 2.5,
          "min": 1,
          "max": 5,
          "step": 0.1,
          "unit": "rem"
        },        
        {
          "type": "range",
          "id": "label_font_size",
          "label": "Label Font Size",
          "default": 1.7,
          "min": 1,
          "max": 3,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "range",
          "id": "compare_price_font_size",
          "label": "Compare Price Font Size",
          "default": 1.3,
          "min": 0.5,
          "max": 2,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "range",
          "id": "final_price_font_size",
          "label": "Final Price Font Size",
          "default": 1.5,
          "min": 0.5,
          "max": 2,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "range",
          "id": "per_unit_font_size",
          "label": "Per Unit Price Font Size",
          "default": 1.0,
          "min": 0.5,
          "max": 2,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "color",
          "id": "text_color_unselected",
          "label": "Button Text Color (Unselected)",
          "default": "#121212"
        },
        {
          "type": "color",
          "id": "text_color_selected",
          "label": "Selected Button Text Color",
          "default": "#FFFFFF"
        },
        {
          "type": "color",
          "id": "selected_button_bg_color",
          "label": "Selected Button Background Color",
          "default": "#121212"
        },
        {
          "type": "color",
          "id": "savings_text_color",
          "label": "Savings Label Text Color",
          "default": "#ffffff"
        },
        {
          "type": "range",
          "id": "savings_label_font_size",
          "label": "Savings Label Font Size",
          "default": 1.1,
          "min": 0.5,
          "max": 1.5,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "color",
          "id": "savings_bg_color",
          "label": "Savings Label Background Color",
          "default": "#334FB4"
        },
        {
          "type": "color",
          "id": "badge_bg_color",
          "label": "Badge Background Color",
          "default": "#e33e3e"
        },
        {
          "type": "range",
          "id": "badge_font_size",
          "label": "Badge Font Size",
          "default": 1.0,
          "min": 0.5,
          "max": 2,
          "step": 0.1,
          "unit": "rem"
        },
        {
          "type": "color",
          "id": "badge_font_color",
          "label": "Badge Font Color",
          "default": "#ffffff"
        }
      ]
    },

Create new liquid file tiered-quantity-selector-custom.liquid

{% assign product_form_id = 'product-form-' | append: section.id %}
{% assign base_price = product.selected_or_first_available_variant.price %}

<div class="tiered-quantity-selector" {{ block.shopify_attributes }}>
  <style>
    .tiered-quantity-options {
      --selected-bg-color: {{ block.settings.selected_button_bg_color }};
      --savings-text-color: {{ block.settings.savings_text_color }};
      --savings-bg-color: {{ block.settings.savings_bg_color }};
      --border-radius: {{ block.settings.border_radius }}rem;
      --option-bottom-spacing: {{ block.settings.option_bottom_spacing }}rem;
      --compare-price-font-size: {{ block.settings.compare_price_font_size }}rem;
      --final-price-font-size: {{ block.settings.final_price_font_size }}rem;
      --per-unit-font-size: {{ block.settings.per_unit_font_size }}rem;
      --label-font-size: {{ block.settings.label_font_size }}rem;
      --text-color-unselected: {{ block.settings.text_color_unselected }};
      --text-color-selected: {{ block.settings.text_color_selected }};
      --savings-label-font-size: {{ block.settings.savings_label_font_size }}rem;

      --badge-bg-color: {{ block.settings.badge_bg_color }};
      --badge-font-size: {{ block.settings.badge_font_size }}rem;
      --badge-font-color: {{ block.settings.badge_font_color }};
    }

    .tiered-quantity-selector {
      margin: 1em 0;
    }

    .tiered-quantity-options {
      display: flex;
      gap: 1em;
      margin-top: 0.7rem;
      flex-wrap: wrap;
      align-items: stretch;
    }

    .tiered-option-wrapper {
      position: relative;
      display: flex;
      flex: 1;
      flex-direction: column;
      align-items: center;
    }

    .tiered-option {
      cursor: pointer;
      border: 1px solid #ccc;
      padding: 0.5em;
      text-align: center;
      transition: all 0.3s;
      background: #fff;
      font-size: var(--pricing-font-size);
      color: var(--text-color-unselected);
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      border-radius: var(--border-radius);
      position: relative;
      padding-bottom: var(--option-bottom-spacing);
      overflow: hidden;
      width: 100%;
    }
    .tiered-option--active {
      background: var(--selected-bg-color);
      color: var(--text-color-selected);
    }
    .tiered-option:hover {
      border-color: #000;
    }

    .tiered-option__badge {
      position: absolute;
      top: 0; 
      left: 50%;
      transform: translate(-50%, -80%);
      display: inline-block;
      background: var(--badge-bg-color);
      color: var(--badge-font-color);
      font-size: var(--badge-font-size);
      font-weight: bold;
      text-align: center;
      white-space: nowrap;
      padding: 0.1em 0.5em;
      border-radius: var(--border-radius);
      z-index: 2;
    }

    .tiered-option__label {
      font-weight: 600;
      margin-bottom: 0.5em;
      font-size: var(--label-font-size);
    }
    .tiered-option__prices {
      margin: 0.5em 0;
    }
    .tiered-option__compare-price {
      color: inherit;
      opacity: 0.75;
      text-decoration: line-through;
      display: block;
      margin-bottom: 0.25em;
      font-size: var(--compare-price-font-size);
    }
    .tiered-option__final-price {
      font-weight: bold;
      font-size: 1.1em;
      margin-bottom: 0.25em;
      font-size: var(--final-price-font-size);
    }
    .tiered-option__per-unit {
      font-size: var(--per-unit-font-size);
      color: inherit;
      opacity: 0.75;
      margin-bottom: 0.5em;
    }
    .tiered-option__discount-area {
      position: absolute;
      bottom: -0.25px;
      left: -1px;
      width: calc(100% + 2px);
      box-sizing: border-box;
      text-align: center;
      padding: 0.5em;
      background: var(--savings-bg-color);
      color: var(--savings-text-color);
      font-size: var(--savings-label-font-size);
      font-weight: bold;
      transform: translateZ(0);
      will-change: transform;
    }
  </style>

  <!-- Hidden quantity input -->
  <input type="hidden" name="quantity" id="Quantity-{{ section.id }}" value="1" form="{{ product_form_id }}" />

  {% assign per_unit_label = block.settings.per_unit_label %}
  {% assign show_zero_percent_savings = block.settings.show_zero_percent_savings %}
  {% assign show_savings_labels = block.settings.show_savings_labels %}
  {% assign show_strikethrough = block.settings.show_strikethrough %}
  {% assign show_per_unit = block.settings.show_per_unit %}
  {% assign show_total_pricing = block.settings.show_total_pricing %}

  {% assign show_quantity_label = block.settings.show_quantity_label %}
  {% assign quantity_label_text = block.settings.quantity_label_text %}

  {% if show_quantity_label %}
    <legend class="form__label">{{ quantity_label_text }}</legend>
  {% endif %}

  <div class="tiered-quantity-options" data-quantity-input-id="Quantity-{{ section.id }}">

    {% assign option_numbers = "1,2,3" | split: "," %}
    {% for i in option_numbers %}
      {% assign label_key = "option_" | append: i | append: "_label" %}
      {% assign quantity_key = "option_" | append: i | append: "_quantity" %}
      {% assign discount_pct_key = "option_" | append: i | append: "_discount_percentage" %}
      {% assign badge_enable_key = "option_" | append: i | append: "_badge_enable" %}
      {% assign badge_text_key = "option_" | append: i | append: "_badge_text" %}

      {% assign label = block.settings[label_key] %}
      {% assign quantity = block.settings[quantity_key] | plus: 0 %}
      {% assign discount_pct = block.settings[discount_pct_key] | plus: 0 %}
      {% assign badge_enable = block.settings[badge_enable_key] %}
      {% assign badge_text = block.settings[badge_text_key] %}

      {% if label != blank and quantity > 0 %}
        {% assign compare_total_cents = quantity | times: base_price %}
        {% assign discount_multiplier = 100 | minus: discount_pct %}
        {% assign final_price_cents = compare_total_cents | times: discount_multiplier | divided_by: 100 %}
        {% assign per_unit_cents = final_price_cents | divided_by: quantity %}

        {% capture compare_price_formatted %}{{ compare_total_cents | money }}{% endcapture %}
        {% capture final_price_formatted %}{{ final_price_cents | money }}{% endcapture %}
        {% capture per_unit_price_formatted %}{{ per_unit_cents | money }}{% endcapture %}

        {% assign show_compare = false %}
        {% if discount_pct > 0 and show_strikethrough %}
          {% assign show_compare = true %}
        {% endif %}

        {% assign show_discount = false %}
        {% if show_savings_labels %}
          {% if discount_pct > 0 %}
            {% assign show_discount = true %}
          {% elsif discount_pct == 0 and show_zero_percent_savings %}
            {% assign show_discount = true %}
          {% endif %}
        {% endif %}

        <div class="tiered-option-wrapper">
          {% if badge_enable %}
            <div class="tiered-option__badge">{{ badge_text }}</div>
          {% endif %}
          <button type="button"
                  class="tiered-option{% if forloop.first %} tiered-option--active{% endif %}"
                  data-quantity="{{ quantity }}">
            <div class="tiered-option__content">
              <div class="tiered-option__label">{{ label }}</div>
              <div class="tiered-option__prices">
                {% if show_compare %}
                  <span class="tiered-option__compare-price">{{ compare_price_formatted }}</span>
                {% endif %}
                {% if show_total_pricing %}
                  <span class="tiered-option__final-price">{{ final_price_formatted }}</span>
                {% endif %}
                {% if show_per_unit %}
                  <div class="tiered-option__per-unit">{{ per_unit_price_formatted }} / {{ per_unit_label }}</div>
                {% endif %}
              </div>
            </div>
            {% if show_discount %}
              <div class="tiered-option__discount-area">
                Save {{ discount_pct }}%
              </div>
            {% endif %}
          </button>
        </div>
      {% endif %}
    {% endfor %}
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
  var container = document.querySelector('.tiered-quantity-options[data-quantity-input-id="Quantity-{{ section.id }}"]');
  if (!container) return;
  var quantityInput = document.getElementById(container.dataset.quantityInputId);
  var buttons = container.querySelectorAll('.tiered-option');

  buttons.forEach(function(btn) {
    btn.addEventListener('click', function() {
      buttons.forEach(b => {
        b.classList.remove('tiered-option--active');
        b.style.background = '#fff';
        b.style.color = 'var(--text-color-unselected)';
      });
      this.classList.add('tiered-option--active');
      this.style.background = getComputedStyle(this).getPropertyValue('--selected-bg-color') || '#000';
      this.style.color = 'var(--text-color-selected)';
      var qty = parseInt(this.getAttribute('data-quantity'), 10);
      if (quantityInput && !isNaN(qty)) {
        quantityInput.value = qty;
        quantityInput.dispatchEvent(new Event('change'));
      }
    });
  });
});
</script>

Browse other ways to boost conversion rate & profit