🙌

Shopify でランキング表示を行う方法について調べてみた

2024/04/03に公開

はじめに

今回は、Shopify でランキング表示を行う方法について調べてみました。

それでは、頑張っていきましょう。

Shopify のランキング表示とは

Shopify におけるランキング表示とは、以下の画像のようにコレクション表示の中にランキングのアイコンが表示されることを指します。

上記のような表示は、日本の EC サイトでは非常によく見るものであるため、Shopify のストア構築者の中にはランキング表示の作成を依頼された方もいらっしゃるかもしれません。

今回は、上記のようなランキング表示を行う方法をコーディングで作成する方法と、アプリを用いて作成する方法について解説していきます。

以下のアプリストアから引用しました。
https://apps.shopify.com/sa-022-ur-ranking-app?from=hp-list&locale=ja

コーディングで作成

まずは、コーディングで作成する方法について解説していきます。

といっても、まずは Shopify の管理画面でコレクションを作成するところから始めていきます。

コレクションの作成

コレクションページ右上のコレクションを作成するから、コレクションを作成していきましょう。

コレクションの種類は手動自動があります。
コレクションの定義だけで考えるなら、自動で全ての商品を選択して、ベストセラー順に並び替えれば良いでしょう。

実際には、ストア側で手動で設定したい部分があるかと思うので、今回は手動で作成していきましょう。

上記のように手動でいくつかの商品を設定して、ベストセラー順に並び替えて下さい。

ここまでで、コレクションの作成は完了です。次に、ランキング表示の作成を行っていきましょう。

ランキング表示の作成

それでは次に、ランキングの作成を行っていきましょう。

一番簡単な方法は、既存のランキングセクションに手を加えることです。

オンラインストアのテーマの三点リーダーのコードを編集から、コードの編集画面に移動しましょう。

コードの編集画面に移動したら、main-collection-product-grid.liquidに移動しましょう。
このコードは、既存の collection のコードになります。

このコードは、コレクションページでのみ呼び出されるので、collectionで Liquid のコレクションオブジェクトにアクセスすることができます。

以下の部分で、コレクションを表示しています。

{%- for product in collection.products -%}
  {% assign lazy_load = false %}
  {%- if forloop.index > 2 -%}
    {%- assign lazy_load = true -%}
  {%- endif -%}
  <li
    class="grid__item{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
    {% if settings.animations_reveal_on_scroll %}
      data-cascade
      style="--animation-order: {{ forloop.index }};"
    {% endif %}
  >
    {% render 'card-product',
      card_product: product,
      media_aspect_ratio: section.settings.image_ratio,
      image_shape: section.settings.image_shape,
      show_secondary_image: section.settings.show_secondary_image,
      show_vendor: section.settings.show_vendor,
      show_rating: section.settings.show_rating,
      lazy_load: lazy_load,
      show_quick_add: section.settings.enable_quick_add,
      section_id: section.id
    %}
  </li>
{%- endfor -%}

上記で card-product というスニペットを呼びだしています。

このコレクションのループの中で forloop.indexを用いるとインデックス番号を取得することができるので、以下のように条件に応じてランキングのアイコンを表示させましょう。

{%- case forloop.index -%}
  {%- when 1 -%}
   {% render 'star' %}
...

このようにコーディングを行うことで、ランキング表示を行うことができます。

参考までに、main-collection-product-grid.liquidの全体を載せておきます。

{{ 'template-collection.css' | asset_url | stylesheet_tag }}
{{ 'component-loading-overlay.css' | asset_url | stylesheet_tag }}
{{ 'component-card.css' | asset_url | stylesheet_tag }}
{{ 'component-price.css' | asset_url | stylesheet_tag }}

{% if section.settings.image_shape == 'blob' %}
  {{ 'mask-blobs.css' | asset_url | stylesheet_tag }}
{%- endif -%}

{%- if section.settings.enable_quick_add -%}
  {{ 'quick-add.css' | asset_url | stylesheet_tag }}
  <script src="{{ 'quick-add.js' | asset_url }}" defer="defer"></script>
  <script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script>
{%- endif -%}

{%- style -%}
  .section-{{ section.id }}-padding {
    padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;
    padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;
  }

  @media screen and (min-width: 750px) {
    .section-{{ section.id }}-padding {
      padding-top: {{ section.settings.padding_top }}px;
      padding-bottom: {{ section.settings.padding_bottom }}px;
    }
  }
{%- endstyle -%}

<div class="section-{{ section.id }}-padding">
  {%- paginate collection.products by section.settings.products_per_page -%}
    {% comment %} Sort is the first tabbable element when filter type is vertical {% endcomment %}
    {%- if section.settings.enable_sorting and section.settings.filter_type == 'vertical' -%}
      <facet-filters-form class="facets facets-vertical-sort page-width small-hide no-js-hidden">
        <form class="facets-vertical-form" id="FacetSortForm">
          <div class="facet-filters sorting caption">
            <div class="facet-filters__field">
              <h2 class="facet-filters__label caption-large text-body">
                <label for="SortBy">{{ 'products.facets.sort_by_label' | t }}</label>
              </h2>
              <div class="select">
                {%- assign sort_by = collection.sort_by | default: collection.default_sort_by -%}
                <select
                  name="sort_by"
                  class="facet-filters__sort select__select caption-large"
                  id="SortBy"
                  aria-describedby="a11y-refresh-page-message"
                >
                  {%- for option in collection.sort_options -%}
                    <option
                      value="{{ option.value | escape }}"
                      {% if option.value == sort_by %}
                        selected="selected"
                      {% endif %}
                    >
                      {{ option.name | escape }}
                    </option>
                  {%- endfor -%}
                </select>
                {% render 'icon-caret' %}
              </div>
            </div>
            <noscript>
              <button type="submit" class="facets__button-no-js button button--secondary">
                {{ 'products.facets.sort_button' | t }}
              </button>
            </noscript>
          </div>

          <div class="product-count-vertical light" role="status">
            <h2 class="product-count__text text-body">
              <span id="ProductCountDesktop">
                {%- if collection.results_count -%}
                  {{
                    'templates.search.results_with_count'
                    | t: terms: collection.terms, count: collection.results_count
                  }}
                {%- elsif collection.products_count == collection.all_products_count -%}
                  {{ 'products.facets.product_count_simple' | t: count: collection.products_count }}
                {%- else -%}
                  {{
                    'products.facets.product_count'
                    | t: product_count: collection.products_count, count: collection.all_products_count
                  }}
                {%- endif -%}
              </span>
            </h2>
            <div class="loading-overlay__spinner">
              <svg
                aria-hidden="true"
                focusable="false"
                class="spinner"
                viewBox="0 0 66 66"
                xmlns="http://www.w3.org/2000/svg"
              >
                <circle class="path" fill="none" stroke-width="6" cx="33" cy="33" r="30"></circle>
              </svg>
            </div>
          </div>
        </form>
      </facet-filters-form>
    {%- endif -%}

    <div class="{% if section.settings.filter_type == 'vertical' %} facets-vertical page-width{% endif %}">
      {{ 'component-facets.css' | asset_url | stylesheet_tag }}
      <script src="{{ 'facets.js' | asset_url }}" defer="defer"></script>
      {%- if section.settings.enable_filtering or section.settings.enable_sorting -%}
        <aside
          aria-labelledby="verticalTitle"
          class="facets-wrapper{% unless section.settings.enable_filtering %} facets-wrapper--no-filters{% endunless %}{% if section.settings.filter_type != 'vertical' %} page-width{% endif %}"
          id="main-collection-filters"
          data-id="{{ section.id }}"
        >
          {% render 'facets',
            results: collection,
            enable_filtering: section.settings.enable_filtering,
            enable_sorting: section.settings.enable_sorting,
            filter_type: section.settings.filter_type,
            paginate: paginate
          %}
        </aside>
      {%- endif -%}

      <div
        class="product-grid-container{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
        id="ProductGridContainer"
        {% if settings.animations_reveal_on_scroll %}
          data-cascade
        {% endif %}
      >
        {%- if collection.products.size == 0 -%}
          <div class="collection collection--empty page-width" id="product-grid" data-id="{{ section.id }}">
            <div class="loading-overlay gradient"></div>
            <div class="title-wrapper center">
              <h2 class="title title--primary">
                {{ 'sections.collection_template.empty' | t -}}
                <br>
                {{
                  'sections.collection_template.use_fewer_filters_html'
                  | t: link: collection.url, class: 'underlined-link link'
                }}
              </h2>
            </div>
          </div>
        {%- else -%}
          <div class="collection{% if section.settings.filter_type != 'vertical' %} page-width{% endif %}">
            <div class="loading-overlay gradient"></div>

            <ul
              id="product-grid"
              data-id="{{ section.id }}"
              class="
                grid product-grid grid--{{ section.settings.columns_mobile }}-col-tablet-down
                grid--{{ section.settings.columns_desktop }}-col-desktop
              "
            >
              {%- for product in collection.products -%}
                {% assign lazy_load = false %}
                {%- if forloop.index > 2 -%}
                  {%- assign lazy_load = true -%}
                {%- endif -%}
                <li
                  class="grid__item{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
                  {% if settings.animations_reveal_on_scroll %}
                    data-cascade
                    style="--animation-order: {{ forloop.index }};"
                  {% endif %}
                >
                  {% render 'card-product',
                    card_product: product,
                    media_aspect_ratio: section.settings.image_ratio,
                    image_shape: section.settings.image_shape,
                    show_secondary_image: section.settings.show_secondary_image,
                    show_vendor: section.settings.show_vendor,
                    show_rating: section.settings.show_rating,
                    lazy_load: lazy_load,
                    show_quick_add: section.settings.enable_quick_add,
                    section_id: section.id
                  %}
                </li>
              {%- endfor -%}
            </ul>

            {%- if paginate.pages > 1 -%}
              {% render 'pagination', paginate: paginate, anchor: '' %}
            {%- endif -%}
          </div>
        {%- endif -%}
      </div>
    </div>
  {%- endpaginate -%}
  {% if section.settings.image_shape == 'arch' %}
    {% render 'mask-arch' %}
  {%- endif -%}
</div>

{% schema %}
{
  "name": "t:sections.main-collection-product-grid.name",
  "class": "section",
  "settings": [
    {
      "type": "range",
      "id": "products_per_page",
      "min": 8,
      "max": 24,
      "step": 4,
      "default": 16,
      "label": "t:sections.main-collection-product-grid.settings.products_per_page.label"
    },
    {
      "type": "range",
      "id": "columns_desktop",
      "min": 1,
      "max": 5,
      "step": 1,
      "default": 4,
      "label": "t:sections.main-collection-product-grid.settings.columns_desktop.label"
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header__3.content"
    },
    {
      "type": "select",
      "id": "image_ratio",
      "options": [
        {
          "value": "adapt",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__1.label"
        },
        {
          "value": "portrait",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__2.label"
        },
        {
          "value": "square",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__3.label"
        }
      ],
      "default": "adapt",
      "label": "t:sections.main-collection-product-grid.settings.image_ratio.label"
    },
    {
      "type": "select",
      "id": "image_shape",
      "options": [
        {
          "value": "default",
          "label": "t:sections.all.image_shape.options__1.label"
        },
        {
          "value": "arch",
          "label": "t:sections.all.image_shape.options__2.label"
        },
        {
          "value": "blob",
          "label": "t:sections.all.image_shape.options__3.label"
        },
        {
          "value": "chevronleft",
          "label": "t:sections.all.image_shape.options__4.label"
        },
        {
          "value": "chevronright",
          "label": "t:sections.all.image_shape.options__5.label"
        },
        {
          "value": "diamond",
          "label": "t:sections.all.image_shape.options__6.label"
        },
        {
          "value": "parallelogram",
          "label": "t:sections.all.image_shape.options__7.label"
        },
        {
          "value": "round",
          "label": "t:sections.all.image_shape.options__8.label"
        }
      ],
      "default": "default",
      "label": "t:sections.all.image_shape.label",
      "info": "t:sections.all.image_shape.info"
    },
    {
      "type": "checkbox",
      "id": "show_secondary_image",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_secondary_image.label"
    },
    {
      "type": "checkbox",
      "id": "show_vendor",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_vendor.label"
    },
    {
      "type": "checkbox",
      "id": "show_rating",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_rating.label",
      "info": "t:sections.main-collection-product-grid.settings.show_rating.info"
    },
    {
      "type": "checkbox",
      "id": "enable_quick_add",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.enable_quick_buy.label"
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header__1.content"
    },
    {
      "type": "checkbox",
      "id": "enable_filtering",
      "default": true,
      "label": "t:sections.main-collection-product-grid.settings.enable_filtering.label",
      "info": "t:sections.main-collection-product-grid.settings.enable_filtering.info"
    },
    {
      "type": "select",
      "id": "filter_type",
      "options": [
        {
          "value": "horizontal",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__1.label"
        },
        {
          "value": "vertical",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__2.label"
        },
        {
          "value": "drawer",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__3.label"
        }
      ],
      "default": "horizontal",
      "label": "t:sections.main-collection-product-grid.settings.filter_type.label",
      "info": "t:sections.main-collection-product-grid.settings.filter_type.info"
    },
    {
      "type": "checkbox",
      "id": "enable_sorting",
      "default": true,
      "label": "t:sections.main-collection-product-grid.settings.enable_sorting.label"
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header_mobile.content"
    },
    {
      "type": "select",
      "id": "columns_mobile",
      "default": "2",
      "label": "t:sections.main-collection-product-grid.settings.columns_mobile.label",
      "options": [
        {
          "value": "1",
          "label": "t:sections.main-collection-product-grid.settings.columns_mobile.options__1.label"
        },
        {
          "value": "2",
          "label": "t:sections.main-collection-product-grid.settings.columns_mobile.options__2.label"
        }
      ]
    },
    {
      "type": "header",
      "content": "t:sections.all.padding.section_padding_heading"
    },
    {
      "type": "range",
      "id": "padding_top",
      "min": 0,
      "max": 100,
      "step": 4,
      "unit": "px",
      "label": "t:sections.all.padding.padding_top",
      "default": 36
    },
    {
      "type": "range",
      "id": "padding_bottom",
      "min": 0,
      "max": 100,
      "step": 4,
      "unit": "px",
      "label": "t:sections.all.padding.padding_bottom",
      "default": 36
    }
  ]
}
{% endschema %}

それでは次に、アプリを用いてランキング表示を行う方法について解説していきます。

ランキング表示ができるアプリを解説

今回紹介するアプリは、「シンプルランキング表示|お手軽ベストセラー」と「らくらくランキング表示アプリ|リテリア Ranking」の二つになります。

それぞれ、以下の記事を参考にしています。

https://unreact.jp/blog/shopify-blog-bundle-app

https://unreact.jp/blog/shopify-app-ranking

それでは、アプリについて解説していきます。

シンプルランキング表示|お手軽ベストセラー

https://apps.shopify.com/sa-022-ur-ranking-app?locale=ja

まずは、シンプルランキング表示|お手軽ベストセラーについて解説していきます。

こちらは、以下のようなランキング表示を簡単に実現することができます。

また、ラベルの種類も豊富で、ラベルの位置も調整することができます。

こちらのアプリは Shopify のアプリブロックを使用しているアプリなので、基本的にはアプリブロックをストアに追加するだけで利用することが可能です。

以下に、具体的な編集項目をまとめていきます。

見出しテキストについて

こちらのアプリは、ランキング表示とは別に見出しテキストを設定することが可能です。

見出しテキストは、以下の項目を編集することができます。

  • 見出しの大きさ(PC)
  • 見出しの大きさ(スマホ)
  • 見出しの色
  • 見出しの上部の余白
  • 見出しの下部の余白

かなりカスタマイズできる項目は多いですね。

それでは次に、ランキング表示のアプリブロックについて解説していきます。

ランキング表示について

ランキング表示のアプリブロックは、基本的にアプリブロックにランキングを設定するだけで設定は完了です。

順位ラベルの種類を設定することができます。以下の四つの順位ラベルから選択することができます。

カスタマイズできる項目は以下になります。

  • コレクション
  • 順位ラベルの種類
  • 順位テキストの色
    • こちらは、1 位・2 位・3 位と 4 位以下の四つの色を選択することが可能
  • 順位ラベルの種類
    • 「左上」「右上」「左下」「右下」の 4 種類から選択可能
  • 商品の表示数
  • 商品間の余白
    • 「横」「縦」から選択可能
  • 縦横比
  • マウスオーバー時の挙動
  • 商品名のテキストサイズ
  • 商品名のテキストの色
  • 値段のテキストサイズ
  • 売り切れ時の表示テキスト
  • アプリブロック間の余白設定

このように、カスタマイズできる項目がかなり多いので、かなり使いやすいアプリだと思います。

次に、らくらくランキング表示アプリ|リテリア Rankingについて解説していきます。「

らくらくランキング表示アプリ|リテリア Ranking

こちらも、先ほどのアプリと殆ど同様の機能を持つ Shopify アプリです。

https://apps.shopify.com/ranking?locale=ja

以下の項目が編集可能です。

  • 順位アイコンの形
  • 色商品の表示数
  • 商品表示の列数(PC・スマホそれぞれで設定可能)
  • 商品間の余白
  • 商品のスライダー表示(左右にスクロール)
  • 商品画像の縦横比
  • 商品名・値段テキストのサイズ・色

列数を変更することができるので、下記のようなランキング表示を行うことができます。

終わりに

ここまでで、Shopify のランキング表示についての解説は終了です。お疲れさまでした。

Discussion