Shopifyテーマでお客様が自由に入力できるオプション欄を作る方法
本記事は私達の会社で作ったShopifyテーマ開発入門書『Hello Shopify Themes Shopifyテーマ開発ガイド』からの抜粋です。
注文時にユーザーからの追加情報を受け付けたいというリクエストは多くのストアで見られます。たとえばギフトラッピングの希望や、商品に刻印する文言、配送の日時指定などです。
アプリを用いて対応しても良いのですが、ちょっとしたカスタム情報の入力欄ならば、Liquid編集だけで充分に実装できます。
本節では、「Line Item Property」と「Cart attributes」という仕組みを用いて、商品ページに「刻印文言」の入力要素を、カートページに「ギフトラッピング希望」のチェックボックスを追加します。
本節で学ぶもの
- Line Item Propertyの概要と使い方
- Cart attributesの概要と使い方
- Shopify UI Elements Generatorの活用
- Dawnにおける商品購入フォームの設計
- テスト注文の実施
本節で作るもの
- 商品ページで「刻印文言」の入力を受け付ける
- カートページにギフトラッピング希望のチェックボックスを追加
本記事の内容はYouTube上でも解説しています。
配送日時指定の追加について
本節で紹介するCart attributesを用いれば、カートページに配送日時指定の入力要素を追加できます。
ただ、実案件においては、配送日時指定はアプリを利用するケースが多いです。
※アプリを用いない場合、配送停止期間(休日や年末年始など)の細かな調整・配送業者ごとに異なる指定可能時間帯への対応などが難しいため。
代表的な配送日時指定アプリについては、第5章で後述します。
目次
Line Item Propertyで商品ページに入力欄を追加する
さっそく、Line Item Propertyを用いて、刻印文言の入力要素を商品ページに追加してゆきましょう。
Line Item Propertyについて
まず、Line Item Propertyとは、商品のカート追加フォームから送信可能な情報を拡張するものです。
一定の規則に沿ったフォームウィジェット(input要素やselect要素などの、フォームのデータ入力要素)を商品ページに追加することで、刻印文言のようなカスタマイズ情報を取得し、商品が購入された時にShopify側へ追加のデータを渡せるようになります。
Shopifyに送信されたLine Item Propertyの情報は、管理画面の注文詳細ページから確認できます。ユーザーへ送られる注文完了メールや、マイページの注文情報からもアクセス可能です。
次に示すのはLine Item Property入力要素のサンプルコードです。
name属性を "properties[任意名称]"
の形式で指定し、商品のカート追加フォームと関連づけられたフォームウィジェットは、Line Item Property入力要素となります。
<input type="text" name="properties[任意名称]">
Shopify UI Elements Generatorを活用する
inputなどの入力要素は自身で作成しても良いのですが、今回は、Shopifyから提供されている「Shopify UI Elements Generator」を利用します。
https://ui-elements-generator.myshopify.com/pages/line-item-property
Shopify UI Elements Generator
Shopify UI Elements Generatorは、フォームの入力タイプ(テキスト・セレクトボックス・ラジオボタンなど…)ごとに適したHTMLを、Line Item Propertyなどの種別に沿った形式で自動的に生成してくれます。
ツールを用いて生成したLine Item Propertyのテキスト入力input要素がこちらです。
<p class="line-item-property__field">
<label for="">刻印する文言</label>
<input id="" type="text" name="properties[刻印する文言]">
</p>
id属性などは空欄で生成されるので、適宜調整してください。
このコードをDawnに組み込んでゆきます。
開発テーマの立ち上げ
開発テーマで実際に編集してみたい方は、次のコマンドでローカル環境を立ち上げてください。
shopify theme dev
コマンド実行後、テーマエディタへアクセスするためのURLも表示されるので、適宜利用しましょう。
Liquidに入力要素を記述する
商品ページの商品情報セクションに追加したいので、前節に引き続き sections/main-product.liquid
を編集してゆきます。
編集箇所の確認
商品のカート追加フォームはどこにあるかというと、Dawnでは {%- for block in section.blocks -%}
ループ内の {%- when 'buy_buttons' -%}
ブロックで呼び出されている snippets/buy-button.liquid
内にあります。
sections/main-product.liquid
{%- for block in section.blocks -%}
{%- case block.type -%}
//略
{%- when 'buy_buttons' -%}
{%- render 'buy-buttons', block: block, product: product, product_form_id: product_form_id, section_id: section.id, show_pickup_availability: true -%}
//略
snippets/buy-button.liquid
<product-form
class="product-form"
data-hide-errors="{{ gift_card_recipient_feature_active }}"
data-section-id="{{ section.id }}"
>
//略
{%- form 'product',
product,
id: product_form_id,
class: 'form',
novalidate: 'novalidate',
data-type: 'add-to-cart-form'
-%}
HTMLのカスタム要素
見慣れないHTML要素 <product-form>
は、 assets/product-form.js
で定義されている自律カスタム要素(divでもsectionでもない、独自に定義されたHTMLタグ)です。本書では解説しませんが、詳しく知りたい方はWeb ComponentsやCustom Elementsで調べてみてください。
HTMLのform要素は、Liquidタグの {%- form 'product', …… -%}
によってレンダリングされています。
このform内に、先ほど生成したLine Item Propertyのinput要素を追加……しても良いのですが、ここで、このformがループ処理の {%- when 'buy_buttons' -%}
内に存在することに注目してください。
前節で解説したとおり、 {%- case block.type -%}
〜 {%- when 'ブロックのタイプ値' -%}
の条件分岐は、テーマエディタから追加されたブロックのタイプに従ってLiquidをレンダリングしています。
そのため、ここで {%- when 'buy_buttons' -%}
内のform要素にinput要素を記述すると、購入ボタン(buy_buttons)ブロックから切り離せず、表示位置を自由に変更できなくなってしまいます。
form要素内に追加した場合のイメージ
購入ボタンブロック内に、Line Item Propertyの「刻印する文言」input要素を追加した場合。
たとえば数量セレクターブロックの上に、刻印のinput要素のみを移動させたくても、購入ボタンブロックから切り離せないため不可能
そこで、本節ではform要素の外側にフォーム入力要素を配置する方法を紹介します。
formの外にLine Item Propertyのinput要素を配置する
勘の良い方は「あれ、数量セレクターもバリエーションピッカーも、購入ボタンブロックの外に存在してるな」と気づかれたかもしれません。
Dawnでは、各要素の並び替えを優先してか、多くのフォーム入力要素がフォームの外側に独立して配置されています。数量セレクターのinput要素が分かりやすいです。
フォーム外の入力要素は、 form="関連づけたいフォームのid値"
属性を付与することで、関連づけたフォームの送信対象に含めることができます。
sections/main-product.liquid
// 数量セレクターのinput要素。form属性が指定されている
<input class="quantity__input"
type="number"
name="quantity"
id="Quantity-{{ section.id }}"
min="1"
value="1"
form="{{ product_form_id }}"
>
既に存在するフォーム入力要素に倣い、Line Item Propertyのinput要素に form="{{ product_form_id }}"
属性を追加しましょう。
最終的に、 sections/main-product.liquid
へ追加するコードは次のようになります。
一旦、 {%- for block in section.blocks -%}
の外側に配置してみましょう。
sections/main-product.liquid
{%- for block in section.blocks -%}
// 略
{%- endfor -%}
// ループの外に配置
<p class="line-item-property__field">
<label for="engraveTxt">刻印する文言</label>
<input id="engraveTxt" type="text" name="properties[刻印する文言]" form="{{ product_form_id }}">
</p>
ローカル環境の商品ページを開くと、刻印文言の入力要素が追加されています。
任意のテキストを入力し、カートに追加してみましょう。カート追加の通知ウィンドウと、カートページの該当商品に、入力した刻印のテキストが表示されれば成功です!
商品カート追加時、メタフィールドの受け渡しに成功
刻印テキストを入力し「カートに追加する」ボタンをクリックした場合の表示。
Line Item Propertyのinput要素はカート追加フォームの外に存在するが、問題なく値を送信できている
現状はLiquid内にハードコードしている状態のため、ブロックとしてテーマエディタから利用できるようにしたければ、「3-2. 動的セクションとブロックの作成」の解説を参考にカスタマイズしてみてください。
Shopify Dawnテーマのカスタマイズ 〜動的セクションとブロックの作成〜
補足:うまく動作しない場合
Dawnのバージョンによってはform属性の記述が異なるため、サンプルの form="{{ product_form_id }}"
では動かないかもしれません。
これらのform属性は、関連づけたいform要素のid属性と一致させる必要があるため、 {%- form -%}
タグのidに何が渡されているかを確認してください。
sections/main-product.liquid
// 一例:Dawn 3.0.0における記述
// Liquid変数product_form_idの定義
{%- assign product_form_id = 'product-form-' | append: section.id -%}
// form要素外のinput要素。form属性に変数product_form_idが指定されている
<input class="quantity__input"
type="number"
name="quantity"
id="Quantity-{{ section.id }}"
min="1"
value="1"
form="{{ product_form_id }}"
>
// Liquidのformレンダリングタグ。id属性に変数product_form_idが指定されている
{%- form 'product', product, id: product_form_id, class: 'form', novalidate: 'novalidate', data-type: 'add-to-cart-form' -%}
Cart attributesでカートページに入力欄を追加する
続けて、Cart attributesを用いて、ギフトラッピング希望のチェックボックスをカートページに追加してゆきます。といっても、基本的な流れはLine Item Propertyと同様です。
Cart attributesについて
Cart attributesは、カートの商品購入フォームから送信可能な情報を拡張します。Line Item Propertyのカート版と捉えると分かりやすいです。
Cart attributesもまた、一定の規則に沿った入力要素をカートに追加することで、カスタマイズ情報を取得し、商品の購入時にShopify側へ追加データを送信できるようになります。
Shopifyに送信されたCart attributesの情報は、管理画面の注文詳細ページに表示されます。ユーザーへの注文完了メールや、マイページの注文情報にも表示可能です。
次に、Cart attributesのサンプルコードを示します。
name属性を attributes[任意名称]
形式で指定し、カートの商品購入フォームと関連づけられたフォームウィジェットは、Cart attributes入力要素となります。
<input type="text" name="attributes[任意名称]">
Shopify UI Elements Generatorを活用する
Cart attributesの要素生成にも、前述した「Shopify UI Elements Generator」が使えます。
https://ui-elements-generator.myshopify.com/pages/cart-attribute
Line Item PropertyとCart attributesとで生成される要素は異なります。適切なジェネレーターを利用してください。
今回、生成したギフトラッピング希望チェックボックスのコードは次のとおりです。
<p class="cart-attribute__field">
<input type="hidden" name="attributes[無料ラッピング希望]" value="No">
<input type="checkbox" name="attributes[無料ラッピング希望]" value="Yes"{% if cart.attributes["無料ラッピング希望"] == "Yes" %} checked{% endif %}>
<label>無料ラッピング希望</label>
</p>
さっそく、Dawnにコードを組み込んでゆきましょう。
Liquidに入力要素を記述する
今回のコードはカートページに追加します。
Dawnのカートページは、カート内のアイテム詳細部分と、備考欄・小計・購入ボタン部分とが別々のセクションファイルに記述されているのですが、今回のギフトラッピング希望チェックボックスは備考欄の傍に表示させたいので、 sections/main-cart-footer.liquid
ファイルを利用します。
なお、初期設定では備考欄が非表示になっているため、テーマエディタ「小計」セクションの設定から「カートメモを有効にする」にチェックを入れておきましょう。
編集箇所の確認
カートページの備考欄は、{%- if section.settings.show_cart_note -%}
タグ内にあります。
sections/main-cart-footer.liquid
{%- if section.settings.show_cart_note -%}
<cart-note class="cart__note field">
<label for="Cart-note">{{ 'sections.cart.note' | t }}</label>
<textarea class="text-area field__input" name="note" form="cart" id="Cart-note" placeholder="{{ 'sections.cart.note' | t }}">{{ cart.note }}</textarea>
</cart-note>
{%- endif -%}
※ <cart-note>
はHTMLのカスタム要素です。カスタム要素については、Line Item Propertyの解説パートで備考として紹介しています。
備考欄を示す <cart-note>
要素の隣に、先ほど生成したCart attribute入力要素を追加します。
Line Item Attributeのときと同様に、フォームの外側に入力要素を配置する関係上、form属性の指定が必要です。
備考欄の textarea
要素を見ると form="cart"
属性が指定されていますね。こちらの記述に倣い、Cart attribute入力要素にも form="cart"
を追加しておきます。
完成したコードは次のとおりです。label
要素の for
属性と、 input
要素の
id`` 属性も追記しておきました。
{%- if section.settings.show_cart_note -%}
<cart-note class="cart__note field">
<label for="Cart-note">{{ 'sections.cart.note' | t }}</label>
<textarea class="text-area field__input" name="note" form="cart" id="Cart-note" placeholder="{{ 'sections.cart.note' | t }}">{{ cart.note }}</textarea>
</cart-note>
//EDIT_START
<p class="cart-attribute__field">
<input type="hidden" name="attributes[無料ラッピング希望]" form="cart" value="No">
<input type="checkbox" id="giftRequest" name="attributes[無料ラッピング希望]" form="cart" value="Yes"{% if cart.attributes["無料ラッピング希望"] == "Yes" %} checked{% endif %}>
<label for="giftRequest">無料ラッピング希望</label>
</p>
//EDIT_END
{%- endif -%}
ローカル環境のカートページを開くと、備考欄の近くに、無料ラッピング希望のチェックボックスが表示されています。
無料ラッピングのチェックボックスを追加したカートページ
これで完成……と言いたいところですが、実際にShopify側にデータを送信できているかどうか、テスト注文を行って確かめてみましょう。
テスト注文は、ローカル環境ではなく開発ストアから行うため、ここまでの作業内容を、ストアのテーマライブラリー内テーマに反映しておきます。
テーマのアップロード
開発テーマでの作業が終わったら、作業内容をテーマライブラリー内のテーマに反映させましょう。
shopify theme push
テスト注文で管理画面上の表示を確認する
初めてテスト注文を実施する場合、ストア上でいくつかの設定が必要です。
ここではテスト注文を行うための決済サービスとしてShopifyのBogus Gatewayを紹介します。Bogus Gatewayを有効化している間は、実際の注文を受け付けられない点に注意してください。
Bogus Gatewayを有効化する
ストア管理画面の「設定」から、「決済」のページを開きます。
ストアの決済設定ページ
決済設定ページの画面上部に「開発ストアでは、テスト決済のみを処理できます」の案内文が出ていますね。
案内文の「決済サービスをテストする」リンクをクリックしてください。
Bogus Gatewayの設定ページに遷移します。
Bogus Gateway設定ページ
「(for testing)Bogus Gatewayを有効化する」ボタンをクリックしてください。
これで、テスト注文を行うための設定は完了です。
テスト注文を行う
Line Item PropertyとCart attribute、それぞれを入力した状態で、カートページから購入手続きのチェックアウトへ移動しましょう。
次のように、決済画面でBogus Gatewayが利用できるようになっています。
テスト注文が有効化されたチェックアウト画面
カード番号、カードの名義人、有効期限、セキュリティコードをそれぞれ次のとおり指定し、支払いを実行します。
- カード番号:1
- カードの名義人:Bogus Gateway
- 有効期限:未来の日付(月/年の形式)
- セキュリティコード:任意の3桁数字
Bogus Gatewayの取引シミュレーション種別
カード番号によって、取引失敗・エラーなどのシミュレーションも可能です。
詳しくはShopifyのヘルプセンターで解説されているので、併せて参考にしてください。
テスト注文を行う
https://help.shopify.com/ja/manual/checkout-settings/test-orders
管理画面の注文データを確認する
テスト注文を実行できたら、管理画面の「注文管理」から、先ほど行った注文の詳細を確認してみましょう。
注文詳細に、今回追加した「刻印する文言」内容と「無料ラッピング希望」情報が表示されていれば、成功です!
注文詳細画面
Line Item Propertyの「刻印する文言」は購入された商品の情報部分に、Cart attributeの「無料ラッピング希望」は注文メモ欄の「追加の詳細」部分に表示されています。
メモとして表示されているのは備考欄の入力内容です。
より高度にするなら
解説の中でも言及したとおり、Line Item PropertyとCart attributeの入力要素をそれぞれ独自のブロックとして作ると、テーマエディタからの操作性が向上します。
ブロックの作成手順については前節「3-2. 動的セクションとブロックの作成」で詳しく解説しているので、そちらを参考に試してみてください。
Shopify Dawnテーマのカスタマイズ 〜動的セクションとブロックの作成〜
Customer note
本書では割愛しましたが、ユーザーのアカウント登録フォームにも、Line Item PropertyとCart attributeと同様にカスタム情報を収集するための仕組みとして「Customer note」が存在します。
本来、アカウント登録フォームには「姓・名」「メールアドレス」「パスワード」の入力項目しか存在しません。Customer noteを用いると、たとえばユーザーの誕生日やアレルギー情報などの入力項目を、アカウント登録フォームに追加できます。
公式ドキュメントにサンプルコードが公開されているので、実装の際は参考にしてみてください。
https://shopify.dev/themes/customer-engagement/additional-customer-information
通知メールに表示する
もう一つ。Line Item PropertyとCart attributeで取得したデータは、Liquidのオブジェクトとして利用可能です。
Shopifyから送られる注文完了などの通知メールはLiquidで構成されているので、ここにLine Item PropertyとCart attributeの記述を加えれば、マーチャントとユーザーのコミュニケーションをより良い形にサポートできるでしょう。
通知メールにおける line_item.properties
オブジェクトの記述例を次に示します。
// ※購入された商品の出力ループ内に記述すること
{% for line in subtotal_line_items %}
{% unless line.properties == empty %}
{% for property in line.properties %}
<p>{{ property.first }}: {{ property.last }}</p>
{% endfor %}
{% endunless %}
{% endfor %}
// ▼レンダリング結果(Line Item Propertyのname名:入力データ)
// 刻印する文言: 文言サンプル
cart.attributes
オブジェクトの記述例は次のとおりです。
{% for attribute in attributes %}
{% assign attributecheck = attribute | last %}
{% if attributecheck != "" %}
<p>{{ attribute | first }}:{{ attribute | last }}</p>
{% endif %}
{% endfor %}
// ▼レンダリング結果(Cart attributeのname名:入力データ)
// 無料ラッピング希望:Yes
各オブジェクトの詳細は、公式ドキュメントを参照してください。
https://shopify.dev/api/liquid/objects/line_item#line_item-properties
https://shopify.dev/api/liquid/objects/cart#cart-attributes
Shopify公式ブログによる解説
本節で解説したCart attributesとLine Item Property(と、割愛したCustomer note)について理解を深められる教材として、Shopify Japan公式ブログの記事を紹介します。
とても分かりやすくまとまっているので、関心があればぜひ一読してみてください。
Shopify Japanの公式ブログは、Shopifyの最新情報や開発Tipsが日本語で発信されており、情報源のひとつとしてオススメです。
Shopifyテーマカスタマイズの三種の神器:Cart attributes、Line Item Property、Customer noteを使いこなそう!
https://www.shopify.jp/blog/partner-shopify-theme-customize-cart-attributes-line-item-property-customer-note
完売後の増刷予定は現時点ではございません。印刷書籍をご希望の方は、ぜひお早めにお迎えください。
- 著者:川島さやか
- 出版:non-standard world, Inc.
- 判型・ページ数:B5判・248ページ
- 価格:3,850円(税込)※PDF版同梱、送料無料