アプリ不要!Shopify商品ページにギフトラッピングオプションを追加し、カートで自動課金

ECサイトを運営するうえで、クリスマスや誕生日などの特別な日には、ギフトラッピング機能があるととても便利ですよね。
しかし、残念ながらShopifyにはデフォルトでギフトラッピング機能がついていません。
Shopifyにギフトラッピング機能を追加するには、アプリを利用するか、コーディングで自作する必要があります。

アプリを利用する場合、有料のアプリを利用すれば細かい設定が可能ですが、月額がかかります。今回は無料で、アプリなしで実装したいと思います。

Shopifyの公式でもギフトラッピングの導入方法を説明していますが、カート内でのギフトラッピングの導入方法になります。
今回は、商品ページにギフトラッピングのオプションを追加してカート内で自動で課金する仕組みにしたいと思います。

▽Shopify公式 カートページにギフト包装のオプションを追加する
https://help.shopify.com/ja/manual/online-store/themes/themes-by-shopify/vintage-themes/customizing-vintage-themes/add-gift-wrap-option

ギフトラッピングの実装

まずは、Shopify公式で紹介されているページのギフトラッピングのオプションを参考にします。

上記で準備したコードを元に、商品ページで「ギフトラッピング」のオプションを追加し、カートページに行くと自動で課金されるようにカスタマイズしていきます。

商品ページにオプションの追加

まずは「Line Item Property」を利用して商品ページにオプションを追加します。
さらに、商品に「ギフト」のタグがある場合のみ表示できるようにしています。

    {% for tag in product.tags %}
      {%- if tag contains 'ギフト' -%}
        <p class="line-item-property__field">
          <label>ギフトラッピング</label><br>
          <select id="" name="properties[ギフトラッピング]">
            <option value="">希望しない</option>
            <option value="希望する">希望する</option>
          </select>
        </p>
      {%- endif -%}
    {% endfor %}

テーマによってファイル名が違ったりすると思いますが、商品ページのコードが記載されているファイルの「form」部分に追加してください。

「gift-wrapping.liquid」をカスタマイズ

次に、ギフトラッピング対応商品の数に応じて料金が加算される仕組みを実装します。
以下が完成系のコードです。

{% assign gift-wrap-count = 0 %}
{% for item in cart.items %}
  {% assign item_gift_wrap_count = 0 %}
  {% for property in item.properties %}
    {% if property[0] == 'ギフトラッピング' and property[1] == '希望する' %}
      {% assign item_gift_wrap_count = item.quantity %}
    {% endif %}
  {% endfor %}
  {% assign gift-wrap-count = gift-wrap-count | plus: item_gift_wrap_count %}
{% endfor %}

{% assign gift_wraps_in_cart = 0 %}
{% assign gift_wrap_product_id = linklists.gift-wrapping.links.first.object.variants.first.id %}

{% for item in cart.items %}
  {% if item.id == gift_wrap_product_id %}
    {% assign gift_wraps_in_cart = item.quantity %}
  {% endif %}
{% endfor %}

{% if gift-wrap-count > 0 %}
  <input id="gift-wrapping" type="hidden" name="attributes[ギフトラッピング]" value="yes" checked="checked" />
{% endif %}

<style>
  #updates_{{ gift_wrap_product_id }} {
    display: none;
  }
</style>

<script>
  Shopify.Cart = Shopify.Cart || {};
  Shopify.Cart.GiftWrap = {};

  Shopify.Cart.GiftWrap.set = function (quantity) {
    var headers = new Headers({ 'Content-Type': 'application/json' });
    var request = {
      method: 'POST',
      headers: headers,
      body: JSON.stringify({ updates: { {{ gift_wrap_product_id }}: quantity }, attributes: { 'ギフトラッピング': '希望する' } })
    };
    fetch('/cart/update.js', request)
      .then(function () {
        location.href = '/cart';
      });
  }

  Shopify.Cart.GiftWrap.remove = function () {
    var headers = new Headers({ 'Content-Type': 'application/json' });
    var request = {
      method: 'POST',
      headers: headers,
      body: JSON.stringify({ updates: { {{ gift_wrap_product_id }}: 0 }, attributes: { 'ギフトラッピング': '', 'gift-note': '' } })
    };
    fetch('/cart/update.js', request)
      .then(function () {
        location.href = '/cart';
      });
  }

  document.addEventListener("DOMContentLoaded", function () {
    if ({{ cart.items.size }} == 1 && {{ gift_wraps_in_cart }} > 0) {
      Shopify.Cart.GiftWrap.remove();
    } else if ({{ gift_wraps_in_cart }} != {{ gift-wrap-count }}) {
      Shopify.Cart.GiftWrap.set({{ gift-wrap-count }});
    }

    document.querySelector('[name="attributes[ギフトラッピング]"]').addEventListener("change", function (event) {
      if (event.target.checked) {
        Shopify.Cart.GiftWrap.set({{ gift-wrap-count }});
      } else {
        Shopify.Cart.GiftWrap.remove();
      }
    });

    document.querySelector('#gift-note').addEventListener("change", function (evt) {
      var note = evt.target.value;
      var headers = new Headers({ 'Content-Type': 'application/json' });

      var request = {
        method: 'POST',
        headers: headers,
        body: JSON.stringify({ attributes: { 'gift-note': note } })
      };

      fetch('/cart/update.js', request);
    });
  });
</script>

{% if linklists.gift-wrapping.links.size == 0 or linklists.gift-wrapping.links.first.type != 'product_link' %}
  <p style="clear: left; margin: 30px 0" class="rte">
    You attempted to add a gift-wrapping script to your shopping cart, but it won't work because you don't have a link list with handle <code>gift-wrapping</code> which, in turn, contains a link to your gift-wrapping product. Please review the steps outlined <a href="https://help.shopify.com/manual/online-store/themes/os/customize/add-gift-wrap-option" target="_blank" rel="noopener noreferrer nofollow">here</a>.
  </p>
{% endif %}

{% assign gift-wrap-count = 0 %}
{% for item in cart.items %}
  {% assign item_gift_wrap_count = 0 %}
  {% for property in item.properties %}
    {% if property[0] == 'ギフトラッピング' and property[1] == '希望する' %}
      {% assign item_gift_wrap_count = item.quantity %}
    {% endif %}
  {% endfor %}
  {% assign gift-wrap-count = gift-wrap-count | plus: item_gift_wrap_count %}
{% endfor %}

この部分では、カート内の各商品について、ギフトラッピングオプションが選択されているかどうかをチェックし、選択されている商品の数量をカウントしています。

{% assign gift_wraps_in_cart = 0 %}
{% assign gift_wrap_product_id = linklists.gift-wrapping.links.first.object.variants.first.id %}

{% for item in cart.items %}
  {% if item.id == gift_wrap_product_id %}
    {% assign gift_wraps_in_cart = item.quantity %}
  {% endif %}
{% endfor %}

ここでは、ギフトラッピング商品(設定された商品)のIDを取得し、カート内にその商品が何個入っているかを確認しています。

{% if gift-wrap-count > 0 %}
  <input id="gift-wrapping" type="hidden" name="attributes[ギフトラッピング]" value="yes" checked="checked" />
{% endif %}

ギフトラッピングオプションが選択されている場合、「input」を追加してその情報を保存します。
「input」は「type="hidden"」にして非表示にしています。

Shopify公式にある「gift-wrapping.liquid」の「name="attributes[gift-wrapping]"」の注文内容の確認がしやすいように「[name="attributes[ギフトラッピング]"」と日本語に変更しています。

注意事項

このコードは一例であり、人によって書き方が異なる場合があります。また、テーマや設定によって必要な調整が異なることがありますので、ご自身のサイトに合わせて適宜カスタマイズしてください。

後はShopify公式にあるようにカートテンプレートに上記ファイルを読み込ませてください。
これで、商品ページで「ギフトラッピング」オプションを選択した商品がカートにある場合、カート内で自動課金してくれるようになります。


※カートページの読み込みの際に自動課金されます。
カート内で対象商品を削除した場合は、再読み込みをしないとカート内に「ギフトラッピング」のアイテムが残ります。
再読み込みすると対象商品がないので「ギフトラッピング」のアイテムは削除されます。

#shopify #ギフトラッピング #プログラミング