カートページ統合

概要

この記事では、カートページへのプランと、カートページへのモーダルプランをレンダリングするロジックについて説明します。

所要時間:約1時間

設定


  1. cartのitem列を見つけます。
    1. カートに商品が入っている状態でカートページに移動します。アイテムのタイトルを見つけます。
    2. 右クリックしてから、右クリックメニューの[検証]をクリックします。
    3. elementタブで、列全体が強調表示されるまで要素にカーソルを合わせます。これには、商品のタイトル、数量、画像等が含まれます。
    4. クラス名を見つけます。これは、ステートメント class= の後の属性名になります。
    5. クラス名をコピーして、後で使用するために別の場所に貼り付ける等保存しておきます。

  1. cartのitemタイトルを見つけます。
    1. カートに商品が入っている状態でカートページに移動します。アイテムのタイトルを見つけます。
    2. 右クリックしてから、右クリックメニューの[検証]をクリックします。
    3. elementタブで、タイトルが強調表示されるまで要素にカーソルを合わせます。
    4. クラス名を見つけます。これは、ステートメント class= の後の属性名になります。
    5. クラス名をコピーして、後で使用するために別の場所に貼り付ける等保存しておきます。

  1. cartのitem数量[quantity]を見つけます。
    1. カートに商品が入っている状態でカートページに移動します。アイテムのタイトルを見つけます。
    2. 右クリックしてから、右クリックメニューの[検証]をクリックします。
    3. elementタブで、数量が強調表示されるまで要素にカーソルを合わせます。
      NOTE: 通常、これは <input> タグ内にあります。
    4. クラス名を見つけます。これは、ステートメント class= の後の属性名になります。
    5. クラス名をコピーして、後で使用するために別の場所に貼り付ける等保存しておきます。

  1. (コード エディターの左側のサイドバーで)、スニペットディレクトリを見つけて、[新しいスニペットを追加する] をクリックし、proteger-cart-integration という名前を付けます。
  2. 下記のコードを挿入します。
<script>
    //DOMContentLoadedでスクリプトを実行し、サイトのロード時間に影響を与えないようにする
    window.addEventListener('DOMContentLoaded', function(){
   
     //protegerのプランを表示する前に、protegerがウィンドウ内に存在し、アクティブな通貨がJPYであるかどうかをチェックします。
     if (window.Proteger && window.ProtegerShopify && window.ProtegerCart && window.Shopify.currency.active === 'JPY') {
   
      /*****************************************/
      /* Global Variables - THEME SPECIFIC */
      /*****************************************/
   
      let cartRowItem = 'ADD SELECTOR HERE'; // cartのitem列のセレクタに変更
      let cartRowItemTitle = 'ADD SELECTOR HERE'; // cartのitemタイトルのセレクタに変更
      let cartRowItemQuantity = 'ADD SELECTOR HERE'; // cartのitem数量のセレクタに変更
      
      /***************************************/
      /* Global Variables - No Change Needed */
      /***************************************/
      let planClass = 'proteger-cart-plan'; // 各 proteger プランに割り当てられるクラス
      let localCart = {{ cart | json }}; // 初期ロード時のShopify Cart Object
   
      // safe機能
      if(!localCart) return;
   
      /***********************/
      /* util functions */
      /***********************/
      // findAll(element) -ドキュメント内の子要素または親要素を検索するためのquerySelectorAll
      function findAll(elementToFind, parentElement) {
       const items = parentElement ? parentElement.querySelectorAll(elementToFind) : document.querySelectorAll(elementToFind);
       return items;
      }
   
      /***********************/
      /* createElement */
      /***********************/
      // createElement(product) - product 要素を取り込み、proteger プラン 要素を作成 + プランを追加する
      function createElement(product, index){
   
       // 新しいプランを作成する前に、既存のプランを削除
       let protegerPlan = product.querySelector('.' + planClass);
       if (protegerPlan) protegerPlan.remove();
   
       // variantIdを取得
       let variantId = localCart.items[index].id;
   
       // 数量を取得
       let quantity = product.querySelector(cartRowItemQuantity).value;
   
       //プランを追加する親コンテナ
       let container = product.querySelector(cartRowItemTitle);
   
       // safe機能
       if(!variantId || !quantity || !container) return;
   
       // 新規に要素を作成し、class、data-proteger-variant、data-proteger-quantity属性を設定する。
       let newProtegerPlan = document.createElement('div');
       newProtegerPlan.className = planClass;
       newProtegerPlan.setAttribute('data-proteger-variant', variantId);
       newProtegerPlan.setAttribute('data-proteger-quantity', quantity);
   
       // コンテナ要素にオファーを追加する (THEME SPECIFIC)
       container.append(newProtegerPlan);
   
      }
   
      /************************/
      /* Handle Styling */
      /************************/
      // すべての cartRowItemsを検索し、プランにスタイルを適用
      function handleStyling() {
   
       findAll(cartRowItem).forEach(function(el, index) {
   
        // itemのタイトルを取得
        let title = el.querySelector(cartRowItemTitle);
   
        // safe機能
        if(!title) return;
   
        // protegerプランであればリンクを削除
        if (title.innerText.toLowerCase().indexOf('proteger') > -1) {
   
         // pointerEventを無効化
         title.style.pointerEvents = 'none';
         const image = el.querySelector('.cart-item__media');
         if (image) image.style.pointerEvents = 'none';
   
        } else {
         // 各itemにプラン要素を作成
         createElement(el, index);
        }
   
       });
   
      }
   
      /************************/
      /* initializeCartPlan */
      /************************/
      // handleStylingを実行し、カートにある全てのプランを見つけ、正規化とバランス調整
      function initializeCartPlan() {
   
       // スタイリング、プラン要素作成
       handleStyling();
   
       // 全てのプラン要素を検索
       findAll('.' + planClass).forEach(function(el){
   
        // atrributeを取得
        let variantId = el.getAttribute('data-proteger-variant');
        let quantity = el.getAttribute('data-proteger-quantity');
   
        // もしプランがカートにある場合return
         if (ProtegerCart.warrantyAlreadyInCart(variantId, localCart.items)) {
          return;
        }
   
        // ボタンをレンダリング
        ProtegerCart.renderSimplePlan(el, {
          referenceId: variantId,
          quantity: quantity,
        });
       })
   
        // 正規化により、商品とプランを1:1にする
        ProtegerCart.normalizeCart({cart: localCart, balance: true}, function() {
          ProtegerCart.hardRefresh();
        });
      }

      // カートの内容が変わった場合のイベントをlisten
      window.addEventListener("normalizeCart", function () {
        ProtegerCart.getShopifyCart(function(newCart) {
          localCart = newCart;
          initializeCartPlan();
        });
      });
   
      // 初回レンダリング時
      initializeCartPlan();
   
     }
    });
   
   </script>
  1. proteger-cart-integration.liquid 内で次のコードを変更します (12 ~ 14 行目)。
    1. cartRowItemADD SELECTOR HERE を、上記で取得したcartのitem列クラスに置き換えます。
      NOTE: クラス名には css セレクターを使用する必要があります。取得したクラスを適切な構文に変換してください。前方に .ピリオドを付けてください。
    2. cartRowItemTitleADD SELECTOR HERE を、上記で取得したcartのitemタイトルクラスに置き換えます。
      NOTE: クラス名には css セレクターを使用する必要があります。取得したクラスを適切な構文に変換してください。前方に .ピリオドを付けてください。
    3. cartRowItemQuantityADD SELECTOR HERE を、上記で取得したcartのitemタイトルクラスに置き換えます。
      NOTE: クラス名には css セレクターを使用する必要があります。取得したクラスを適切な構文に変換してください。前方に .ピリオドを付けてください。
let cartRowItem = 'ADD SELECTOR HERE'; // cartのitem列のセレクタに変更
let cartRowItemTitle = 'ADD SELECTOR HERE'; // cartのitemタイトルのセレクタに変更
let cartRowItemQuantity = 'ADD SELECTOR HERE'; // cartのitem数量のセレクタに変更
  1. Ajaxカートを利用の場合に必要な記述を説明します。
    Ajaxカートをお使いで無い場合は次のセクションに進んで下さい。
    Ajaxカートとはカートページで商品の数や商品の削除を行った時にページが再読み込みされない事を指します。
    カートページ内で数量が更新された時、Ajaxカートはページを更新しません。
    カートに変更があった時にinitializeCartPlanの処理を行う必要があります。
  2. カスタムイベントをディスパッチするコード内の場所を見つける必要があります。
    Shopifyテーマのどこでカートアイテムの数量が更新されているかを見つけ、イベントをprotegerにディスパッチして、新しいShopifyカートオブジェクトを読み込ませます。
    1. Dawnテーマの場合はcart.jsにカートページでの更新の記述があるので、そこにディスパッチのコードを追記します。
window.dispatchEvent(new CustomEvent('normalizeCart'));

確認


  1. [ストアをプレビュー]をクリックしてプレビューを開きます。
  2. 保証対象製品ページに移動します。
  3. 製品のみをカートに追加します。
  4. カートページでプラン表示のボタンが表示されているのを確認します。

  1. ボタンを押すとモーダルが表示される事を確認します。

  1. モーダルからプランを追加するとカートに追加される事を確認します。

  1. 製品の数量を変更するとプランの数量も自動で変更される事を確認します。

  1. 完了です 🎉

📘

NOTE

お困りの際は担当者または下記のメールアドレスにいつでもご連絡下さい。
[email protected]