Shopify の Liquid イントロダクション

Liquid とは Shopify のテンプレート言語のひとつで、Shopify のテーマのバックボーンとなっているものです。Shopify ストアのデータと HTML を橋渡しするために使われます。 これにより、オンラインストア上で商品やその画像のデータを実際のウェブサイト上に表示することができます。

Chapter 1 Liquid について概要

Liquid はテンプレート言語と呼ばれることもあり、またテンプレートエンジンと呼ばれることもありますが、どちらも正解といえます。ただ Liquid には他のプログラミング言語同様、独自の文法があり、ループや変数などと相互作用して動き HTML をアウトプットしたりするため PHP などのようなウェブに特化し言語と呼べます。

しかし、Liquid は他のプラグラミング言語とは違いステイトのようなコンセプトはなく、必ずしも自由度が高くないため、他のプログラミング言語に親しんできた人にとっては戸惑う所があるかもしれません。 ただこの制限は意図的に設計されたものであり、Shopify というプラットフォームに最適になるように作られました。

Liquid の機能

Liquid は HTML ファイルと Shopify ストアで登録されたデータを橋渡しを行います。 煩わしいデータの処理をしなくても、商品などといった特定の情報へのアクセスをシンプルにしてくれます。product.liquidのテンプレートは、その商品ページ上で、現在見ているその商品・・・・のデータの必要な情報に簡単にアクセスしてくれます。しかも、その実際の商品のデータの詳細ついての予め知っておく必要はありません。

このテンプレート機能により、商品データが入れ替わっても、商品数が増えても同じように必要な情報を抜き出して表示することができます。 つまり、何百・何千という商品数が増えても、そのたびに、増えた商品に合わせて、商品ページを手動で作成する必要がなくなります。

Shopify プラットフォーム(Shopify のシステム)は、テンプレートに書かれた Liquid コードをもとに商品のデータを読み込み HTML データとして表示します。

このテンプレート言語のメリットは商品について知ることなく、ページをデザインができることです。テンプレートを他のまったく違うクライアントのストアでも使うことも可能になります。

Liquid ファイルの拡張子とデリミタ −(区切り記号)

Liquid コードによるファイルには.liquid の拡張子が付きます。Liquid ファイルの中身は通常の HTML と Liquid コードが合わさったものです。通常の HTML と Liquid コードは見分けやすいように設計されています。 通常の HTML タグは < > で囲いますが、Liquid コードは別の二種類の括弧で囲います。

アウトプットには{ { } } の括弧はデータをつかいます。

if 文や loop 文のような論理式には{% %} の括弧とパーセンテージ記号をつかいます。

この区切り括弧(タグ)は プレースホルダーとして考えることができます。 なぜなら、この Liquid タグ(プレースホルダー)に、最終的にブラウザで見れる状態へ出力される際には HTML のコードが差し替えられることになります。

Output

アウトプットのタグはストアにあるデータを持ってきてテンプレートファイルに出力するためのものです。 例えば以下のような例です


<h2>{{ product.title }}</h2>

この Liquid タグだと、今見ている商品ページの商品のタイトルが見出し 2 h2 タグの html として表示されることになります。 例えば商品名が『夏用 T シャツ』と Shopify 上で登録してあれば、その商品ページには <h2> 夏用 T シャツ </h2> の HTML の形で出力されることになります。

フィルターなどを使わない限りは基本的にアウトプットはstringとして出力されます。 *フィルターについては後述。

オブジェクトとプロパティ

次はドット(.)の使いかたです。 ドットを使うことにより、Japascript のような言語と同じようにオブジェクトのプロパティにアクセスすることができます。

例えばshopのオブジェクトは、Shopify の管理画面で登録されたプロパティが複数あります。shopのオブジェクトには下記のようにshop の後にドット(.)をつけて各プロパティにアクセスできます。


shop.address
shop.coollections_count
shop.currensy
shop.description
shop.domain
shop.email
shop.enabled_payment_types
shop.metafields
shop.money_format
shop.money_with_currency_format
shop.name
shop.policies
shop.password_message
shop.permanent_domain
shop.products_count
shop.types
shop.secure_url
shop.vendors
shop.locale

コレクションプロパティ

  • shop.enabled_payment_types
  • shop.metafields
  • shop.types

上記のプロパティは-s がついて複数形になります。

これらのプロパティは Liquid collections で一つのstringを返す代わりにarrayデータを返します。 これらの array データは Liquid Loop を使うことにより中のデータをリストとして出力することができます。

Liquid collection の中にはさらにプロパティがあるものがあります。

例えばproduct.imagesです。 このプロパティの中には、商品登録画面で登録した画像がすべてが含まれています。 さらにその一つ一つの画像にも下記のようなプロパティがありアクセスできます。

image.alt
image.attached_to_variant?
image.product_id
image.position
image.src
image.variants
image.height
image.width
image.aspect_ratio

ただし、product.imagesは複数データがはいった Array なので、そのまま個別にアクセスすることはできません。アクセスするためには Liquid Loop(後述)を使う必要があります。

Liquid loops

他のプログラミング言語と同じように Liquid でもループ文を使うことができます。

for ループを使うと同じコードを複数回ループさせて出力することができます。 liquid collection で紹介されたproduct.imagesでみてみます。

下記は product.images の中にある複数の画像データ配列を出力する例です。

{% for image in product.images %}
<img src="{{ image | img_url: 'medium' }}">
{% endfor %}

STEP1

まず最初に {% %}の括弧を使い liquid の構文がはじまることを記します。forを使うことにより同じものを複数回ループさせ出力します。例えば、商品登録画面で画像を 6 つ登録したとします。product.imagesの中には 6 つの画像データが入っています。そして for loop 文を使うことにより、6 つの画像を出力します。

テーマをデザインする側(liqudi テンプレートを作っている時)には、その商品に画像がいくつ登録されているかわかりません、またその後追加されることがあるかもしれませんが、for loop であれば、そこに登録されている数と同じだけループされることになります。

それぞれのアイテムのプロパティにアクセスするためには、どのオブジェクトをループさせるか指定しなければいけません。上記の例はimageで何をループさせるか明白でした。しかし、たとえばimageの代わりに{% for alltheimagesintheworld in product.images %}と記述することもできますが、これは馬鹿げた例です。imageとするほうがわかりやすく、liquid collection product.imagesとの関係性は明白なのでimageだけで十分でしょう。

STEP2

二行目のライン<img src="{{ imge | img_url: "100x100" }}" />は HTML と Liquid コードで構成されています。srcの中に liquid コードのアウトプットが埋め込まれています。

またこの例にはフィルターの使い方も含まれています。 フィルターは| (pipe)の文字で記述されます。 フィルターについては後述で詳しく解説しますが、この記述例ではimageから 100×100 のサイズの画像の URL を抜き出すための記述です。 *100X100 というサイズは商品管理画面で追加された画像に対して Shopify のシステムが生成したものです。

STEP3

最後の liquid タグ{% endfor %}は for loop の終了を意味します。

この例ではもしproduct.imagesオブジェクトの中に 3 つ画像があった場合、下記のような HTML が生成されることになります。

<img
src=“//cdn.shopify.com/s/files/1/2509/4288/products/13038FAW_PRO_EarringsD_352_100x100.jpg?v=1509545613”>
<img
src=“//cdn.shopify.com/s/files/1/2509/4288/products/13039FAW_PRO_SQ_Jewellery4F_022_100x100.jpg?v=1509545613”>
<img
src=“//cdn.shopify.com/s/files/1/2509/4288/products/13039FAW_PRO_SQ_Jewellery4S_023_100x100.jpg?v=1509545613”>

Shopify では一つの商品に対して複数の画像を登録することができるので、この商品の画像をループさせ表示させるというのは最もループがつかわれる例の一つです。

Liquid filters フィルター

Liquid のもう一つの便利な機能はアウトプットフィルターです。フィルターは主に 3 つの機能を果たします。

  • アウトプットデータになんらかの操作(変化)を施す。
  • Shopiy のテーマとデータを分けて作ることができるようにする。
  • デザイナー・プログラマーにとって記述するコードを減らす。

フィルターは必ず Liquid のアウトプットと共に使用されます。ここでいくつかのフィルターを見てみましょう。まずは日付に関するフィルターです。

ブログの記事をアウトプットさせるときに、いつ公開されたのか日付をつけることは一般的です。 下記はブログ記事の日付をアウトプットするコード例です。

<p class=”date-time”>{{ article.published_at | date: ‘%d %B %Y’ }}</p>

いろいろな情報の中でも特に日付の記載方法は様々です。同じ日でも、『2021-1-20』と記載することもあれば、『Jan 20, 2021』と記載する方法もあります。国よって違うこともあります。

published_atの日付データは同じ内容をLiquidのフィルターを使うことによって、好きな日付の記載方法でアウトプットすることができます。

上記の例では| date:のフィルターを使い ‘%d %B %Y’(日 月 年)の順番でアウトプットされるように記述しています。 このフォーマット指定では『20 January 2021』という具合でアウトプットされることになります。日付フォーマットについて他のバリエーションは こちら

北米では 日 月 年 の順番で記載されることが多いですが。日本だと 年 月 日 の順番が一般的なので '%Y-%m-%d'のフォーマットにする方がわかりやすいかもしれません。この場合『2021-01-21』という感じで出力されます。'%Y 年 %-m 月 %-d 日であれば『2021 年 1 月 21 日』となります。

スタイルシートの追加

フィルター機能によって css ファイルを Liquid コードに読み込ませることができます。 下記はファイル名 『style.css』を読み込ませる Liquid コードの例です。 *『style.css』はassetsのフォルダ内に収納されている前提です。

{{ 'style.css' | asset_url | stylesheet_tag }}

まず最初に CSS ファイルのファイル名をシングルクォーテーションで囲みます。その後 フィルター使用を示す| pipe を記述し、asset_urlのフィルターを使います。このフィルターはとても便利多く使うことになります。

こういった Liquid コードはどのマーチャントのストアの登録データによらず使用することができますが、assets フォルダに 必要なファイルが収納されていない場合はエラーを引き起こすため注意が必要です。この場合 assets フォルダ内に『style.css』という名前のファイルが存在しないといけません。

asset_urlのフィルターのおかげで、cssファイルを読み込み、Liquidコードファイル内に埋め込むことができます。しかしながらフィルター機能が、そのファイルが本当に存在しているかどうかをチェックするわけではありません。 なので、『style.css』のファイルがassets フォルダ内にあることを確かにしておいてください。

このフィルターによって下記のようなものが出力されることになります。

//cdn.shopify.com/s/files/1/0087/0462/t/394/assets/ shop.css?28178

そして、さらにstylesheet_tagというフィルターにより、asset_urlで出力された URL は、html で css を埋め込むのに必要なタグで囲まれ下記のように出力されます。

<link href=“//cdn.shopify.com/s/files/1/0087/0462/t/394/ assets/shop.css?28178”
rel=“stylesheet” type=“text/css” media=“all”>

フィルター機能は、最終的な HTML に適する形になるように調整し出力するためのものです。

他にもたくさんの便利なフィルター機能はありますが下記のようなものが良くつかわれます。

asset_url
stylesheet_tag
script_tag
date
pluralize
replace
handle
money
money_with_currency
image_url
link_to

フィルター機能についてはこちら

Liquid logic

Liquid では if 文が使え、条件によって出力する内容を変更することが可能です。 Liquid コードの if 文は下記のように記述します。

{% if product.available %}
<h2>価格: ¥1,980</h2>
{% else %}
<h2 class=“sold-out”>売り切れ</h2>
{% endif %}

上記の例では、もしproduct.availabletrueであれば 『価格: ¥1,980』と表示させ、falseの場合 『売り切れ』と表示させる条件分岐です。 (商品が購入可能であれば値段、購入不可の場合、売り切れ を表示)

こういった条件分岐文・論理式で、テンプレート上で、どのようにデータを表示させるか、または表示させないかを決めることができます。 こういった if 文は直接なにかをアウトプット(レンダリング)させるものではありませんが、どのようにアウトプットするかをコントロールすることができます。 もう一つの例を紹介しておくと、、

 {% if cart.item_count > 0 %}
<p>カートの中に {{ cart.item_count }} 個のアイテムがあります。 </p>
{% else %}
<p>カートの中になにも入っていません。
<a href= “/products”>こちら</a>で商品を選んでください。</p>
{% endif %}

このようにカートに入っている商品の個数を表示させたり、空であった場合別の文を表示させるといったことが可能です。

オペレーター

先程の例では>を使ってカート内の商品が 0 個より多い場合と比べています。 こういった記号はプログラミングではオペレーターと呼び、頻繁に使われます。 数学で使う記号と似ていますが、プログラミング言語により記述方法が変わることもあります。 下記は Liquid で使えるオペレーターとその機能です。

オペレーター機能(意味)
==イコール
!=イコールではない
<〜より多い
>〜より少ない
>=〜以上
<=〜以下
orAもしくはB
andAかつB
contains String上でsbustringを含む、もしくはArrayの中にあるか

Whitespace コントロール 余白コントロール

デフォルトではなにもアウトプットしない Liquid コードでも空のラインを HTML で出力します。

liquid 上での記述 とそのアウトプット(html)

{% assign my_variable = "coffee" %}
{{ my_variable }}

//output
(空白ライン)
coffee

ハイフォンを使って空白ラインが生成されないようにできます。

liquid 上での記述と そのアウトプット(html)

{%- assign my_variable = "coffee" -%}
{{ my_variable }}

//output
coffee

Liquid Cheat Sheet Liquid チートシート

このように便利なフィルターはたくさんありますが、すべて覚えるのは大変です。 Shopify では Liquid のチートシート(コード一覧)を用意してくれています。

Liquid Cheat Sheet

Sass and Shopify

Shopify は Sass へ対応し、自動的にコンパイルしてくれていましたが、OS2.0 の現行バージョン(2021 年現在)から非対応になりました。 なので Sass で記述する場合は、ローカル環境で一旦 CSS へコンパイルしてから CSS ファイルとしてアップロードする必要がでてきました。 Sass のローカル環境でのコンパイルの記事は製作中。。。(2021-12)

Summary まとめ

  • Liquid はテンプレートファイル上にデータを表示するためのテンプレート言語
  • Liquid にはアウトプット・論理条件・ループなどの機能がある。
  • Liquid ファイルは HTML と Liquid コードがあわさったもので.liquidの拡張子がつく。
  • Shopify テーマの Liquid ファイルはストアに登録された情報にかかわらず構成するのことができる。
  • Liquid では二つのタイプのタグを使って囲む。
  • データアウトプットは{{ }}を使う。
  • フィルターは|pipe を使う。
  • 論理式やループには{% %}を使う。
  • 他のプログラミング言語同様、さまざまなオペレーター論理記号がある。

Chapter 2 どのようにローカル環境で Shopify テーマを開発するか

Shopify では管理画面からテーマのカスタムや Liquid コードを直接編集することができます。 ただより複雑なカスタマイズを行ったりするにはローカル環境で高機能なテキストエディタや IDE を使用したほうが便利な場合があります。

Shopify ではローカル環境で Shopify テーマの開発や Liquid コードのカスタマイズを行いやすいように二つのツールを用意しています。

Theme kit

Theme kit は Shopify のテーマ用のコマンドラインツールです。ローカル環境と Shopify ストアにあるテーマファイルの橋渡しをしてくれます。Shopify ストアからテーマをローカル環境へダウンロードしたり、ローカル環境で編集した Liquid ファイルをアップロードしたりを行えます。

Shopify CLI

Shopify CLI は 2021 年の Shopify Unite で発表された新しいコマンドラインツールです。 テーマの開発だけでなく、Shopify アプリの構築などにも使えるツールです。 Shopify CLI については後述予定。

Theme kit のインストール

Theme kit は下記の機能が備わっています。

  • 複数環境へのテーマのアップロード
  • 速いアップロードとダウンロードの機能
  • ローカル環境での変更を即座に Shopify ストアへアップロードする Watch 機能
  • Windows, macOS, Linax で動く cross-platform ツール

Mac でのインストール

ターミナルで

curl -s https://raw.githubusercontent.com/Shopify/ themekit/master/scripts/install | sudo python

詳しい Theme kit のインストール方法はこちら

Startingu up API credential ローカル環境と Shopify ストアへの接続 API

Shopify ストアと Themekit を使ったローカル環境との接続には下記のものが必要です。

  • API key
  • password
  • theme ID

API key とパスワード

Shopify のストア上でアプリを管理の中からローカルアプリを使い、Themekit が Shopify ストアにアクセスするための API key を発行します。 Themekit アクセスのためのアプリが Shopify により用意されているので、それを使い APIKey を発行します。

Theme ID

Shopify ストアには複数のテーマを保管しておけるので、どのテーマと接続するかを指定する必要があります。(公開中のテーマだけでなく、テスト用や今後使用する用など他のテーマも保管しておけます。簡単に複製しておけるので、編集する前に予め複製しておくなどバックアップをとっておくと安心です。) テーマにはそれぞれ ID が割り振られていて、どのテーマにアクセスするかは ID を使います。

テーマの ID 番号をチェックするには、対象のテーマのアクション>コードを編集 をクリックすると URL の末尾がそのテーマの ID に変わります。

https://store-name.myshopify.com/admin/themes/124895658133

この例の場合 ID は124895658133です。

テーマダウンロード

ストア URL・ThemeID・APIKey がわかればローカル環境から Shopify ストア上にアクセスでき、ダウンロードやアップロードができるようになります。 カスタマイズしたいテーマをダウンロードするには Themekit のコマンド theme getを使います。 下記の例はそのコマンドです。

theme get --password=[your-theme-kit-password] --store="[your-store.myshopify.com]" --themeid=[your-theme-id]

config.yml ファイル

Themekit のコマンド を使ってダウンロードすると自動的にconfig.ymlというファイルが作られます。 そこに Shopify ストアの URL・APIKey・themeID が保管され、以降は毎回 長いパスワードや ID を入力することなく、ストアのテーマにアクセスできるようになります。

他にもignore_filesというコードymlファイルに記述しておくことにより、アップロードしないファイルを指定することもできます。 下記はymlファイルの中身の例です。

development:
  password: shptka_16465886faaa20760480d5504480add7
  theme_id: "124610805933"
  store: store-name.myshopify.com
  ignore_files:
    - config/setting_data.json
    - node_modules/

上記のファイルによりstore-name.myshopify.comという URL のストアのテーマ ID が124610805933のテーマにアクセスすることができます。 また、config/setting_data.json のファイルはアップロードされません。同じようにnode_modules/のフォルダの中にあるものはアップロードされません。

Push updates テーマの更新

ローカル環境で構築・またはカスタマイズしたテーマは theme watchのコマンドで保存するたびに自動的にアップロードし更新されるようになります。 終了するには、ターミナル上で ctrl + cと入力します。

*Shopify ストアで現在使用しているテーマ(公開中のテーマ)は、予期せぬトラブルを防ぐためにも更新できないようになっています。カスタマイズは非公開中のテーマを使って行うのが好ましいですが、公開中のテーマを直接カスタマイズしたい場合、下記のようにフラッグを追加します。

theme watch --allow-live

Themekit の他の便利なコマンドはこちら

またtheme helpでも terminal 上で簡単なヘルプを見ることができます。

特定のコマンドのヘルプを見たい場合はtheme [コマンド名] --helpでも見ることができます。

Chapter2 のまとめ

チャプター 2 では Themekit について解説しました。

  • Theme kit を使うことによりローカル環境と Shopify 上のテーマを同期することができる。
  • Theme kit は windows, macOS, Linux で使うことができる。
  • API key を使って Shopify ストア上にあるテーマにアクセスする。
  • config.ymlファイルにAPI key・URL・themeIDを保持できる。

Chapter 3 How URLs Map to Shopify Templates どのように Liquid ファイルと URL が連携しているか

Shopify 上で、Liquid コードはそのフォルダ構成やファイル名によって、Shopify ストアフロント上でどのファイルがどのページでレンダリングされるなどがあらかじめきめられています。

まず、どのフォルダがどういった場合に使われるか、またそのファイル名がどのページでレンダリングされるのかを知る必要があります。

URL テンプレート マッピング

Shopify は独自のルーティング(URL との紐付け)構造をもっていって、ユーザーがリクエストする URL によってどの Liquid ファイルがレンダリングされるかが決定されます。 たとえば、商品のページは🗂layoutのフォルダのproduct.liquidのファイルによってレンダリングされます。 *OS2.0 の仕様ではproduct.jsonを元にレンダリングされます。

URLレンダリングされるliquidファイルレンダリングされるjsonファイル(OS2.0)
/index.liquidindex.json
/該当しないURL404.liquid404.json
/blog/{blog-name}/{article-id-handle}article.liquidarticle.json
/blogs/{blog-name}blog.liquidblog.json
/cartcart.liquidcart.json
/collectionslist-collections.liquidlist-collections.json
/collections/{collection-handle}collection.liquidcollection.json
/collections/{collection-handle}/{tag}collection.liquidcollection.json
/pages/{page-handle}page.liquidpage.json
/productslist-collections.liquidlist-collections.json
/products/{product-handle}product.liquidproduct.json
/search?q={検索ワード}search.liquidserach.json

Poswred protected ページ

template フォルダの中にpossword.liquidが含まれていません。これはストアフロントにパスワードを設置したときに表示されるページ用の Liquid ファイルで、パスワードが設定されている場合他のすべての URL を上書きする形になります。

このpossword.liquidは必須ファイルでなく、もしテーマファイルに含まれていない場合、Shopify のデフォルトのログインページが表示されます。

Alternamte Templates

上記の表のファイル以外にも、代わりとなる Liquid ファイルを設定することができます。(後述)

URL パラメーター

上記の表をみると URL が{ }で囲まれているものがあるのがわかります。 これは読み込むデータによって変わる変数のような値がはいります。

例えば、名前が「shirts」というコレクションにアクセスしたときには、そのコレクション名に応じて URL が/collections/shirts/と自動的に変わります。 名前が「cars」というコレクションであれば/collections/cars/という感じです。

また、/products/collectionsのように同じ Liquid ファイルをシェアしている場合もあります。

最後に

もし、どの Liquid ファイルがレンダリングされているかわからない場合、簡単にチェックするほうほうがあります。 それは、theme.liquidのファイルに、{{template}}と加えると、そうするといま現在レンダリングされているページが.liquidの拡張子とともに表示されます。 これは設置したテンプレートファイルがうまく動いてるかの確認にも役に立ちます。

<p style=“background: #f1c40f; padding: 1em; font-weight: bold;”>Current template: {{ template }}.liquid</p>

template

Chapter 4 product.liquid template

これまでのチャプターでは Shopify のテンプレートがどのような URL でレンダリングされるかみてきました。このチャプターではproduct.liquidファイルについてみていきます。

カスタマーが製品のページをみたときにはproduct.liquidの liquid コードファイルがデフォルトでレンダリングされます。 また、別のバージョンのプロダクト用のファイル作って、それをレンダリングさせることも可能です。

下記はproduct.liquidテンプレートファイルの中身の例です。


<h2>{{ product.title }}</h2>
{{ product.description }}
<form action=“/cart/add” method=“post” enctype= “multipart/form-data”>
<select name=“id”>
{% for variant in product.variants %}
{% if variant.available == true %}
<option value=“{{variant.id}}”> {{ variant.title }} for {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled=“disabled”> {{ variant.title }} -
sold out!</option>
{% endif %}
{% endfor %}
</select>
<input type=“submit” name=“add” id=“add” value=
“Add to Cart” class=“button”>
</form>

先のチャプターで紹介したように、Liquid ファイルは HTML と Liquid コードで構成されています。

最初の一行目<h2>{{ product.title }}</h2>を見てください。見出し 2 の h2 の html タグでproduct.titleが囲まれていることがわかります。 このproduct.titleには Shopify ストアの管理画面で、商品のタイトルとして登録されたデータが出力されます。そして最終的には h2 の html タグによって「見出し 2」の装飾がされてブラウザ上に表示されることになります。
その後の{{ product.description }}には管理画面で商品の説明として登録されたデータが出力されます。
もちろん、この{{ product.description }}<p> </p>などで囲ってパラグラフとして表示させることも可能です。

次に< form >のタグを見てみます。

<form action=“/cart/add” method=“post” enctype= “multipart/form-data”>
<select name=“id”>

このactionのアトリビュートは重要です。 この例では/cart/addが指定されておりこの form の action が実行されることにより商品アイテムがカートに送られることを意味しています。

次の Liquid コードの例をみてみます。

{% for variant in product.variants %}
{% if variant.available == true %}
<option value=“{{variant.id}}”> {{ variant.title }} for {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled=“disabled”> {{ variant.title }} -
売り切れ!</option>
{% endif %}
{% endfor %}
  • {% for %} ループが商品のバリエーションをループされています。
  • {% if %}により商品バリエーションが購入可能状態かどうかの条件文になっています。
  • もし商品のバリエーションが購入可能状態であればoptionのエレメントにその商品バリエーションの ID を value として設定し、金額が表示されるようになっています。
  • 金額は liquid フィルターを使い通貨単位とともに表示されるようにしてあります。
  • そうでない場合は{% else %} のタグにより「売り切れ!」と表示されるようになっています。
  • {% endif %}で条件文を終了させ
  • 最後に{% endfor %}によりループを終了させています。

最後の< input type="submit" >は選択された<select >ないの<option >がこの<form >のタグの action を実行するようにしてあります。(/cart/add)によりショッピングカートに送られる。

このテンプレートでは商品とそのバリエーションのオブジェクトをつかっています。productには他にもたくさんのプロパティがあります。他のプロパティについてはこちらが参考になります。

Extending the template テンプレートの拡張

上記の例はシンプルなものですが、もっと他にもコードを付け加えることももちろん可能です。

  • 商品とそのバリエーションの写真variant imagesを加えることもできます。詳しくはこちら

  • shopify JavaScript のスニペットを使いより良く商品のバリエーションを表示させることもできます。詳しくはこちら

  • | tフィルターとlocal fileを使いテーマを多言語対応させることもできます。詳しくはこちら
  • 他のファイルからsectionを表示させることもできます。

Chapter 5 オルタネイトテンプレートの使い方

Shopify テーマのファイル構成を見た時、最初は collection や product ページはそれぞれ一つだけのファイルに対応させているように見えるからもしれませんが、Shopify では、複数のバリエーションファイル(オルタネイトテンプレート)を作り、別のファイル指定してレンダリングさせることが可能です。

例えば T シャツの商品群には A の liquid ファイルを、ズボンの商品群には別のレイアウトの B の liquid ファイルを、、という具合に。

このチャプターではより細かくテーマをカスタマイズができるように、オルタネイトテンプレートの作り方を見ていきます。

オルタネイトテンプレートの作り方

オルタネイトテンプレートを作るのは簡単です。それぞれのページに対応するデフォルトの名前の後に.(ドット)をつけて liquid の拡張子をつけるだけです。

default_template_name.*.liquid *にすきな名前をつけれます。

たとえば、靴の商品に対応するproduct.liquidのオルタネイトテンプレートを作るには下記のような名前をつけます。。

product.shoes.liquid

OS2.0 では

product.shoes.jsonというファイル名をつけます。 JSONファイルを使いテンプレートの名前・どのsectionsを加えるか、そしてどの順序(order)でセクションを追加するかを指定します。

下記の例では、テンプレートの名前は product。main-product.liquidという名前の section ファイルをmainという名前にしています。そのファイルをorderで指定します。

さらにそれだけでなく、OS2.0 では、shopify 管理画面上で自由に他のセクションファイルを加えることができます。

ただし、加えたいセクション内の{% schema %}内の JSON に、あらかじめ preset の項目を追加しておく必要があります。{% schema %}については後述。

また同じタイプのテンプレートを.liquidJSONのファイルを同時に作ることはできません。例えば商品をレンダリングするためのproduct.liquidproduct.jsonを同時にテンプレートディレクトリに入れておくことはできません。

{
  "name": "product",
  "sections": {
    "main": {
      "type": "main-product"
    }
  },
  "order": ["main"]
}

Shopify ストアの管理画面で上でもオルタネイトテンプレートを作ることが可能です。

  1. Shopify の管理画面にログインする。
  2. テーマのアクションからコード編集を選択
  3. テンプレートフォルダにて新しいテンプレートを作成
  4. 新しいテンプレートに名前をつけ編集と保存を行えばオルタネイトテンプレートが生成できます。

また OS2.0 からはテーマのプレビュー画面からも json ファイルを作成できるようになりました。くわしくはこちら

オルタネイトテンプレートの選択

オルタネイトテンプレートを使ってページをレンダリングするには Shopify ストアの管理画面上でオルタネイトテンプレートを選択します。
オルタネイトテンプレートが存在している場合、各対応するページで選択できるようになります。

例えば、特定の商品に対してオルタネイトテンプレートを使用したい場合、その商品の登録画面の右下部分にあるテーマのテンプレート選択で、使用したいテンプレートを選択できます。何も選択しない場合はデフォルトのproductテンプレートとなっています。

alternate-template

URL によるテンプレートのスイッチ

テンプレートを選択する方法は他にも URL のパラメーター view=を使って選択する方法があります。 例えばhttp://store.myshopify.com/products/blue-t-shirt?view=specialの URL では、product.special.liquidのオルタネイトテンプレートがレンダリングされます。

この方法は他のページでも使えます。例えばhttp://store.myshopify.com/collections/ computers?view=listのコレクションへの URL ではcollection.list.liquiのオルタネイトテンプレートが表示されます。

もしリクエストされたオルタネイトテンプレートが存在シていない場合、Shopify はデフォルトのテンプレートもしくは、管理画面で選択されているテンプレートを使ってレンダリングを行います。

この URL をつかったテンプレートの選択は商品コレクションをグリッドで表示したりリストで表示したりなど切り替える場合によくつかわれます。

オルタネイトテンプレートの使用

このオルタネイトテンプレートが使えるのは Shopify のテーマを使うメリットの一つです。 商品によって違うレイアウトを使用したり、同じ商品でも URL 操作を使い、別のテンプレートを使用し、別のレイアウトを見せることができるからです。 この見せ方の多彩さを利用し、より良いショッピング体験を顧客に提供できます。

Chapter 6 オルタネイトレイアウトファイル

先のチャプターではオルタネイトテンプレートの使い方をみました。このチャプターでは Liquid レイアウトファイルをみていきます。

Shopify のテーマのでデフォルトのレイアウトファイルはtheme.liquidというファイルでlayoutsフォルダーの中に入っています。

このtheme.liquidレイアウトファイルは Shopify テーマのいわば「マスター」テンプレートのようなものです。 このtheme.liquidファイルが他のすべてのテンプレートファイルをまとめる役割を果たします。

一般的なウェブサイトでは、ヘッダー・ナビゲーションバー・フッターといったコンポーネントはどのページを表示しても常にレイアウトされています。Shopify では、こういった常に表示されるコンポーネントをこのtheme.liquidのファイル内に設置しレンダリングを行えます。

どのくらいのコンポーネントを設置するかはテーマのデザインによりますが、常に表示させ再利用するような要素はこのtheme.liquidに配置できます。

そして、特別に指定をしない限り Shopify テーマはこのファイル名theme.liquidをデフォルトとしてレンダリングを行います。

layout ファイルの利点

このレイアウトファイルを利用する利点はプログラミングにおける DRY (Don't Repeat Yourself) 同じコードを繰り返さないの原則に沿うことができることです。

たとえばフッターに一つ変更を加えたい場合、theme.liquid 上でレンダリングされていれば、他のすべてのフッターに変更を加えなくてもグローバルに変更されるため、簡単にグローバルな変更を加えることができます。

またもう一つの利点としてはproduct.liquidcollection.liquidといったファイルが各所に散在することを防ぐことができます。

layout ファイルの作り方

どれほどの HTML ファイルをレイアウトファイルに加えようと、二つ重要な点があります。

{{ content_for_header }}

html の<head>のタグないに必ず{{ content_for_header }}の Liquid タグを埋め込む必要があります。これは、Google Analytics,Shopify Analytics,ShopifyApp などを使うために必ず必要です。

{{ content_for_layout }}

html の<body>のタグ内に{{ content_for_layout }}の Liquid タグを埋め込む必要があります。これはindex.liquidproduct.liquidといったテンプレートファイルを動的にレンダリングするために必ず必要です。

この二つプレースホルダータグがtheme.liquid内の正しい位置に設置されている必要があります。

オルタネイトレイアウト

一つのレイアウトデザインだけでなく、別のレイアウトが必要なとき、CSS を使ってエレメントを隠したり、表示したりと切り替えることは可能ですが、より良い方法はオルタネイトレイアウトを作ることです。 オルタネイトレイアウトを作ることによって同じストアでも、まったく違う HTML で表示することが可能です。

例えば、特定の商品に特価したランディングページデザインを作るなどが良い例です。

オルタネイトレイアウトを作るのは簡単です。まず最初に、好きな適する名前をつけて、その後に.liquidの拡張子をつけます。 そしてそれをlayoutsのフォルダーに入れます。

そして、theme.liquidと同じように、必要な HTML や CSS、JavaScript へのリンクと一緒に、上記で説明した Liquid のプレースホルダータグ{{ content_for_header }}{{ content_for_layout }}を適切な場所に設置します。

デフォルトのtheme.liquidを上書きして、この新しいレイアウトファイルを上書きしてレンダリングさせるには、index.liquidproduct.liquidなどの liquid ファイルの 1 行目に次の Liquid タグを挿入します。

{% layout ‘alternative’ %}

これによりデフォルトのtheme.liquidは適用されなくなり、代わりに作ったレイアウトファイルが適用されます。例:alternative.liquid

下記のように Liquid タグを設置し、レイアウトファイルを適用させないようにすることも可能です。

{% layout none %}

これらのタグは対象のテンプレートファイルの最初の 1 行目に挿入する必要があります。JSONファイルのシンタックスなどからレンダリングさせるときに使えます。

セクションのオルタネイトレイアウト

どんなタイプのテーマやテンプレートを作るかによりますが、新しいテンプレートが、独自に作ったセクションを取り入れたい場合は、セクションを作る必要があります。

例えば、商品ページのオルタネイトテンプレートをつくる場合、新しいセクションを作る必要がでてくるでしょう。なぜなら、商品ページに必須になってくる情報はテンプレートファイル自身からよりも、そこに挿入されたセクションファイルがレンダリングすることになっているからです。

商品のテンプレートファイルをみてみると、おそらくほとんどなにも HTML や Liquid コードが書かれているのでなく、代わりに下記のように Liquid タグが書かれていることに気づくでしょう。

{% section 'product-template' %}

このproduct-templateという名前のセクションを新たに作ったセクションファイルの名前にに置き換えると、新しいセクションがレンダリングされます。

{% scetion 'product-alternative' %}

OS2.0 でのテンプレートファイル

OS2.0 ではテンプレートファイルは.liquidの拡張子ファイルではなくJSONファイルが割当られています。 これにより好きなセクションコンポーネントをindex.liquidだけでなく、他の page テンプレートや product テンプレートを Shopify ストアの管理画面でカスタマイズとして挿入することができるようになりました。 このsection everywhereを適用したい場合、テンプレートファイルはJSON形式のファイルで構成する必要があります。

Snippets の使い方

Snippets を使って同じコンポーネントを別のレイアウトやセクションファイルで再利用することができます。これにより、各所の配置する同じコンポーネントを一元管理することができます。 またレイアウトやセクションファイルをよりシンプルにすることができます。

Snippets は snippets のフォルダに格納されて .liquidの拡張子がつきます。

下記は一般的に作られる snippets の一覧です。

snnipets/html-header.liquidbodyタグの上に配置するすべての要素を含むsnippets
/snnipets/html-footer.liquidbodyタグを閉じる場所には配置するスクリプトファイルなどを含むsnnipets
snnipets/header.liquidサイト全般を通して表示するメインヘッダーのsnippets
snnipets/footer.liquidサイト全般を通して表示するメインフッターのsnnipets

これらの snippets を配置しレンダリングするいは下記のように Liquid タグを使います。

{% render  'html-header' %}
{% render 'header' %}
{% render 'html-footer' %}
{% render 'footer' %}

*2020 年以前は、snippets を使うには{% include %}タグを使っていましたが{% render %}のタグに置き換わりました。

Snippets については Chapter 8 で解説 よりくわしい Snippets 公式ドキュメントはこちら

また、これらの snippets の利点はオルタネイトテンプレートやレイアウトファイルを作るときに、再び同じヘッダーやフッターのコンポーネントを作らなくても再利用できる点です。

オルタネイトレイアウトを使うにあたって

オルタネイトレイアウトは、ある特定の商品ページだけに特化したレイアウトを構成する場合にとても便利な機能です。

Chapter 7 リンクリストの使い方

リンクリストは Shopify の特定のページにアクセスするためのリンクのリストです。リンクはページ・コレクション・プロダクトなどのページへアクセスすることができます。 リンクはネストさせることができ、Shopify の管理画面で設定することができます。

リンクリストはtheme.liquidのレイアウトで表示させるのが一般的です。

メニューの作成

Shopify の管理画面上のオンラインストアを選択すると、メニューを作成することができます。

デフォルトでは「Main Menu」と名前のつけられたリンクリストがあります。基本的にこのリストはデフォルトでヘッダーメニューの役割をしています。

自分でオリジナルのリンクリストを作ることも可能です。リンクの名前とそのリンクがどこにつながるかを設定できます。商品のページ・コレクションのページ・ブログページ・または外部のサイトの URL などを設定することができます。また、メニューをネスト(階層化)することもできます。

メニューのアウトプット

管理画面で作ったリンクリストをアウトプットさせるにはメニューの名前(handle)が必要です。 handle はそのリンクリストを特定するもので同じ名前をつけることはできません。

リンクリストは Liquid のループ機能をつかって表示させます。また一般的なウェブサイトのナビゲーションバーのように html の<ul><li>タグを使って表示させることができます。下記は「main-menu」という handle のリンクリストをループさせた例です。

<ul>
{% for link in linklists.main-menu.links %}
<li><a href= “{{ link.url }}”>{{ link.title }}</a></li> {% endfor %}
</ul>
  1. 最初に html のタグ<ul>をつかいます。
  2. そして{% for link in linklists.main-menu.links %}の Liquid コードを使いループさせます。
  3. linklistsはShopifyストア管理画面で作成したリンクリストのオブジェクトです。プロパティはhandle名を使用し(ここでは main-menu ),さらにそのプロパティのlinksをループさせています。
  4. forループでlinkをさせ、それぞれlink.urllink.titleをアウトプットさせリンクリストをhtmlタグ内に設置します。
  5. 最後に html タグ</ul >でリストを終了させます。

上記の例では Shopify のテーマにデフォルトであるmain-menuという handle 名を使っていますが、管理画面上で作ったオリジナルのリンクリストをレンダリングさせたい場合その handle 名を使います。

もしその handle 名がfooter-menuであれば {% for link in linklists.footer-menu %}というループ文になります。

ループさせる variable の link は下記のプロパティを持っています。

  • url
  • title

これらは管理画面で作成したときに各リンクにつけた名前(title)とそのリンク先の URL です。

階層化させたリンクリスト

管理画面上で階層化させたリンクリストを作成した場合、それに合う Liquid コードを使う必要があります。 階層化させたリンクリストとは、リンクが更にサブリンクを持っているものです。 例えば下記は三段階のレベルのリンクリストです。

  • home
  • about us
  • Women
    • accesorries
      • Earings
      • Scarves

この三段階のレベルのリンクリストは下記のような Liquid コードでレンダリングさせます。

<ul class=“parent”>
  {% for link in linklists.main-menu.links %}
     <li><a href=“{{ link.url }}”>{{ link.title }}</a>
      {% if link.links != blank %}
       <ul class=“child”>
        {% for child_link in link.links %}
           <li><a href= “{{ child_link.url }}”>{{ child_link. title }}</a>
            {% if child_link.links != blank %}
               <ul class=“grandchild”>
                 {% for grandchild_link in child_link.links %}
                    <li><a href= “{{ grandchild_link.url }}”>{{ grandchild_link.title }}</a></li>
                 {% endfor %}
                </ul>
            {% endif %}
           </li>
        {% endfor %}
        </ul>
      {% endif %}
    </li>
  {% endfor %}
</ul>

Liquid コードのif文が使われていることがわかります。これはもしそのレベルのリンクがサブリンクが空白でない場合、そのサブリンクを表示させるために使用しています。

この例ではわかりやすいように一つ下の階層のサブリンクはchild_linkという名前で、さらに一つ下のサブリンクはgrandchild_linkという名前を使ってループさせています。

アクティブリンクについて

リンクには便利なプロパティがあります。link.activelink.child_activeです。 これらのプロパティはbooleanプロパティでtruefalseの value をもっています。 もしこのリンク先がアクティブ状態であればtrueを返します。 これにより CSS などでアクティブ状態のリンクには別のアクティブ用のクラス名を指定することが可能です。

もしアクティブであれば CSS のactiveのクラスを付与し、もしそのリンクのサブリンクがアクティブであればchild-activeのクラスを付与する例です。 アクティブのリンクは色を変えたりアンダーバーで装飾するなどが一般的です。

{% if link.active %} class=”active

{% if link.child_ active %}child-active{% endif %}”

{% endif %}

リンクリストのループとアクティブの CSS クラスを付与している例

<ul class="parent">
    {% for link in linklists.main-menu.links %}
        <li {% if link.active %} class="active {% if link.child_active %} child-active {% endif %} " {% endif %}>
            <a href="{{ link.url }}"> {{ link.title }} </a>
            {% if link.links != blank %}
                <ul class="child">
                    {% for child_link in link.links %}
                        <li {% if child_link.active %} class="active {% if child_link.child_active %} child-active {% endif %} " {% endif %} >
                            <a href="{{ child_link.url }}"> {{ child_link.title }}</a>
                              {% if child_link.links != blank %}
                                 <ul class="grandchild">
                                    {% for grandchild_link in child_link.links %}
                                        <li {% if grandchild_link.active %} class="active {% if grandchild_link.child_active %} child-active {% endif %} " {% endif %}>
                                            <a href="{{ grandchild_link.url }}">{{ grandchild_link.title }}</a>
                                        </li>
                                    {% endfor %}
                                </ul>
                            {% endif %}
                        </li>
                    {% endfor %}
                </ul>
            {% endif %}
        </li>
    {% endfor %}
</ul>

まとめ

リンクリストは Shopify のプラットフォームでパワフルなエレメントです。管理画面上で好きなメニューを自由に作成できるのはとても便利です。 このように Liquid のループ文や if 文を使えば、あらかじめいくつの要素のあるメニューを知る必要なく、ユーザーが作った任意の数のリストをフレキシブルにレンダリングできます。

Chapter 8 Snippets の使い方

以前のチャプターでも紹介しましたが、Shopify で Snippets を使うにあたって下記のことを覚えておくとわかりやすいです。

  • Snippets は再利用するコードの塊をまとめたファイルです。
  • Snippets はsnipppetsフォルダーに収納します。
  • Snippets ファイルは.liquidの拡張子をつけます。
  • Snippets ファイルはストア全体を通して複数回つかうコードに使われます。
  • テンプレートで使用するには liquid コードタグ{% render %}を使います。
  • 使用する際に{% render 'snippets-name'%}のように.liquidの拡張子をつける必要はありません。
  • Snippets はその使用先のテンプレートの variable を引き継ぐことができます。
  • SNS リンクやパジネーションなども Snippets を使う例の一つです。

Snippets の使い方(応用)

Snippets を使えば、同じコードを何度も書く必要がなくなり、そのコードについて一元管理できるので大変便利です。 サイト全体の複数のテンプレートに何度も使われるコードを、Snippets を使っていれば、その Snippets の内容を一つ書き換えるだけで、すべてのコードをアップデートできます。

また、Snippets を使いテンプレートファイルを Snippets を使い構成しておけば、長いコードで構成されるファイルになるのを防ぐことができます。

もちろん、ファイルの構成の仕方の方針は人によって違いますが、Snippets を使うのには他の理由もあります。

条件による Snippets のローディング

Snippets 活用の一例として条件によるローディング(読み込み)があります。

例えば、coffee cupという handle 名を持つある特定の商品群を表示したいとします。

Shopify のすべてのオブジェクトにはそれぞれ、固有の handle 名があります。それは wordpress でいうような slug のようなものです。handle 名は URL で使えるような名前になっています。すべての商品は管理画面で登録したときにその商品名を参考にして自動で handle 名がつけられます。基本的には自動で行われる処理ですが、自分で好きな handle 名をつけることもできます。 この handle があることにより Shopify のテーマで商品をオブジェクトとして扱うのがとても簡単になります。Liquid の条件分岐 if 文を使うことにより、現在の handle 名をチェックし、Snippet をローディングさせるかどうかを決めることができます。

{% if product.handle contains 'coffee-cup' %}
  {% render 'special-offer' %}
{% endif %}

上記例ではまず if 文によりproduct.handlecoffee-cupの値を持つかどうかを判断し、もしそうであればspecial-offerの snippets を読み込ませています。

これはもっともシンプルな例ですが、このような方法を用いれば、商品によってページの内容を変化させることが可能になりオンラインストアの魅せ方・表現の幅が広がります。このシンプルな方法だけでも Shopify のテーマをとてもフレキシブルに構成することができます。

Snippets の名前付けの通例

先にも紹介したように snippets フォルダーは、すべての snippets が入った大きな『カゴ』のようなものです。 大きなカゴの中のたくさんのファイルを上手に整理しておくためにも名前の付け方は大変重要です。できる限り明確にわかりやすい名前をつけるようにしておきましょう。例えば下記のように。

  • product-limited-edition-coffee-cup.liquid
  • product-showcase.liquid
  • collections-coffee-cups.liquid

またこの例ではテンプレートの名前に付随して名前をつけてあることによって、テンプレートと共に使うワークフローがわかりやすくなるようにしています。

Variable scope

Spnippets がテンプレートファイル内で使われたとき、Snippet はそのテンプレートの variable にアクセスすることができます。 ただしそのテンプレートが持つ variable に限り、その variable に対応する形でしかアクセスできません。

では、グローバルやテンプレートのもつ variable の形式以外のものにアクセスしたい場合はどうするか?その場合は{% assign %}の Liquid コードタグを使います。

下記はこの{% assign %}を使う例です。

{% assign my_variable = ‘apples’ %}
{% render ‘name’, my_variable: my_variable, my_other_variable: ‘oranges’ %}

これでこの snippet はapplesorangesといういう variable にアクセスするようになります。

また下記のようなフォーマットでコレクションにもアクセスできます。

{% assign all_products = collections.all.products %}
{% render ‘snippet’, products: all_products %}

また snippet 内で新しい variable にアサインをしても、その親テンプレートの variable が上書きされるわけではない点も注意。

with の使い方

次はrenderタグ内のパラメーターwithについて見ていきます。このアプローチはさまざまなアプリケーションに使える再利用可能なスニペットを作る上で非常に有用なものとなります。

下記は、テンプレート内に商品コレクションをアウトプットさせるためのスニペットの例です。

<ul>
{% for product in collections.all.products %}
<li><a href="{{ product.url}}">{{ product.title}}</a>
{% endfor %}
<ul>

このcollectionsはグローバルな variable であるため、どのテンプレート上でも使えます。そのため、この snippet はシンプルに Shopify ストアのすべての商品をアウトプットすることになります。

もしある特定の商品コレクションだけを表示させたい場合は、下記のように snippet を書く必要があります。

<ul>
{% for product in collection-product-list %}
<li><a href="{{ product.url}}">{{ product.title}}</a>
{% endfor %}
<ul>

見てわかるようにcollections.all.productsという Liquid コレクションのすべての商品をループさせるのでなく、代わりにcollection-product-listをループさせていることがわかります。

では、この snippet をすべての商品だけでなくもっと汎用性をもたせて使用する方法をみていきます。

{% assign c = collections.all.products %}
{% render ‘collection-product-list’ with c %}

最初にcollections.all.productscにアサインさせていることがわかります。(この名前は c でなく好きなものをつけることができます)

そしてrenderのタグをみるとcollection-product-listに続きwith cと付け加えられていることがわかります。

このwithのパラメーターは、スニペットとして同じ名前共有し、Snippets の中の variable に value をアサインさせます。

この説明だけではすこしわかりにくいので、例を使って説明していきます。

{% for product in collection-product-list %}

ここでcの variable は snippet 内でcollection-product-listによって参照されることになります。 この時点で snippet はwithのパラメーターによって渡されたどのコレクションでも機能するようになります。

generic snippet の拡張

snippet には一つ以上の variable を渡すことも可能です。例えば、表示する商品数を制限することなどに使われます。liquid の for ループでは下記の例のようにループする回数を制限します。

<ul>
{% for product in collection-product-list limit: limit_count %}
<li><a href="{{ product.url }}">{{ product.title }}</a>
{% endfor %}
</ul>

そして下記のように snippet にアサインした value を渡すことができます。

{% assign c = collections.all.products %}
{% render ‘collection-product-list’ with c, limit_count: 2 %}

この snippet がレンダリングされたとき、二回目のループされたらそこでループするのは終わりになります。 回数を指定しなければ liquid コレクションはすべて繰り返します。また liquid コレクションに含まれる商品数より、limit_countの方が多い場合は、最後の商品でforループは終わります。

また variable はコンマで区切ることでさらに追加できます。例えば以下のような例です。

{% render 'collection-product-list' with c, limit_count:2, heading_text: "All Products" %}

これで snippet 内に{{ heading_text }} というアウトプットタグがあれば render の variable で指定した値をアウトプットできるようになります。

Snippets を使ってみよう。

snippets は単純なツールのように見えるかもしれませんが、テーマを様々な要素を盛り込めるパワフルなものにしてくれます。

Chapter 9 セクションとブロックの使い方

Section はページを構成させるカスタマイズ可能な要素です。Section は snippets と似ていますが、 shopify ストアのテーマエディターでカスタマイズを行うことができます。

下記は Section の特徴の概要です。

  • セクションは、テーマエディターでテンプレートに追加することができます。*
  • セクションは{% section 'section_name' %}でテンプレートファイルに静的に追加することができます。またpresetを追加しておくことで自動的にホームページ(index)に追加されます。
  • (OS2.0)ではテンプレートファイルを JSON ファイルで作ることにより、管理画面のテーマエディタでセクションをより自由に追加できるようになりました。
  • セクションでは{% schema %}{% javascript %}{% stylesheet%}のタグが使えます。
  • Liquid タグの使用によりセクションに付随した CSS を加えることができますが、デフォルトではtheme.liquidで読み込んだ CSS ファイルも読み込みます。
  • セクションは特定の input タイプを含めることができます。

Shopify テーマの静的なセクションの作り方。

新しいセクションをテーマファイルエディターで作ったときに自動的に schema・css・javascript のタグが下記の例のように挿入されます。 schema タグの中の情報によって Shopify ストア管理画面でどのようにコンテンツを読み込ませるかを設定することができます。CSS と Javascript タグはセクション固有のスタイルや機能を加えるのに使うことができます。ただし、デフォルトではセクションはテーマのメイン CSS を読み込みます。

{% schema %}
{
  "name": "Section name",
  "settings" :[]
}
{% endschema %}
{% stylesheet %}
{% endstylesheet %}
{% javascript %}
{% endjavascript %}

セクションに実際のコンテンツを加えるには HTML と Liquid タグによりを加えます。{{ section.settings.name }}のアウトプットタグにより、schema 内で指定したコンテンツがアウトプットされます。そしてそのコンテンツはテーマエディターでカスタマイズできます。

下記の例は見出し 1 とテキストボックスを加えたものです。

<div id="textsection">
  <h1>{{ section.settings.text }}</h1>
  <p>{{ section.settings.text-box }}</p>
</div>

{% schema %}
{
  "name": "Text Box",
  "settings": [
    {
      "id": "text",
      "type": "text",
      "label": "見出し1",
      "default": "Title"
    },
    {
      "id": "text",
      "type": "richtext",
      "label": "文章を追加",
      "default": "サンプル文章"
    }
  ]
}
{% endschema %}

上記の例ではシンプルなテキストを見出し 1 のタグの中とパラグラフタグの中に入れてアウトプットさせただけですが、image_pickeradiovideo_urlまたはfontなどのタイプも使いアウトプットさせることが可能です。

Schema タグの中にあるidは Liquid タグを特定するもので、typeはどのようなアウトプットのタイプなのかを指定するものです。またlabelはテーマカスタマイズ画面で表示されるラベルを示すものです。

defaultデフォルトでアサインされるプレースホルダーです。

Liquid テンプレートファイル上で特定のセクションを加えるには{% section 'name_of_section' %}のようにセクションの名前を Liquid タグを挿入します。これは snippet を加える方法に似ています。

OS2.0

OS2.0 ではテンプレートは JSON でできています。JSON 内にセクションを指定することもできますが、presets が予め設定されているセクションはストアの管理画面でも自由に追加できるようになりました。presetsが設定された動的なセクションは次で後述。

動的なセクションの作り方。

Liquid タグを使った静的セクションとちがい動的セクションは管理画面上で自由にセクションを追加し動かせることが可能です。また OS2.0 ではテンプレートファイルを JSON ファイルにすれば、ホームページ以外でも自由にセクションを追加できるようになり、より柔軟なレイアウトを作ることができるようになりました。あいうえおかきくけこさしすせそたちつてと

この動的なセクションを作るにはpresetsschemaタグの中にセットしなければなりません。presetsnamecategoryが必須です。

下記のようにSchemaタグ内に記入します。

{
  "name": "call to Action",
  "category": "CTA button"
}

このようなpresetsschemaタグ内に記入するとテーマ内で自動的に動的なセクションとして認識されるようになります。そしてindex page内で自由に追加することができます。

ストアの管理画面にてテーマのカスタマイズを行ってみてください。そしてホームページにいくと先程名前をつけたCall to Actionが追加できるようになっているのがわかります。またこのセクションは自由に順番を変えることができるはずです。

OS2.0

OS2.0 でテンプレートファイルを JSON ファイルにしておけば、ホームページ以外のページも自由にこのセクションを追加できるようになります。

セクションへのブロックの追加

セクション内におけるblocksはストアの管理画面のカスタマイズで自由に追加できるコンテンツやセッティング要素です。またblocksはセクション内で自由に動かすことができます。

この block 要素には画像・動画・カスタムテキストやその他の input 設定がつかわれます。下記はその一覧です。

valueApplication
text一行のテキスト
textarea複数行のテキスト
image_picker画像のアップロード
radioラジオボタン
checkboxチェックボックス
selectドロップダウンリスト
rangeレンジスライダー

ブロックの schema を作ったら、Liquid ループ{% for block in section.blocks %}を使ってレンダリングさせます。

この Liquid タグを使い、アウトプットには{{ block.settings.id }} を使ってレンダリングさせます。idは schema 内で設定された JSON に基づいたものです。たとえばimageという id をアウトプットさせるには{{ block.settings.image }}という具合です。

下記のようにブロック内の array には必ずnametypeを設定しなければなりません。ブロックのsettingssettings_schema.jsonと同じフォーマットを使用します。

{% schema %}
{
  "blocks": [
    {
      "type": "quote",
      "name": "Quote",
      "settings": [
        {
          "id": "content",
          "type": "text",
          "label": "引用"
        }
      ]
    }
  ]
}
{% endschema %}

また追加できる最大のブロック数を指定できたり、presets内にてセクションを追加したときにデフォルトでいくつブロックを表示させるかなどを予め設定することもかのうです。

詳しくはこちら

Case/When をつかった Block のコントロール

Liquid 内で case/when control flow tags を使うことにより、どのタイプのブロックをアウトプットさせるかを選択できるようになります。

下記の例ではニュースレターのブロックかテキストのブロックを選んで配置することができるようにしてあります。


{% for block in section.blocks %}
  {% case block.type %}
    {% when ‘text’ %}
      <div class=“grid__item”>
        <h3>{{ block.settings.title }}</h3>
        <div class="rte">{{ block.settings.richtext }}</div>
      </div>
    {% when ‘newsletter’ %}
      <div class=“grid__item”>
        <h3>{{ ‘layout.footer.newsletter_title’| t }}</h3>
        <p>{{ ‘layout.footer.newsletter_caption’ | t }}</p>
          {% render ‘newsletter-form’ %}
     </div>
    {% endcase %}
{% endfor %}

大きな力とその責任

これまでいかにテーマにセクションを加えるのが簡単か見てきました。これでクライアントのストアに無限の可能性が加わりました。

しかしながら、複数のブロック、とくに画像や動画ようなものをリピートさせることはページの動作や読み込みを遅くさせ、快適なユーザー体験を阻害する恐れがあることも念頭におかなければなりません。

もししっかりと注意を払いブロックなどの要素最適化させれば、よりよいショップ作りに役に立つのは間違いありません。

Chapter 10 どのように all_products を使うか

このチャプターではコレクションをループさせたりせず、もしく商品詳細ページ上ではなく、商品の情報に悪世するする方法を説明していきます。

商品に直にアクセスするためにはall_productsを使用します。 例えば下記のような方法です。

{{ all_products["coffee-cup"].title }}

この方法のシンタックス(記法)はとてもシンプルですall_productsに product handle を[]ないで指定するだけです。

Liquid handles

Handles とは Liquid objects にアクセスするために使われます。デフォルトではその商品・ブログ・記事などのタイトルがすべてアルファベットの小文字で自動生成されます。もしタイトルに空白が含まれている場合はすべて自動的に(-)ハイフォンに置き換えられます。

上記のサンプルでは Handle はcoffee-cupでした。そして、アウトプットさせるのは title でしたが他にも下記のように多数のプロパティにアクセスすることができます。

all_products[“coffee-cup”].available
all_products[“coffee-cup”].collections
all_products[“coffee-cup”].compare_at_price_max
all_products[“coffee-cup”].compare_at_price_min
all_products[“coffee-cup”].compare_at_price_varies
all_products[“coffee-cup”].content
all_products[“coffee-cup”].description
all_products[“coffee-cup”].featured_image
all_products[“coffee-cup”].first_available_variant
all_products[“coffee-cup”].handle
all_products[“coffee-cup”].id
all_products[“coffee-cup”].images
all_products[“coffee-cup”].image
all_products[“coffee-cup”].options
all_products[“coffee-cup”].price
all_products[“coffee-cup”].price_max
all_products[“coffee-cup”].price_min
all_products[“coffee-cup”].price_varies
all_products[“coffee-cup”].selected_variant
all_products[“coffee-cup”].selected_or_first_available_variant
all_products[“coffee-cup”].tags
all_products[“coffee-cup”].template_suffix
all_products[“coffee-cup”].title
all_products[“coffee-cup”].type
all_products[“coffee-cup”].url
all_products[“coffee-cup”].variants
all_products[“coffee-cup”].vendor

この中のいくつかのプロパティは Liquid コレクションで Loop によって出力必要があるものあります。 下記の例は coffee-cup の Handle を持つ商品の画像をアウトプットさせているものです。

{% for image in all_products["coffee-cup"].images %}
<img src="{{ image.src | img_url: 'grande' }}"
{% endfor%}

一つ以上の Handle の扱い

さらに一歩踏み込んだ方法として Liquid の Handle の Array を作り特定の商品をアウトプットさせることができます。下記はその例です。

{% assign favorites = "hand-made-coffee-tamper | edible-coffee-cup" | split: "|" %}
<ul>
{% for product in favorites %}
<li>{{ all_product[product].title }} </li>
{% endfor %}
</ul>

上記ではまず Liquid の assign のタグを使い新しい variable を設定します。そして handle はすべて|pipeline で区切られています。|はそれらを区切り Array にするための Liquid フィルターです。そしてforループにより Array をループさせて出力しています。

いつ all_products を使うか?

all_products は特定のテンプレートに数個のプロダクトだけを表示したいときに有効な方法です。 もちろんたくさんの商品をアウトプットさせるのもできますが、その場合はcollectionsを使ったほうが良いでしょう。商品の handle を手動で入力する必要がないので。
しかし、all_productsは頻繁に変更を加える必要のない少数のプロダクトを表示させるには良い方法です。

Chapter 11 img_url フィルターをつかった画像操作

このチャプターではimg_filterをつかってどのように画像を表示させるか、またどのようなパラメーターを加えることができるかを見ていきます。

ではimg_urlフィルターをみていきます。このフィルターを使うと画像の URL が返ってくることになります。ただそれにはサイズのパラメーターを指定する必要があります。またこのフィルターは下記のような画像を持つオブジェクトに対してとても有効です。

  • product
  • variant
  • line item
  • collection
  • article
  • image

下記の例をみてください。

{{ product.featured_image | img_url: '100x100' }}

この例ではimg_urlフィルターを使い100x100のサイズを指定しています。このバリューは画像をアップロードした際に Shopify によって自動的に作り出されたサイズです。

この場合、画像は 100x100 ピクセルより大きくなることはありません。
もしスクエア正方形のサイズをアップロードした場合は、理想的にサイズが変更されます。 しかし、もしオリジナルの画像が正方形でなく長方形であれば、Shopify はその形に従い長い方を 100 ピクセルとしてサイズを変更します。基本的には画像のクロップを行わない限り、もとの形に従うことになります。 下記は画像プロパティの指定の仕方です。

{" "}

{" "}

1024x1024(width and height)1024x1034
Width only100x
Height onlyx100
Largest/オリジナルの画像master

またimg_urlフィルターにさらにフィルターを重ねチェインさせることもできます。img_tagフィルターを使えば<img>の html 要素として出力することも可能です。

{{ product.featured_image | img_url: '100x100' | img_tag }}

これまでimg_urlフィルターの基本的な動作を見てきました。他にも新しいパラメーターを加えることができます。

新しいパラメーター

Size

では基本のパラメーターであるサイズから見ていきます。

{{ product.featured_image | img_url: '450x450' }}

pizza-450x450

このように幅と高さを指定してイメージのサイズをコントロールできますが、幅だけ高さだけ指定ということもできます。

幅だけを指定

{{ product.featured_image | img_url: '450x' }}

pizza-450x

高さだけを指定

{{ product.featured_image | img_url: 'x450' }}

pizza-450x

このように「1 辺」だけを指定した場合、Shopify は他の辺はオリジナルのサイズに合わせて、オリジナルのアスペクト比(縦横比)をキープしたまま画像サイズを計算します。

最初の450x450の例にもどります。この画像は指定どおり 450x450 ピクセルで出力されると思うかもしれませんが、必ずしもそうとは限りません。

この指定は元の画像が完全なスクエア、、正方形である場合のみ指定通りの 450x450 のサイズになります。しかし、もしそうでない場合、Shopify は長い方の辺を基準として元のアスペクト比をキープしたサイズで出力します。

Crop (切り抜き)

ただし便利なことに、完全な正方形のオリジナル画像をアップロードしなくても調整する方法があります。cropの下記のような新たなパラメーターを使うことによりうまく画像のサイズを調整することができます。

  • top
  • center
  • bottom
  • left
  • right

例えばこれまでの同じ画像を以下のようにクロップすることができます。

{{ product.featured_image | img_url: '450x450', crop: 'center' }}

pizza-450x450-center

Scale 大きさ

縦横サイズと同じようにピクセルの密度も指定することができます。

指定できるオプションは

  • 2
  • 3

です。

指定方法は下記のようにシンプルなものです。

{{ product.featured_image | img_url: '450x450', crop: 'center', scale: 2 }}

pizza-450x450-center-scale2

その結果イメージのサイズは900x900となります。ただこれは、オリジナルの画像サイズがスケールアップに十分対応する大きさである場合に有効です。もし足りない場合は近いサイズのイメージになります。

フォーマット

最後のパラメーターにフォーマットを加えることができます。フォーマットは画像のタイプで下記のオプションが使えます。

  • jpg
  • pjpg
{{ product.featured_image | img_url: '450x450', crop: 'center', scale: 2, format: 'pjpg' }}

このような指定により画像はプログレッシブ JPG としてレンダリングされることになります。

Progressive JPG: 上から下へ順番に画像が読み込まれるのでなく、まずはフルサイズの画像が読み込まれて、次第にクオリティがあがっていくタイプの画像フォーマット

Shopify は下記のコンバージョン(変換)が行えます。

  • PNG to JPG
  • PNG to PJPG
  • JPG to PJPG

Caching

最後に、リクエストされた画像が生成されたときについて。生成された画像は Shopify CDN (Content Delivery Network)上にキャッシュされ利用可能になります。そのため、テンプレートがレンダリングされるたびに画像生成が行われることについて心配する必要はありません。

結論

あたらしいパラメーターを使うことにより、テンプレートにて画像をレスポンシブにすることが可能になりました。 html の< picture >要素を使う、もしくはsrcsetsizes使い始めるにせよ、これで適切な画像のサイズや解像度を提供できるようになります。

Chapter 12 img のカスタマイズ方法

このチャプターでは HTML のimg要素を見ていきます。

Shopify のテーマを作る時、assetsフォルダーに好きなだけ画像を加えることができます。一般的にこれらの画像は背景画像やスプライト、ブランドイメージ要素などに使われます。

テーマ内でこれらの画像を参照するのはとても明快です。
ではassetsフォルダーの中にlogo.pngというファイルがあるとします。このイメージは下記のような書き方でどのテンプレートファイル内にでもアウトプットさせることができます。

{{ 'logo.png' | asset_url | img_tag: 'Logo'}}

このアプローチは二つの liquid フィルターをつかって HTML の<img>としてフルで出力されます。
まず最初にasset_urlによって現在のストアのテーマのassetsフォルダーにアクセスします。そしてimg_tagは HTML の< img >タグとして出力されるためのフィルターです。

img_tag のあとの attribute はaltを指定します。記載しない場合は空欄になります。上記の例の Liquid タグは下記のような HTML を出力します。

<img
  src="//cdn.shopify.com/s/files/1/0222/9076/t/10/assets/logo.png?769"
  alt="Logo"
/>

上記の html を見て気づくと思いますがsrcは Shopify の CDN を指定します。イメージ画像追加されるたび、どのようなタイプであれ、Shopify の CDN(Content Delivery Network)に送られます。そのため、asset_urlを使うことにより、どこにその画像ファイルが保存されているかを悩む必要はありません。

img に要素に class を加える

先程の例ではaltの attribute を liquid タグ内で追加しました。それと同様に他の attribute を加えることも可能です。たとえばclassを加えたい場合は下記のように liquid タグを記します。

{{ 'logo.png' | asset_url | img_tag: 'Logo', 'cssclass1 csssclass2' }}

そしてこのタグは以下のような html をアウトプットします。

<img
  src="//cdn.shopify.com/s/files/1/0222/9076/t/10/assets/logo.png?769"
  alt="Logo"
  class="cssclass1 cssclass2"
/>

より詳細なコントロール

もしimgidのような attribute を加えたい場合は、単純にimg_tagのフィルターを使うのではなく下記のように通常の html コードを使って、必要な attribute を自由に付け加えるアプローチもあります。

<img src="{{ 'logo.png' | asset_url }}" alt='Logo' class="cssclass1 cssclass2 " id="logo">

このような柔軟なアプローチも行えます。

Chapter 13 Liquid で便利な CSS Hooks を作る

Javascript hooks や Wordpress のように CSS をbodyクラスを使うように、Shopify にも便利な CSS クラスをbodyエレメントに簡単に加えることができるができます。

body クラスに現在のレンダリングされたテンプレートを加える

<body class="{{ template | handlize }}">

この例では現在使用しているテンプレートの名前を返しています他には下記のようなものです。

<body class="index">
<body class="product">
<body class="collection">

これは特定のオルタネイトテンプレートが必要なときに便利な方法です

現在レンダリングしているプロダクト Handle を body class に加える。

現在の商品のhandleを body class に加えたいとします。ifを使うことにより条件を分岐させて加えることもできます。

<body class="{{template}}{% if template == "product" %}{{ product.handle }} {% endif %}" >

注意 {{ product.handle }}のアウトプットタグにスペースが含まれるようにします。CSS のクラスはスペースによって区切られて個別にレンダリングされるからです。

もしオルタネイトテンプレートをつかっているなら、containのオペレーターを使うとよいでしょう。

<body class="{{ template }}" {% if template contains "product" %} {{ product.handle }} {% endif %} ">

body の class に現在のページタイトルを加える

いくつかのテーマはidを利用し、現在のページのタイトルを body の class に加えているものもあります。下記のような形です。

<body id="{{ page_title | handleize }}" class={{ template }}{% if template == "product" %} {{ product.handle }} {% endif %}">

ここで注目すべきなのがhandlizeの Liquid フィルターを使用しているところです。idclassの名前に空白を含めることはできません。このhandlizeのフィルターにより、例えば "Blue Jeans"は "blue-jeans"のように変換しています。

現在の collection 名を body の class に加える

先に紹介してきたと同じように collection を名前を class に加えることもできます。

<body id="{{ page_title | handlize }}"
class="{{ template }}{% if template == "product" %} {{ product.handle }}{% %}">

このように目的に応じて簡単に調整することができます。
サイド確認ですが、containsはオルタネイトテンプレートを使う時に便利です。

まとめ

このように body の html 要素をいろいろな class を加えることができました。これらの hooks を CSS や Javascript に活用することができます。

Chapter 14 case/when のコントールタグを使う。

if や else のような liquid のタグのような条件分岐のコントロールは case/when でも行えます。

case/when は特定のvariable が条件にマッチしたときにブロックを切り替えることが行なえます。caseでステートメントを切り替え、whenで 条件を特定します。
{% asign handle = 'cake' %}
{% case handle %}
{% when 'cake' %}
This is a cake.
{% when 'cookie' %}
This is a cookie
{% else %}
This is not a cake nor a cookie
{% endcase %}

上記の例では handleが cake のとき「This is a cake.」と、cookie であった場合は、「This is a cookie 」がレンダリングされるような条件の分岐です。また、どの条件も満たさない場合はelseにより「This is not a cake nor a cookie」がレンダリングされます。

もしelseを設定せず、どの条件にも満たない場合は何もアウトプットされません。

実用的なケース

たとえば実際に用いる例として、特定の商品によって違う種類のプロモーションバナーを表示させるなどがあります。

{% asign handle = product.handle %}
{% case handle %}
{% when 'coffee- cup' %}
  {% render 'promo-coffee-cup' %}
{% when 'cup-saucer' %}
  {% render 'promo-cup-saucer' %}
{% else %}
  {% render 'promo-default' %}
{% endcase %}

上記の例ではまずhandleproduct.handleをアサインしています。 そしてcasewhenの条件分岐を設定していきます。

商品の handleが coffee-cup の場合は、promo-coffee-cupのスニペットがレンダリングされます。

商品のhandlecup-saucer の場合は、promo-cup-saucerのスニペットがレンダリングされます。

そしてどれにも該当しない場合はpromo-defaultのスニペットがレンダリングされます。

このように特定のケースに応じて特定のブロックやスニペットなどの表示を切り替えることができます。 if 文だけだと条件わけが難しい、複数の条件に対して特定のコードを実行したい場合はcase/whenのタグが役に立ちます。