【Shopify】標準だとイケてないカートページをカスタマイズ!

liquid
liquid Shopify

Shopifyではデザインが洗練されたテーマを使用すれば、カートページのデザインもイケてるものにできるはず、、と思いきや、何もしないと案外UIが悪いものがある。

ここでは、カートページ内を一新した例をもとに要点を紹介します。

商品ページ、カートページでは、<form>タグや<input>タグの使い方やテーマのコアになるjsの仕様をよく理解していないといけないし、ECサイトが機能しないことになりますので、クリティカル・取扱注意なコードである。

今回はその中のカートページのカスタマイズについて。

カートページカスタマイズの際の要点

ノーコード(ノーコーディング)では構造の自由度がないため、コーディングが必要になる。

ノーコードの場合の構図の例

以下のように、

  • 備考欄(配送メモ欄)と配送希望日の位置がそれぞればらばらになる。
  • テーマによっては数量選択のUIがプルダウンになっているので、数量増減には2クリックが必要(①プルダウンを開く②数を選択する)になる。

コーディングで構図を整えた場合の例

  • 備考欄(配送メモ欄)と配送希望日の位置が整理され情報が一目瞭然。
  • 数量選択がーと+のスピナーボタンになっているので、ユーザはワンクリックで増減ができる。

補足:セクションでもブロックでもざっくりはノーコードで組み込みできる

※Dawnはセクション単位で機能が分割されていたため、ノーコードでも構図を組み替えることができた。Dawn優秀。。ただし備考欄を表示する機能がない!

数量選択スピナーを作成する

UIとしてはプルダウンよりスピナーの方が手数がかかって大変です。

以下のような仕様を想定します。

  • ーか+ボタンを作成し、それぞれクリックされた時の挙動を作り分ける
  • 数量が変更されたとき、合計金額が自動更新されるようにjsでCart APIを使用する

それぞれ実装方法を順に解説します。

スピナーボタンの作成:ーか+ボタンを作成し、それぞれクリックされた時の挙動を作り分ける

イケてない場合の構図の例

コーディングでスピナーをつけた場合の例

  • input内の数値をスピナーで変更できるようにjsを記述
  • スピナーでinput内の数値を変更した際に、合計金額が動的に変わるようにテーマのjsに追記することを忘れず!

snippetに以下ふたつのファイルを追加する

icon-mimus.liquid

(コード)

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash" viewBox="0 0 16 16">
  <path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>
</svg>

icon-plus.liquid

(コード)

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
  <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg>

余談:ありそうでなかなかない、無料SVGの素材サイト(だいたいどこも本当に使えるやつは有料にしている)

-と+のくせのないSVGアイコン画像がほしい。

だが、これが意外にも、簡単に見つからない。妙な素材サイトばかり見つかり、SVGコードを知りたければPro版を促され、課金を要求されるところが多い。そんなすさんだ世の中で、一閃の光が。。

それがこちらです。

Bootstrap Icons
Bootstrap 向けのオープンソース SVG アイコンライブラリ

(一時期はfontawesome使ったりしたこともあったけど、

あっちも無料だともっさりしたデザインのを使わされる形なのと、

あと意外と読み込みが重い。。

初めはよかったが、ページスピードを気にしていると、fontawesomeの部分だけが後出しで出てくるような表示になりイケてなかった)

スピナーボタンに数量増減のボタン機能をつける

スピナーのliquid

( さきほど作ったicon-minus.liquidとicon-plus.liquidのスニペットを{% render ‘icon-minus’ %}および{% render ‘icon-plus’ %}で呼び出して( 表示して )います。

<button class="quantity__button btnspinner spinner-down" name="minus" type="button" item_index="{{ item_index }}">
    {% render 'icon-minus' %}
</button>
<!--ここにもとの数値入力フォーム(セレクトボックス式)-->
<button class="quantity__button btnspinner spinner-up" name="plus" type="button" item_index="{{ item_index }}">
    {% render 'icon-plus' %}
</button>

js

//数量スピナーボタン(マイナス)
$('.spinner-down').on('click', function () {
  let current_qty = parseInt($(this).nextAll('input').val());
  let change_qty = current_qty - 1;
  $(this).nextAll('input').attr("value", change_qty);
  var item_index = $(this).attr("item_index");
  lineitemQuantity( item_index, change_qty )
});

//数量スピナーボタン(プラス)
$('.spinner-up').on('click', function () {
  let current_qty = parseInt($(this).prevAll('input').val());
  let change_qty = current_qty + 1;
  $(this).prevAll('input').attr("value", change_qty);
  var item_index = $(this).attr("item_index");
  lineitemQuantity( item_index, change_qty )
});

数量変更時の合計金額自動更新の処理:CartAPIを利用してjsを追記

こちらが公式から解説しているCart APIの仕様。

Cart API reference
Learn about the calls that the Cart API can make and the responses it will return.

ちょっと翻訳版を一読してみてほしいのだが、僕はこれを読んで、何度も

「で、結論コードは何て書けばいいの??」でした。

どうやら、jsの構文のfetch〜thenを用いて、上記リファレンスで解説しているパラメータをfetchに続けて以下のように読む必要があったようです。

  fetch("/cart/change", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(
      {
        line: line,
        quantity: quantity
      }),

postのbodyでvariantID( ここではline )を渡しているが、他にも line item key でもいけるようだ。

作成したjsに以下を追記する。

function lineitemQuantity (line, quantity){
  var quantity = quantity;
  fetch("/cart/change", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(
      {
        line: line,
        quantity: quantity
      }),
  }).then(() => {
    location.reload();
  });

fetch(“/cart/change”からはじまる構文で、Cart APIの”changeイベント”を呼ぶ処理をしている。

テーマのコアjs(例えばtheme.jsのような名前か、テーマ名”Empire”の場合はempire.jsのように命名されていることが多い)の中に、

カートページの数量入力の前後にマイナスとプラスのスピナーを設置したためボタン押下時に金額が更新されるようにするコードを追記。

個人的にはここの挙動を精査するのが一番しんどかった。

this.$el.on(‘click.cart-page’

とか、

this.$el.on(‘change.cart-page’

で検索したらヒットする行があれば、その下に以下を追記。

 this.$el.on('click.cart-page', '[btnspinner]', this._editItemQuantity);

カートページの数量入力の前後に、さきほど作成したマイナスとプラスのスピナーボタン押下時に金額が更新されるようにするコードだ。

前後で使用されている変数に合わせて改変すること!

ここでは、

[btnspinner]

で、スピナーボタンにつけた属性名を指定している。

以上です!

これでカートページ改修のときの一番の悩みは解消できるのではないでしょうか?

追記:jsにコードを追加して、数量上限設定を行う!

上記のjsだけでは数量を無限に(1,000でも10,000でも)入れられてしまいますので、上限の設定をする必要があったので、jsで制御する必要がありました。

以下のコードで、入力フォームがすでに0のときにはそれ以上マイナスにならないようにし、

プラスを連打しても5以上にならないような制御を入れています。

ストアによっては、さらに細かく、「Aというグループの商品は小型サイズだから10個までカートインできるけれど、Bという商品は大型なので1個しかカートインできない」など、

もっとスクリプトを書かないといけない可能性もあります!

//カートページの数量スピナーボタン(minus)
$('.spinner-down').on('click', function () {
  let current_qty = parseInt($(this).nextAll('input').val());
  let change_qty = 0;
  if(current_qty < 1){
    change_qty = 0;
  }
  else{
    change_qty = current_qty - 1;
  }
  $(this).nextAll('input').attr("value", change_qty);
  var item_index = $(this).attr("item_index");
  lineitemQuantity( item_index, change_qty )
});

//カートページの数量スピナーボタン(plus)
$('.spinner-up').on('click', function () {
  let current_qty = parseInt($(this).prevAll('input').val());
  let change_qty = 0;
  if(current_qty > 4){
    change_qty = 5;
  }
  else{
    change_qty = current_qty + 1;
  }
  $(this).prevAll('input').attr("value", change_qty);
  var item_index = $(this).attr("item_index");
  lineitemQuantity( item_index, change_qty )
});
タイトルとURLをコピーしました