跳转到主要内容

Shopify 高级技巧

Shopify 实现组合产品Listing打包销售,提高销售额

在 Shopify 上,产品组合打包销售是一种非常有效的提高销售额的策略。通过将多个相关产品捆绑在一起,以优惠价格出售,不仅能够提高顾客的购买量,还能增加平均订单价值。下面是如何在 Shopify 中实现组合打包销售的详细步骤和代码实现。

1. 什么是组合打包销售?

组合打包销售是将多个产品组合在一起,以一个优惠价格出售的策略。这种方式通常比单独销售每个产品时提供更高的折扣,能够吸引客户购买更多的商品。例如,假设你销售一套护肤品,可能会将面膜、精华液和乳液打包在一起,以优惠的价格销售。

通过这种方式,不仅可以提高每个客户的订单价值,还能让客户体验到更多的产品组合,从而增加销售额。

2. 为什么选择组合打包销售?

组合打包销售有许多好处,特别是对 Shopify 商家而言:

  • 提高平均订单价值:通过捆绑多个产品并提供折扣,商家可以激励顾客购买更多商品,从而提高每个订单的价值。
  • 增加库存周转率:将销售不太热销的产品与畅销商品捆绑销售,可以提高库存的周转率,减少积压。
  • 提升顾客购买意图:当客户看到折扣和组合优惠时,往往会更愿意购买,从而提高转化率。

3. 哪些是适合组合打包销售的产品

首先,商家需要确定哪些产品适合进行组合销售。选择以下几类产品进行捆绑通常效果较好:

  • 互补产品:例如,购买手机时顾客可能需要配件如手机壳、充电线、耳机等。
  • 热销产品:选择已经热销的产品与其他产品搭配,提升销售量。
  • 季节性产品:例如,夏季推出的清凉产品组合包,吸引顾客的注意。
  • 捆绑折扣:通过捆绑多个产品并提供一定的折扣,增加销量。
  • 套装产品:例如帽子,上衣,裤子,鞋子,袜子作为套装整套销售。Shopify 产品 Listing 如何实现组合打包销售,提高销售额

在竞争激烈的电商环境中,提升销售额和提高客户转化率是每个商家追求的目标。产品组合打包销售(Bundled Products)是一种有效的提升销售额的策略。通过将多个产品捆绑在一起,提供优惠价格,商家不仅能提高每个订单的销售额,还能增强顾客的购买意愿。本文将详细介绍如何在 Shopify 上实现产品组合打包销售,帮助你提高销售额。

4. 如何在 Shopify 上实现组合打包销售?

在 Shopify 上实现组合打包销售,首先需要对你的产品页面和购物车页面进行一些自定义修改。这些修改包括显示产品组合、处理折扣价格和更新购物车总价等。

以下是实现组合打包销售的具体步骤。

4.1 修改产品页面

在产品页面上,我们需要检查是否有组合产品,如果有,则显示组合产品的价格,或者提供捆绑的选择。

1、到 settings > Custom data > Products, 点击Add definition 增加自定义字段
创建字段,Name:set products Namespace and key:c_f.set_products Select type:product——》List of products
创建字段,Name:set products rate Namespace and key:c_f.set_products_rate Select type:Decimal——》one vlue

2、sections\main-product搜索@app,添加下面代码

{
"type": "set_product_combo",
"name": "set product combo",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "产品整套组合销售"
},
{
  "type": "number",
  "id": "heading_font_size",
  "label": "Heading font size (px)",
  "default": 18
},
{
  "type": "color",
  "id": "heading_color",
  "label": "Heading color",
  "default": "#121212"
}
]
},

3、sections\main-product继续搜索{%- when '@app' -%}
在下面添加下面代码

{%- when 'set_product_combo' -%}
{%- render 'set-product-combo', product: product -%}

4、snippets文件夹增加文件set-product-combo.liquid
代码为

{% if product.metafields.c_f.set_products %} 
  <style>
  
.shopify-payment-button{
    display: none !important;
}
  .ProductForm__QuantitySelector{
    display: none !important;
}
  </style>
  {% assign set_products = product.metafields.c_f.set_products.value %}
  {% assign total_savings = 0 %} <!-- 用来计算总优惠差额 -->
  {% assign total_discount_price = 0 %} <!-- 用来计算所有打折后的总价格 -->

  <div class="set-product-details">
      <fieldset>
          <legend style="display:none">Included products</legend>
          
          {% for set_product in set_products %}

            {% if set_product.variants and set_product.variants.size > 1 %} <!-- 如果有变体 -->

              {% for variant in set_product.variants %}
              {% if forloop.first %}
              {% assign set_discount_rate = product.metafields.c_f.set_products_rate %}

              {%- if set_discount_rate -%}
                  {% assign set_discount_price = variant.price | times: set_discount_rate %}
              {%- else -%}
                  {% assign set_discount_price = variant.price %}
              {%- endif -%}

              {% assign original_price = variant.price %}
              {% assign savings = original_price | minus: set_discount_price %}
              {% assign total_savings = total_savings | plus: savings %}
              {% assign total_discount_price = total_discount_price | plus: set_discount_price %}
            

              <div class="set-product-detail set-product-detail__info {% if set_product.selected == true %} {% else %} set-product-detail--removed {% endif %}" 
                  data-sku="{{ variant.sku }}"
                  data-price="{{ variant.price }}"
                  data-bundle-price="{{ set_discount_price }}">

                  <div class="set-product-detail__selected">
                      <div class="field field--checkbox">
                          <label class="check_box set-product-detail__image">
                              <img alt="{{ set_product.title }}" src="{{ set_product.images[0] | image_url }}" width="70" height="78">
                              <input class="check_box" type="checkbox" name="set-product-selected" value="{{ variant.id }}" checked="checked" />
                          </label>
                      </div>
                  </div>
                  
                  <div class="set-product-detail-wrap">
                      <a href="{{ set_product.url }}" target="_blank" class="set-product-detail__title">{{ set_product.title }}</a>
                      
                      {% assign set_product_subtitle = set_product.metafields.c_f.option_title.value[0] %}
                      {% if set_product_subtitle %}
                          <p class="set-product-detail__subtitle">{{ set_product_subtitle }}</p>
                      {% endif %}

                      <div class="set-product-detail__option-selector">
                          <select class="js-option-select select-replaced" name="variant" id="variant-select-{{ variant.id }}" class="input" autocomplete="off" onchange="updatePrice(this, '{{ variant.id }}')">
                          {% endif %}
                        {% endfor %}
                              {% for variant in set_product.variants %}
                                  {% assign data-bundle-price = variant.price | times: set_discount_rate %}
                                  <option 
                                      value="{{ variant.id }}"
                                      data-variant-id="{{ variant.id }}"
                                      data-variant-sku="{{ variant.sku }}"
                                      data-variant-price="{{ variant.price }}"
                                      data-bundle-price="{{ data-bundle-price }}"
                                      data-instock="{{ variant.available }}"
                                      data-stock-message="{% if variant.available %}In stock{% else %}Out of stock{% endif %}"
                                      {% if forloop.first %} selected {% endif %}>
                                      {{ variant.title }}
                                  </option>
                              {% endfor %}
                          </select>
                      </div>
                      {% for variant in set_product.variants %}
                        {% if forloop.first %}
                        {% assign set_discount_rate = product.metafields.c_f.set_products_rate %}
          
                        {%- if set_discount_rate -%}
                            {% assign set_discount_price = variant.price | times: set_discount_rate %}
                        {%- else -%}
                            {% assign set_discount_price = variant.price %}
                        {%- endif -%}
          
                        {% assign original_price = variant.price %}
                        {% assign savings = original_price | minus: set_discount_price %}
                        {% assign total_savings = total_savings | plus: savings %}
                        {% assign total_discount_price = total_discount_price | plus: set_discount_price %}
                      <div class="set-product-detail__info-row">
                          <div class="set-product-detail__prices">
                              <p class="set-product-detail__price" id="price-{{ variant.id }}">{{ set_discount_price | money }}</p>
                          </div>
                      </div>

                      <div class="set-product-detail__stock-messages">
                          <div class="set-product-detail__stock-message js-stock-message">
                              {{ variant.price | money }}
                          </div>

                          <!-- Add & save 显示部分 -->
                          <div class="set-product-detail__bundle-message js-bundle-message" style="display: none;">
                              Add & save <span class="save-price">{{ savings | money }}</span>
                          </div>
                      </div>
                  </div>
              </div>
            {% endif %}
          {% endfor %}
            {% elsif set_product.variants.size <= 1 %} <!-- 没有变体,或只有一个变体 -->
                {% assign set_discount_rate = product.metafields.c_f.set_products_rate %}

                {%- if set_discount_rate -%}
                    {% assign set_discount_price = set_product.price | times: set_discount_rate %}
                {%- else -%}
                    {% assign set_discount_price = set_product.price %}
                {%- endif -%}

                {% assign original_price = set_product.price %}
                {% assign savings = original_price | minus: set_discount_price %}
                {% assign total_savings = total_savings | plus: savings %}
                {% assign total_discount_price = total_discount_price | plus: set_discount_price %}

                <div class="set-product-detail set-product-detail__info {% if set_product.selected == true %} {% else %} set-product-detail--removed {% endif %}" 
                    data-sku="{{ set_product.variants.first.sku }}"
                    data-price="{{ set_product.price }}"
                    data-bundle-price="{{ set_discount_price }}">

                    <div class="set-product-detail__selected">
                        <div class="field field--checkbox">
                            <label class="check_box set-product-detail__image">
                                <img alt="{{ set_product.title }}" src="{{ set_product.images[0] | image_url }}" width="70" height="78">
                                <input class="check_box" type="checkbox" name="set-product-selected" value="{{ set_product.variants.first.id }}" checked="checked" />
                            </label>
                        </div>
                    </div>
                    
                    <div class="set-product-detail-wrap">
                        <a href="{{ set_product.url }}" target="_blank" class="set-product-detail__title">{{ set_product.title }}</a>
                        
                        {% assign set_product_subtitle = set_product.metafields.c_f.option_title.value[0] %}
                        {% if set_product_subtitle %}
                            <p class="set-product-detail__subtitle">{{ set_product_subtitle }}</p>
                        {% endif %}

                        <div class="set-product-detail__info-row">
                            <div class="set-product-detail__prices">
                                <p class="set-product-detail__price" id="price-{{ set_product.id }}">{{ set_discount_price | money }}</p>
                            </div>
                        </div>

                        <div class="set-product-detail__stock-messages">
                            <div class="set-product-detail__stock-message js-stock-message">
                                {{ set_product.price | money }}
                            </div>

                            <!-- Add & save 显示部分 -->
                            <div class="set-product-detail__bundle-message js-bundle-message" style="display: none;">
                                Add & save <span class="save-price">{{ savings | money }}</span>
                            </div>
                        </div>
                    </div>
                </div>

            {% else %} <!-- 其他情况为空 -->
              <!-- 可能没有商品或为空,不做任何操作 -->
          {% endif %}

          {% endfor %}
      </fieldset>
  </div>

  <p class="js-bundle-messaging product-details__stock product-details__bundle product-details__bundle--complete"
      data-not-complete="Add all and save {{ total_savings | money }} on the complete set"
      data-complete="You've saved {{ total_savings | money }} with this set" id="total-savings">
      You've saved {{ total_savings | money }} with this set
  </p>
{% endif %}

5.sections\main-product搜索Button__SeparatorDot
将下面整段代码

<button type="submit" data-use-primary-button="{% if use_primary_button %}true{% else %}false{% endif %}" class="ProductForm__AddToCart Button {% if product.selected_or_first_available_variant.available and use_primary_button %}Button--primary{% else %}Button--secondary{% endif %} Button--full" {% if product.selected_or_first_available_variant.available %}data-action="add-to-cart"{% else %}disabled="disabled"{% endif %}>
                      {%- if product.selected_or_first_available_variant.available -%}
                        <span>{% if product.template_suffix == 'pre-order' %}{{ 'product.form.pre_order' | t }}{% else %}{{ 'product.form.add_to_cart' | t }}{% endif %}</span>

                        {%- if block.settings.show_price_in_button -%}
                          <span class="Button__SeparatorDot"></span>
                          <span>{{ product.selected_or_first_available_variant.price | money }}</span>
                        {%- endif -%}
                      {%- else -%}
                        {{- 'product.form.sold_out' | t -}}
                      {%- endif -%}
                    </button>

替换为

{%- if product.metafields.c_f.set_products -%}
                      <button type="button" id="add-set-to-cart" class="ProductForm__AddToCart Button Button--primary Button--full">
                        <span>{{ 'product.form.add_to_cart' | t }}</span>
                      </button>
                      {%- render 'js-addcart' -%}

                    {%- else -%}
                    <button type="submit" data-use-primary-button="{% if use_primary_button %}true{% else %}false{% endif %}" class="ProductForm__AddToCart Button {% if product.selected_or_first_available_variant.available and use_primary_button %}Button--primary{% else %}Button--secondary{% endif %} Button--full" {% if product.selected_or_first_available_variant.available %}data-action="add-to-cart"{% else %}disabled="disabled"{% endif %}>
                      {%- if product.selected_or_first_available_variant.available -%}
                        <span>{% if product.template_suffix == 'pre-order' %}{{ 'product.form.pre_order' | t }}{% else %}{{ 'product.form.add_to_cart' | t }}{% endif %}</span>

                        {%- if block.settings.show_price_in_button -%}
                          <span class="Button__SeparatorDot"></span>
                          <span>{{ product.selected_or_first_available_variant.price | money }}</span>
                        {%- endif -%}
                      {%- else -%}
                        {{- 'product.form.sold_out' | t -}}
                      {%- endif -%}
                    </button>
                  {%- endif -%}

6.snippets文件夹增加文件js-addcart.liquid
代码如下

<script>
  document.addEventListener('DOMContentLoaded', function () {
    const checkboxes = document.querySelectorAll('input[name="set-product-selected"]');
    const totalPriceElement = document.getElementById('total-price');
    const totalSavingsElement = document.getElementById('total-savings');
    const setProductDetails = document.querySelectorAll('.set-product-detail');
    const shopPayButton = document.querySelector('.shopify-payment-button');
    
    let total_price = 0;
    let total_savings = 0;
  
    function formatCurrency(amount, currencyCode = 'USD') {
      return new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: currencyCode,
      }).format(amount);
    }
  
    function updateTotalPriceAndSavings() {
      total_price = 0;
      total_savings = 0;
      const currencyCode = Shopify.currency.active;
  
      setProductDetails.forEach(productDetail => {
        const checkbox = productDetail.querySelector('input[name="set-product-selected"]');
        const originalPrice = parseFloat(productDetail.getAttribute('data-price').replace(/[^0-9.-]+/g, ""));
        const discountedPrice = parseFloat(productDetail.getAttribute('data-bundle-price').replace(/[^0-9.-]+/g, ""));
        const bundleMessageElement = productDetail.querySelector('.set-product-detail__bundle-message');
        
        if (checkbox.checked) {
          total_price += discountedPrice / 100;
          total_savings += (originalPrice - discountedPrice) / 100;
          bundleMessageElement.style.display = 'none';
        } else {
          bundleMessageElement.style.display = 'block';
        }
      });
  
      totalPriceElement.textContent = formatCurrency(total_price, currencyCode);
      totalSavingsElement.textContent = `You've saved ${formatCurrency(total_savings, currencyCode)}`;
      totalSavingsElement.setAttribute('data-complete', `You've saved ${formatCurrency(total_savings, currencyCode)} with this set`);
      totalSavingsElement.setAttribute('data-not-complete', `Add all and save ${formatCurrency(total_savings, currencyCode)} on the complete set`);
    }
  
    checkboxes.forEach(checkbox => {
      checkbox.addEventListener('change', updateTotalPriceAndSavings);
    });
  
    document.querySelectorAll('.js-option-select').forEach(select => {
      select.addEventListener('change', function () {
        const selectedVariant = this.options[this.selectedIndex];
        const selectedVariantPrice = parseFloat(selectedVariant.getAttribute('data-bundle-price').replace(/[^0-9.-]+/g, ""));
        const selectedVariantOriginalPrice = parseFloat(selectedVariant.getAttribute('data-variant-price').replace(/[^0-9.-]+/g, ""));
        
        const productDetail = this.closest('.set-product-detail');
        productDetail.querySelector('.set-product-detail__price').textContent = formatCurrency(selectedVariantPrice / 100, Shopify.currency.active);
        productDetail.querySelector('.set-product-detail__stock-message').textContent = formatCurrency(selectedVariantOriginalPrice / 100, Shopify.currency.active);
        productDetail.querySelector('.save-price').textContent = selectedVariantOriginalPrice > selectedVariantPrice ? `Save ${formatCurrency((selectedVariantOriginalPrice - selectedVariantPrice) / 100, Shopify.currency.active)}` : '';
        
        productDetail.setAttribute('data-bundle-price', selectedVariantPrice);
        updateTotalPriceAndSavings();
      });
    });
  
    updateTotalPriceAndSavings();
  
    function addToCart(callback) {
      let items = [];
      checkboxes.forEach(checkbox => {
        if (checkbox.checked) {
          const productElement = checkbox.closest('.set-product-detail');
          const variantId = checkbox.value;
          const selectedVariant = productElement.querySelector('select.js-option-select');
          const selectedVariantId = selectedVariant ? selectedVariant.value : variantId;
          const setDiscountPrice = parseFloat(productElement.getAttribute('data-bundle-price'));
          
          items.push({
            id: selectedVariantId,
            quantity: 1,
            properties: { _discount_price: setDiscountPrice }
          });
        }
      });
  
      if (items.length > 0) {
        fetch('/cart/add.js', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ items })
        })
        .then(response => response.json())
        .then(() => callback && callback())
        .catch(error => console.error('Add to cart error:', error));
      } else {
        alert('Please choose at least one product!');
      }
    }
  
    document.getElementById('add-set-to-cart').addEventListener('click', () => {
      addToCart(() => {
        document.dispatchEvent(new CustomEvent('product:added', { bubbles: true, detail: { quantity: 1 } }));
      });
    });
  
    {% comment %}if (shopPayButton) {
    shopPayButton.addEventListener('click', function(event) {
      event.preventDefault();  // 阻止默认 Shop Pay 结账行为
      event.stopImmediatePropagation(); // 阻止事件传播,避免其他监听器干扰
  
      addToCart(() => {
        window.location.href = '/checkout'; // 自定义行为,添加到购物车后跳转到结账页面
      });
    });
    }{% endcomment %}
      if (shopPayForm) {
          shopPayForm.addEventListener("submit", function (event) {
              event.preventDefault();  // 阻止默认提交
              event.stopImmediatePropagation();
  
              // 手动跳转到 Shopify 结账页,而不是 Shop Pay
              window.location.href = "/checkout";
          });
      }
  });
  </script> 

7、sinppets\product-meta 搜索ProductMeta__PriceList Heading

{%- if settings.currency_code_enabled -%}
{%- if product.selected_or_first_available_variant.compare_at_price > product.selected_or_first_available_variant.price -%}
{{ product.selected_or_first_available_variant.price | money_with_currency }}
{{ product.selected_or_first_available_variant.compare_at_price | money_with_currency }}
{%- else -%}
{{ product.selected_or_first_available_variant.price | money_with_currency }}
{%- endif -%}
{%- else -%}
{%- if product.selected_or_first_available_variant.compare_at_price > product.selected_or_first_available_variant.price -%}
{{ product.selected_or_first_available_variant.price | money }}
{{ product.selected_or_first_available_variant.compare_at_price | money }}
{%- else -%}
{{ product.selected_or_first_available_variant.price | money }}
{%- endif -%}
{%- endif -%}

整段代码
替换为

{%- if product.metafields.c_f.set_products -%}
    
    {%- render 'set-product-combo-price' -%}
  
  {%- else -%}
    <div class="ProductMeta__PriceList Heading">
      {%- if settings.currency_code_enabled -%}
        {%- if product.selected_or_first_available_variant.compare_at_price > product.selected_or_first_available_variant.price -%}
          <span class="ProductMeta__Price Price Price--highlight Text--subdued u-h4">{{ product.selected_or_first_available_variant.price | money_with_currency }}</span>
          <span class="ProductMeta__Price Price Price--compareAt Text--subdued u-h4">{{ product.selected_or_first_available_variant.compare_at_price | money_with_currency }}</span>
        {%- else -%}
          <span class="ProductMeta__Price Price Text--subdued u-h4">{{ product.selected_or_first_available_variant.price | money_with_currency }}</span>
        {%- endif -%}
      {%- else -%}
        {%- if product.selected_or_first_available_variant.compare_at_price > product.selected_or_first_available_variant.price -%}
          <span class="ProductMeta__Price Price Price--highlight Text--subdued u-h4">{{ product.selected_or_first_available_variant.price | money }}</span>
          <span class="ProductMeta__Price Price Price--compareAt Text--subdued u-h4">{{ product.selected_or_first_available_variant.compare_at_price | money }}</span>
        {%- else -%}
          <span class="ProductMeta__Price Price Text--subdued u-h4">{{ product.selected_or_first_available_variant.price | money }}</span>
        {%- endif -%}
      {%- endif -%}
    </div>
  {%- endif -%}

8、snippets文件夹增加文件set-product-combo-price.liquid
代码如下

{% assign set_products = product.metafields.c_f.set_products.value %}
{%- liquid 
  assign yeshasproduct = false
  for set_product in set_products
    if set_product.available == true
      assign yeshasproduct = true
    endif
  endfor
-%}
{% if yeshasproduct %}
  <div class="ProductMeta__PriceList Heading">

    {% assign total_discount_price = 0 %}

    {% for set_product in set_products %}

      {% assign total_discount_price = total_discount_price | plus: set_product.price %}
    {% endfor %}
    
    <span class="ProductMeta__Price Price Text--subdued u-h4" id="total-price" data-initial-price="{{ total_discount_price }}">
    {{ total_discount_price }}
</span>

  {% endif %}
    
    </div>

5. 更新购物车和结账页面

为了确保顾客在购物车和结账页面能够看到组合包的正确价格,我们需要在购物车和结账页面相应的位置进行修改。

5.1 修改购物车项目价格显示

在购物车页面 cart-items.liquid 中,找到 CartItem__PriceList 相关的代码,并替换为如下内容:

搜索CartItem__PriceList。将整个div代码块替换为

      {%- if line_item.properties._discount_price -%}
        <!-- 如果有折扣价格 -->
        <span class="CartItem__Price Price Price--highlight">{{ line_item.properties._discount_price | money }}</span>
        <span class="CartItem__OriginalPrice Price Price--compareAt">{{ line_item.original_price | money }}</span>
      
      {%- elsif line_item.original_price != line_item.final_price -%}
        <span class="CartItem__Price Price Price--highlight">{{ line_item.final_price | money }}</span>
        <span class="CartItem__OriginalPrice Price Price--compareAt">{{ line_item.original_price | money }}</span>
        
      {%- else -%}
        <span class="CartItem__Price Price">{{ line_item.final_price | money }}</span>
      {%- endif -%}
      

        {%- if line_item.line_level_discount_allocations != blank -%}
          <ul class="CartItem__DiscountList">
            {%- for discount_allocation in line_item.line_level_discount_allocations -%}
              <li class="CartItem__Discount">
                {%- render 'icon' with 'sale' -%}{{ discount_allocation.discount_application.title }}: -{{ discount_allocation.amount | money }}
              </li>
            {%- endfor -%}
          </ul>
        {%- endif -%}
      </div>


这段代码确保了如果某个购物车项有折扣价格,它会显示折扣后的价格并标明原价。

5.2 更新购物车总价格显示

main-cart.liquid 文件中,找到购物车总价的显示部分,并替换为以下代码:

搜索Cart__Total Heading u-h6找到

<p class="Cart__Total Heading u-h6">{{ 'cart.general.total' | t }}: <span>{{ cart.total_price | money_with_currency }}</span></p>

替换为

{%- assign total_discount_price = 0 -%}
          {%- assign has_discount_price = true -%}

          {%- for line_item in cart.items -%}
            {%- if line_item.properties._discount_price -%}
              {%- assign total_discount_price = total_discount_price | plus: line_item.properties._discount_price | times: line_item.quantity -%}
            {%- else -%}
              {%- assign has_discount_price = false -%}
            {%- endif -%}
          {%- endfor -%}

            {%- if has_discount_price -%}
              <!-- 如果所有商品都有折扣价格 -->
            <p class="Cart__Total Heading u-h6">{{ 'cart.general.total' | t }}: <span>{{ total_discount_price | money_with_currency }}</span></p>
            {%- else -%}
              <!-- 如果有商品没有折扣价格,则显示购物车的总价格 -->
              <p class="Cart__Total Heading u-h6">{{ 'cart.general.total' | t }}: <span>{{ cart.total_price | money_with_currency }}</span></p>
            {%- endif -%}


这段代码确保了如果所有商品都有折扣价格,购物车总价会显示折扣后的价格。如果有商品没有折扣价格,则显示正常的购物车总价。

6. 添加CSS样式

为了确保产品组合包和购物车显示的效果良好,您可以为新添加的元素增加一些样式。在 base.csstheme.css 文件中添加以下 CSS 代码:

.set-ring-info {
  margin-bottom: 22px;
  font-size: 10px;
  font-size: 0.625rem;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.68px;
  color: #000000;
}
.set-ring-info a {
  color: #000000;
}

.set-ring-info__separator {
  display: inline;
  margin: 0 10px;
}
.set-ring-info__separator:before {
  content: "|";
}

.set-product-detail {
  display: flex;
  flex-direction: row;
  margin-bottom: 25px;
}
.set-product-detail[data-inactive=true] .set-product-detail__stock-message {
  color: #970202;
  background: #f1eee4;
  font-weight: 600;
}

.set-product-detail__image {
  background: none;
}
.set-product-detail__image img {
  mix-blend-mode: normal;
}

.set-product-detail__image--no-blend img {
  mix-blend-mode: normal;
}

.set-product-detail__separator {
  margin: 0 10px;
}
.set-product-detail__separator:before {
  content: "|";
}

.set-product-detail__info {
  width: 100%;
}

.set-product-detail__title {
  font-size: 12px;
  font-size: 0.75rem;
  line-height: 1.25;
  color: #000000;
  letter-spacing: 0.9px;
  margin-bottom: 6px;
}

.set-product-detail__subtitle {
  font-size: 10px;
  font-size: 0.625rem;
  line-height: 1.5;
  color: #000000;
  letter-spacing: 0.8px;
  font-weight: lighter;
  margin-bottom: 6px;
}

.set-product-detail__info-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  font-size: 12px;
  font-size: 0.75rem;
  line-height: 1.25;
  letter-spacing: 0.6px;
}

.set-product-detail__prices {
  display: inline;
}

.set-product-detail__price {
  display: inline;
}

.set-product-detail__price--was {
  background-image: linear-gradient(to right, #000000, #000000);
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 100% 1px;
  transition: background-size 0.5s ease;
}

.set-product-detail__price--now,
.set-product-detail__price--bundle-now {
  color: #970202;
}

.set-product-detail__personalisation {
  font-size: 10px;
  font-size: 0.625rem;
  line-height: 1.5;
  letter-spacing: 1.5px;
}
.set-product-detail__personalisation button {
  text-transform: uppercase;
  background: unset;
  padding: 0;
}

.set-product-detail__personalisation--secondary {
  flex-basis: 100%;
}

.set-product-detail__add-engraving {
  display: inline;
}

.set-product-detail__option-selector {
  display: flex;
  flex-direction: row;
}
.set-product-detail__option-selector select {
  height: auto;
  padding: 0 10px 0 0;
  border: 0;
}
.set-product-detail__option-selector p {
  border: none;
  display: inline;
  padding: 0;
  font-size: 12px;
  font-size: 0.75rem;
  line-height: 1.5;
  width: auto;
  max-width: calc(100% - 10px);
}
.set-product-detail__option-selector .select-replace__icon {
  right: 0;
}

.option-selector__label {
  margin-right: 5px;
}

.set-product-detail__option-error,
.set-product-detail__engraving-error {
  display: none;
  color: #970202;
  font-size: 12px;
  font-size: 0.75rem;
  line-height: 1.25;
  letter-spacing: 0.6px;
}

.pdp-price-button__price-block--event {
  display: flex;
  flex-direction: row;
}

.set-product-detail__stock-message {
  font-size: 10px;
  font-size: 0.625rem;
  line-height: 1.5;
  font-weight: bold;
  color: #2a7f13;
  letter-spacing: 0.8px;
}

.set-product-detail__stock-message--error {
  color: white;
  background: #8A1B12;
  padding: 4px 12px;
  border-radius: 25px;
}

.set-product-detail__size-guide {
  position: relative;
  right: -18px;
}

7. 优化结账按钮

最后,在购物车抽屉 snippets/cart-drawer.liquid 中,找到结账按钮的代码并根据是否有折扣价格来动态显示总价:

<button type="submit" name="checkout" class="Cart__Checkout Button Button--primary Button--full">
            <span>{{ 'cart.general.checkout' | t }}</span>
            <span class="Button__SeparatorDot"></span>
            <span>{{ cart.total_price | money_with_currency }}</span>
          </button>

替换为

    {%- assign total_discount_price = 0 -%}
    {%- assign has_discount_price = true -%}
    
    {%- for line_item in cart.items -%}
      {%- if line_item.properties._discount_price -%}
        {%- assign total_discount_price = total_discount_price | plus: line_item.properties._discount_price | times: line_item.quantity -%}
      {%- else -%}
        {%- assign has_discount_price = false -%}
      {%- endif -%}
    {%- endfor -%}
    
    {%- if has_discount_price -%}
      <!-- 如果所有商品都有折扣价格 -->
      <button type="submit" name="checkout" class="Cart__Checkout Button Button--primary Button--full">
        <span>{{ 'cart.general.checkout' | t }}</span>
        <span class="Button__SeparatorDot"></span>
        <span>{{ total_discount_price | money_with_currency }}</span>
      </button>
    {%- else -%}
      <!-- 如果有商品没有折扣价格,则显示购物车的总价格 -->
      <button type="submit" name="checkout" class="Cart__Checkout Button Button--primary Button--full">
        <span>{{ 'cart.general.checkout' | t }}</span>
        <span class="Button__SeparatorDot"></span>
        <span>{{ cart.total_price | money_with_currency }}</span>
      </button>
    {%- endif -%}

这段代码会根据购物车中商品的折扣状态来动态显示结账按钮的总价。


8. 总结

通过上述步骤,我们已经成功地在 Shopify 上实现了产品组合打包销售功能。组合销售不仅能够提升订单的平均金额,还能增加客户的购买意愿,从而帮助商家提高销售额。通过合理的组合打包策略,商家可以为客户提供更具吸引力的优惠,并且最大化地提高库存周转率。