Shopifyのフォームってどうなってるの?という疑問に答える解説記事。{% form ‘product’ %}の役割や、variant_idと数量がどのようにサーバーへ送られているのかを、専門用語をかみ砕きながら丁寧に解説します。

ノーコードで実装できるECサイト構築プラットフォームとして注目を集めるShopifyですが、使い慣れてくると「この裏ではいったい何が起きているのだろう?」と気になる瞬間があります。
画面上ではボタンひとつで動いているように見える処理も、仕組みを知ることでカスタマイズの幅が広がり、「あ、こういうアイディアも実装できそうだ」と気づける場面が増えていきます。
そこで今回は、Shopifyを触り始めて間もない私が、初心者ならではの視点で“Shopifyの裏側の仕組み”を少しずつ言語化してみたいと思います。
テーマは「フォームの仕組み」。商品ページやお問い合わせページなど、Shopifyのあらゆる場所で使われているフォームが、どのように動き、Shopifyにどんな情報を送っているのか。初心者だからこそ気になるポイントを、できるだけわかりやすくまとめてみました。
formの書き方
Shopifyのフォームは、基本的に「{% form ‘〇〇〇’ %} ~ {% endform %}」という書き方で構成されています。
この「〇〇〇」部分には、フォームの種類を示すキーワードを指定します。
たとえば、商品をカートに入れるときに使う「product」、ログイン画面で使われる「customer_login」、問い合わせフォームで利用される「contact」などが代表的です。
見慣れない単語が続くように見えますが、Shopify側があらかじめ「このフォームはこう動きますよ」というルールを用意してくれているため、実際にはとてもシンプルです。
今回はこの中でも、もっとも利用頻度が高く、Shopifyの理解を深めるうえでも非常に重要な「{% form ‘product’ %}」にフォーカスしたいと思います。
商品ページにある「カートに追加」ボタンの裏側では何が送信され、どのようにShopifyに処理されるのか。この仕組みを知ることで、Shopifyのフォームというもの全体がぐっと理解しやすくなるはずです。
{% form ‘product’ %} の挙動
「{% form ‘product’ %}」は、Shopify特有の「フォームを自動生成するLiquidタグ」です。このタグが展開されると、実際のHTMLとしては次のようなコードが生成されます。
<form method="post" action="/cart/add">
つまり、Shopifyの商品ページで見かける「カートに追加」ボタンは、この<form>要素の送信によって動いています。
{%- form ‘product’ %} の内部には、次のようなボタンが配置されています。
<button
id="ProductSubmitButton-{{ section_id }}"
type="submit">
…
</button>
このボタンがクリックされると「type=”submit”」の働きによってフォームが送信され、「POST」方式で「ショップURL/cart/add」にデータが渡されます。
「/cart/add」は実在するファイルではない
URLを見ると「cart/addというファイルがあるのかな?」と思いがちですが、そうではありません。
「/cart/add」は Shopify のサーバー側に用意された“入り口”で、フォームから送られたデータを受け取るためのエンドポイント。Shopifyのバックエンド(Ruby on Rails)で処理されており、商品ID(variant_id)などを受け取り、サーバー側でカート情報を更新してくれます。初心者のうちは「Shopify側がカート追加処理を全部やってくれている」と理解するだけで十分です。
{% form ‘product’ %} が実際に送っているデータ
「{%- form ‘product’ %}」がShopifyに送信するデータは、実はとてもシンプルで、主に次の2つだけです。
・ユーザーが選んだバリエーションID(variant_id)
・数量(quantity)
HTMLとして見ると、送られるデータは次のような<input> で表現されます。
<input type="hidden" name="id" value="40123456789">
<input type="number" name="quantity" value="1" min="1">
variant_idが自動で入る仕組み
「{{ product.selected_or_first_available_variant.id }}」が value に入るため、ページが読み込まれた時点では「その商品の最初のバリエーション」が自動的に選ばれた状態になります。
ユーザーが色やサイズを切り替えると、JavaScriptがその変化を検知し、DOM操作で「hidden」の「value」を新しい「variant_id」に書き換える ことで、正しいデータが送信されます。
quantityのinputがformの中に見えない問題
あれ?form の中に quantity の input が見当たらない?
という疑問が必ず出てきます。
ところが、ユーザーが数量を変えると、しっかりShopifyに「quantity」が送られている‥これには理由があります。
その秘密は「<quantity-input>」と「form=”〇〇〇”」属性にある!
Shopifyでは、数量入力部分は専用のウェブコンポーネント「<quantity-input>」として実装されています。
その内部に実際の<input> が入っており、次のような形になっています。
<input
type="number"
name="quantity"
value="1"
form="{{ product_form_id }}"
>
ここで重要なのが「 form=”{{ product_form_id }}”」これはHTMLの標準仕様で、「この <input>は 、指定したformに属するものとして一緒に送信してね」という意味になります。
つまり、<input>がフォームタグの“外側”にあっても「form=”product-form-〇〇”」と書かれていれば、フォーム送信時に自動的にその値が紐づいて送られるというわけです。
初心者にとってはちょっとしたトリックのように見えますが、Shopifyはこの仕組みを利用して、複雑なHTML構造でも整然とデータを送信できるようにしているのです。
一般的には「form=”{{ product_form_id }}”」という形で指定されていますが、この「product_form_id」は 「カートに入れる」ボタンが属している商品用フォーム を指しています。
このフォームが、その商品の“メインフォーム”としての立ち位置を持ち「variant_id」や「quantity」など、商品追加に必要な情報をまとめて Shopify に送信する役割を担っています。
{% form %} 内の属性と構成要素
「{% form ‘product’, … %}」は、Shopifyが用意している特別なLiquidタグで、フォームに必要なHTML属性を自動で生成してくれる仕組みです。
生成された <form> タグには、いくつかの重要な属性が含まれます。
product:フォームの種類を指定
「product」を指定すると、Shopifyは自動的に次のようなフォームを生成します。
つまり「POST で /cart/add にデータを送ってカート追加を行うフォーム」を自動生成しているというわけです。
product(シングルクォーテーションなし):商品オブジェクトを渡す
ここでは、シングルクォーテーションを外し、商品オブジェクトを意味します。
「product」をフォームに渡すことで、「product.title」「product.variants」「product.selected_or_first_available_variant」など、該当する商品のプロパティをフォーム内で利用できるようになります。
id: product_form_id:フォームの固有IDを付与する
Shopifyはフォームひとつひとつに固有IDを設定します。
例:product-form-template–123__main
class: ‘form’:CSSやJS用の識別子
CSSやJS用のターゲットとして利用される識別子を設置します。
novalidate: ‘novalidate’:ブラウザによる入力内容チェックを無効化
商品追加フォームでは、ブラウザ側のバリデーションは不要なため、「novalidate」が付けられています。
Shopify側で正しいデータ処理を行うため、フォームレベルでの細かい入力チェックはあえて行わないというとの事です。
data-type: ‘add-to-cart-form’:JavaScript用のフック
JavaScript側がフォームを識別する際に利用される属性です。イベントハンドリングしやすくなるメリットがあります。
カスタマイズで最低限おさえるべき必須要素
Shopifyで独自カスタマイズをする場合、最低限押さえておきたいのは次の2つだけです。
・’product’(フォームの種類・エンドポイントを決める)
・product(商品オブジェクトそのものをフォームへ渡す)
実は、この2つが揃っていれば、カート追加処理として最低限の機能は成立します。
他の属性は「識別しやすくしたい」「JSで扱いやすくしたい」といったShopifyテーマとしての整備のための付加情報です。
***
いかがでしょうか。Shopifyのフォームの仕組みに、ほんの少しでも近づけたような気がしていただけたなら嬉しいです。
もちろん、フォーム送信の裏側では Shopifyのエンドポイントが動いており、そこで行われる処理はブラックボックスです。したがって、カスタマイズにもどうしても限界があります。しかし、それでも“仕組みを知っている”かどうかで、構築や運営のアイディアは大きく変わります。
「この動きにはこういう裏があるんだ」と理解できると、テーマの読み解きもぐっと楽になり、実装の自由度も一段階上がります。ぜひ今回の内容をきっかけに、Shopifyの裏側にあるロジックにも少しずつ触れていってみてください。

