ShopifyでタグUIのカテゴリリストを作る

ShopifyでタグUIのカテゴリリストを作る

Shopifyではタグやメタフィールドなど、商品に関する情報をたくさん設定できます。それらのカテゴライズをタグUIのリストとして表示しよう、というのが今回の記事です。

やりたいこと

たとえば、こんな感じでゲームソフトを販売しているストアがあるとします。

ゲームソフトでよくあるカテゴリとしては、ゲームのジャンルやメーカー名(販売元)、対応機種などですね。
そして、商品ごとのカタログPDFをダウンロードできるページなどといった、商品のカテゴリを紐づけたタグで絞り込みたいコンテンツがあったりします。

で、せっかくタグをつけたのなら、こんな感じのタグUIなんかも実装したいです。

というわけで、テーマをカスタマイズしていきたいと思います!

ちなみにカタログPDFダウンロードページの作例記事も書きました。

タグのコンポーネントをスニペットファイルにする

タグUIは、商品ページや商品の一覧(コレクション)、よくある質問などなど、サイト内のあちこちで使用することが想定されます。
表示するデータだけを渡して、どこからでも呼び出せるような設計にしておいたほうが使い勝手が良いと思います。
そこで、スニペットファイルにします。

今回は、snippets/tags.liquidというスニペットファイルを用意します。
ul要素ごとコンポーネントにしてしまうか、ループするli要素のみをコンポーネントとするかは、それぞれの設計思想によるかと思います。
私の場合は、この規模のリストアイテムを異なるclassの親要素に入れることはないかなぁと思ったので、ul要素ごとひとまとめにしています。

snippets/tags.liquidのコード

今回紹介するサンプルコードは、「ブログ記事に、その記事につけられたタグを表示する」という想定で書いています。
ブログ記事以外でも同様に、スニペットに任意のデータを渡して表示することができます。

<div class="tags">
  <i class="fa-solid fa-tag"></i>
  <ul class="ul-tags">
    {% for tag in tags %}
      <li>
        {%- assign tag_escape = tag | replace: '・', '-' -%}
        {%- assign tag_html = "<span>" | append: tag | append: "</span>" -%}
        {%- if url != blank -%}
          <a href="{{ url }}tagged/{{ tag_escape }}" class="color-base">{{ tag }}</a>
        {%- else -%}
          {{ tag_html | link_to_tag: tag | replace: '<a', '<a class="color-base"' }}
        {%- endif -%}
      {% endfor %}
    </li>
  </ul>
</div>

タグUIをレンダリングする場所を決める

リストを表示したい場所に下記のコードを記述します。
ここではarticle.tagsとなっていますが、これは「ブログ記事のタグ」の場合です。

なんのデータを使いたいかによって書き方が変わってくるので、Shopifyのドキュメントを参照し、適宜、渡したいデータによってオブジェクトを変更してください。

{%- liquid
if article.tags.size > 0
assign tags = true
else
assign tags = false
endif
-%}

{%- if tags -%}
  {%- render 'tags', tags: article.tags, url: '/blogs/catalogue/' -%}
{%- endif -%}

コードの説明

呼び出し元のコード

タグがないときにはタグUIを表示したくないので、まずは当該ブログ記事にタグが設定されているかどうかを判定します。

if article.tags.size > 0
assign tags = true

通常、スニペットファイルを呼び出してその内容をそのままレンダリングする場合は、とてもシンプルです。
スニペットファイルの名前を指定するだけです。

{%- render 'tags' -%}

このスニペットファイルの中で使いたいデータを、引数に入れて渡します。
渡す引数は複数設定することができます。

{%- render 'tags', tags: article.tags, url: '/blogs/catalogue/' -%}

上記は、変数tagsarticle.tags配列を、
そして、変数url/blogs/catalogue/という文字列を入れてあげています。

タグだけでなく、商品タイプとか、メタフィールドのリストとかも使用可能です。

スニペットのコード

変数tagsで渡された配列を、そのまま使うことができます。
もちろん、スニペットファイルの中でさらに別の変数にassignし直したり、配列を加工したりすることもできます。

今回は、そのまま配列をループしてリストアイテムを出していきます。

{% for tag in tags %}

タグの名前を表示するだけでなく、変数urlが渡されている場合にはそのタグへのリンクも表示するようにしています。
もっとも、サイト設計で常にリンクするルールなのであれば、分岐は必要ありません。

        {%- if url != blank -%}
          <a href="{{ url }}tagged/{{ tag_escape }}" class="color-base">{{ tag }}</a>

ブログがいくつかあるストアでは、ブログの種類によってタグページのディレクトリ名も異なります。
たとえば、お知らせ、よくあるご質問、カタログダウンロードなどのコンテンツがある場合などです。
そこで、ブログ記事につけられたタグを取得するときは、そのブログ記事テンプレートからURLの情報を指定しているわけです。

それ以外にも、コレクションなどさまざまなタグページがさまざまなURLで存在しています。
さらに、ページによってHTMLの記述を変えたい場合には、if文で分岐して、別のコードを書くこともできます。

        {%- else -%}
          {{ tag_html | link_to_tag: tag | replace: '<a', '<a class="color-base"' }}
        {%- endif -%}

Liquidタグ(タグタグややこしいですね)は便利で、タグのURLを直接取得してa要素をレンダリングすることができます。その場合classやカスタムデータ属性などがつけられないので、開始タグをreplaceして書き換えています。

ところで、なぜ受け渡されたデータに対して、下記のような加工をしているのでしょうか?

        {%- assign tag_escape = tag | replace: '・', '-' -%}

ここは私が軽くつまずいたところなのですが…
日本語のタグではときどき中黒「・」が含まれることがあります。
ところが、タグのURLには中黒はそのまま使われず、半角ハイフン「-」に置き換えられてしまいます。

なぜかリンク先が404NotFoundになるぞ…ということで少し悩んでしまったのでした。

というわけであらかじめreplaceして、タグ名を表示する部分とURLにする部分で別の文字列を用意しています。

それにしても本当にShopifyのAPIが充実していて、いろんなデータを引っ張ってくるのがめちゃめちゃ簡単なうえ、Liquidも書くのが簡単で助かります!

タグUIのCSSサンプル

スタイルは好きなCSSファイルに書いてもいいし、スコープを絞りたかったらtags.liquidファイルにそのままstyle要素として書いてしまうという手もあります。


  .tags {
    display: flex;
    margin: 1em 0;
  }

  .tags i {
    flex-shrink: 1;
    padding: 0.4em 0.2em 0 0;
  }

  .ul-tags {
    flex-grow: 1;
  }

  .ul-tags > li {
    display: inline-block;
    margin: 0.2em;
    padding: 0.2em 0.6em;
    background: var(--gradient-base-background-2);
    font-size: 1.2rem;
  }

どんなリストでも思いのまま表示できる!

ちょうどいい感じにスニペットの使い方の基本みたいな内容なので、これを覚えておけばその他のリンクリストなども汎用的に作ることができます。

もともとコレクションの商品一覧や検索結果一覧も、カードUIがスニペット化されているので、たとえばブログ記事一覧のカードUIをスニペットにしておいて、検索結果ではブログ記事アイテムの場合に分岐してそっちのカードスニペットを流用する、といったことも可能ですね。

検索結果のカードのコンテンツ別カスタマイズも、そのうち記事を書きたいと思います!