Skip to main content
カスタムテンプレートを使うと、個々のブロックのレンダリング方法を上書きできます。ブロックの組み込み UI の代わりに、カートは、そのブロックが通常使うのと同じデータを使って、あなた自身の JSX をレンダリングします。これは特定のブロックではなく横断的な機能で、ほとんどのブロックが Code タブからこの機能を公開しています。 このページでは、すべてのブロックに当てはまる内容を扱います。特定のブロックが渡してくる props については、そのブロック自身のリファレンスを参照してください。

カスタムテンプレートと Custom code ブロックの違い

似ているように聞こえますが、役割は異なります:
  • カスタムテンプレートは、既存ブロックのレンダリングを独自のマークアップで置き換え、そのブロック自身のデータ(Header のタイトルとアイテム数、Summary の合計金額など)を渡してくれます。新しいものを追加するわけではなく、1 つのブロックの見た目を作り直すものです。
  • Custom code ブロックは、任意の HTML または React の新しいブロックをカート内のどこにでも追加します。
組み込みブロックがほぼ望みどおりだけれどレイアウトやマークアップを変えたい場合はカスタムテンプレートを、組み込みブロックではカバーできないものを追加したい場合は Custom code ブロックを使ってください。

カスタムテンプレートの使い方

  1. エディタでブロックを選択し、Code タブを開きます。
  2. デフォルトのテンプレートを編集します。カスタムテンプレートは JSX のみです(HTML か JSX かの選択肢があるのは Custom code ブロックだけです)。
  3. Compile をクリックします。コンパイルは型を取り除き JSX をトランスパイルするため、構文エラーを検出します。型エラーはコンパイルを止めません。エディタが入力中にインラインで指摘し、ブロックの props を自動補完するのと同じ IntelliSense が使われます。
  4. テンプレートをオンにすると、カートは組み込みのレンダリングの代わりにそれを使用します。
  5. Reset to default で、いつでもブロックの元のテンプレートを復元できます。

AI でテンプレートを書く

Code タブには Copy AI prompt ボタン(✦ ワンドアイコン)があります。クリックすると、AI チャットセッション(Claude、ChatGPT など)にそのまま貼り付けられる自己完結型のブリーフがクリップボードにコピーされます。 このプロンプトには、その特定のブロック向けに有効なテンプレートを書くために AI が必要とするすべてが含まれています:
  • コンパイルのルール(単一の式、export default なし、import なし)
  • エディタの IntelliSense に表示されるものと一致する、ブロックが受け取る正確な props
  • エディタが強制するロックされた関数シグネチャ
  • ブロック固有のルール(金額のフォーマット、接続すべきハンドラ、アクセシビリティ要件)
  • 現在のテンプレートを貼り付け、望む変更を記述する記入セクション
コピーしたら AI セッションを開き、プロンプトを貼り付け、末尾の 2 つの空欄(現在のテンプレートと望む変更)を埋めて送信します。AI は、エディタに貼り戻してコンパイルできる完全なテンプレートを返します。
記入セクションは空欄のままにせず、既存のテンプレートを貼り付けてください。AI はそれを出発点として使うため、すでに行ったカスタマイズがデフォルトに置き換えられることなく引き継がれます。
プロンプトはブロックごとに固有です。Copy AI prompt ボタンは、カスタムテンプレートをサポートするブロックにのみ表示されます。
出発点となるデフォルトのテンプレートは、ブロックの組み込みマークアップの動作するコピーなので、白紙のページからではなく、正しくレンダリングされるリファレンスを修正する形で始められます。そのリファレンスを取り戻したくなったら、いつでも Reset to default を使ってください。必ずしもバイト単位で一致するわけではありません。Header のデフォルトテンプレートは logoUrl もレンダリングしますが、組み込みマークアップにはその配置場所がないため、アップロードしたヘッダー画像が最初に表示されるのは、そのテンプレートをオンにしたときです。

テンプレートが置き換えるもの

テンプレートはブロックのレンダリングを完全に置き換えます。あなたの JSX の周りにラッパーは残らないため、削除を始める前に知っておくべき影響があります:
Design タブは特に見落とされがちなポイントです。 カスタムテンプレートが有効な間、Design タブのフィールドは無効化され、「Design」見出しの横に警告アイコンが表示されます。アイコンにカーソルを合わせると理由が表示されます。代わりに、インラインまたは独自の CSS を使ってテンプレートからブロックにスタイルを当ててください。カスタムテンプレートをオフにすると、フィールドはすぐに再び有効になります。
保持されるもの: カート内でのブロックの位置、表示切り替え、設定(受け取る props には引き続き反映されます)、カートの Custom CSS パネル、そして組み込みのローディングスケルトンです。 最後の項目は意外に思われがちです。ブロックはテンプレートに到達する前にカートがまだ読み込み中かどうかを確認するため、読み込み中は組み込みのスケルトンがレンダリングされ、テンプレートはカートの準備が整ってから実行されます。ローディング状態を自作する必要はありません。

テンプレート内で利用できるもの

テンプレートは単一の関数コンポーネントです。TSX からコンパイルされるため、型注釈は許可され、コンパイル時に取り除かれます。デフォルトのテンプレートが型注釈付きで書かれているのはそのためです:
シグネチャの行と閉じ括弧はロックされています。 エディタはどちらも編集させず、カーソルを合わせると「Locked — this line can’t be edited.」と表示されます。本体はその間に記述します。これらを置き換えられる唯一の手段が Reset to default です。 その他に重要な点:
  • 使えるフックは 5 つです: useStateuseEffectuseMemouseRefuseCallback。加えて <>…</> のための Fragment
  • import はできません。 何も import できず、スコープ内に React オブジェクトも存在しないため、React.useReducerReact.Children も使えません。上のリストにないフックは利用できません。
  • props は読み取り専用です。 props を書き換えても意味のある結果にはなりません。カートを変更するには、props に直接書き込むのではなく、ブロックが提供するハンドラの props(onCloseincrementselectPlan など)を使ってください。
  • window にはアクセスできます。 そのため、ブロックの props でカバーされないものが必要な場合、テンプレートは window.aftersell.cart 経由で Cart SDK を呼び出せます。

すべてのブロックに共通する規約

3 つのルールがどこでも成り立ち、これを知っておけば推測作業のほとんどがなくなります:
  • *Html という props はサニタイズ済みのリッチテキストです。 dangerouslySetInnerHTML でレンダリングしてください。すでにカートのサニタイザーを通過しており、{{total_price}} のようなマーチャントトークンも解決済みです。
  • string で渡される価格は、ショップの金額フォーマットですでに整形済みです。 number の価格はセント単位です。ブロックはどちらか一方を渡し、各ブロックの表にどちらかが記載されています。
  • テンプレート内では isLoading は常に false です。 ブロックは組み込みのスケルトンをレンダリングし、カートの読み込みが完了してからテンプレートを呼び出すため、この prop は分岐のためではなく網羅性のために渡されています。
一部のブロックは特定の状態では何もレンダリングしないため、テンプレートが空のデータで呼び出されることはありません。Rewards のテンプレートが空の milestones を受け取ることはなく、Subscription upgrade のテンプレートが null の view を受け取ることもありません。各ブロックのリファレンスに該当箇所が記載されているため、空状態の分岐は省略できます。

カスタムテンプレートのスタイリング

出発点となるデフォルトのテンプレートには、ブロックのクラス名が付いています。編集にどうスタイルを当てるかは、その出発点からどれだけ離れるかによって変わります。

2 つのクラスファミリー

デフォルトテンプレートのすべての要素には対になるクラス名が付いており、それぞれの役割は大きく異なります: つまり、cart-internal-header__title はタイトルを組み込みのタイトルらしく見せているものであり、cart-external-header__title は見た目を変えたいときにつかむべきハンドルです。

小さな変更: 両方のクラス名を残す

要素の並べ替え、ラベルの変更、既存の構造の中への追加を行う場合は、クラス名には手を付けないでください。組み込みの見た目をそのまま維持でき、cart-external-* フックを対象にした Custom CSS でスタイルを変更できます。

構造の変更: 両方のクラス名を外す

微調整ではなく DOM 構造そのものを変える段階になったら、マークアップから両方のファミリーを外し、代わりに独自のクラス名を使ってください。それぞれに別の理由があります。 cart-internal-* を外すのは、組み込みの CSS が組み込みの DOM のために書かれているからです。 構造を変えたマークアップにこれらのクラスを残すと、もう存在しない要素を前提としたレイアウトルールを継承してしまいます。異なる子要素を期待する flex コンテナ、移動した要素間の余白、削除したものを基準にした位置指定などです。これは通常、組み込みのルールが勝ってしまうことで、自分の CSS が「効かない」という形で表面化します。
cart-external-* を外すのは、それが共有された名前であって、あなたのものではないからです。 これらのクラス名は組み込みのマークアップ上で特定の意味を持ち、あなたの Custom CSS はカート全体に対して一度だけ書かれます。構造を変えたテンプレートがそれらを再利用すると、書いたルールはあなたの構造と組み込みの構造の両方を対象にしてしまいます。問題が起きるのは、カスタムテンプレートをオフにした瞬間です。ブロックは組み込みのマークアップに戻りますが、CSS は依然としてそれを指したままで、本来想定していなかった DOM にスタイルを当ててしまいます。独自のプレフィックスを使えば両者がきれいに分離され、テンプレートのオフがクリーンな復元になります。
作ったものにスタイルを当てる方法は 2 つあります:

オプション 1: 独自のクラス名 + Custom CSS

保守や再利用をするものに最適です。通常はストア名やブランド名など、他と衝突しないプレフィックスをクラスに付けてください:
次に、カートエディタで左パネルの Cart settings を選択し、右側の Custom CSS タブを開きます:
プレフィックスは見た目以上に重要です。プレフィックスがないと、.header.title のようなクラスは、カート自身のクラス、他のアプリのテンプレート、将来のブロックと衝突するおそれがあります。

オプション 2: インラインスタイル

CSS パネルとの行き来が不要で、すべてが 1 か所に収まります:
レイアウトの骨組みや一度きりの用途に向いています。制約はよくあるものです: :hover などの疑似クラスは使えず、メディアクエリも使えず、ブロック間での再利用もできません。これらのいずれかが必要になったら、オプション 1 に切り替えてください。

アプローチの選び方

カートは shadow root 内でレンダリングされるため、テーマのスタイルシートはその内部に届きません。カスタムテンプレートのスタイルは、テーマからではなく、カート自身の Custom CSS パネルまたはインラインスタイルから当てる必要があります。Custom CSS を参照してください。

テンプレートが失敗したとき

壊れたテンプレートがカートを壊すことはありません。ブロックは何もレンダリングせず、その周りのすべては動作し続けます。安全ではありますが見落としやすく、ブロックがあるはずの場所の空白がその症状です。 ブロックは目に見えるエラーを出さずに静かに消えるため、公開前に必ずプレビューでテンプレートを確認してください。ブロックが消えている場合は、まずブラウザのコンソールを開きます。 そうでないと想定したテンプレートはどちらもクラッシュするため、次の 2 点には注意が必要です:
  • null になり得る props。 多くの props は通常の状況で null になります(ロゴがない場合の logoUrl、画像がない場合の imageUrl、単一バリアント商品の variantTitle など)。使う前に確認してください。
  • 空になり得る配列。 discountTagsdiscountCodes は、むしろ [] であることの方が多いです。

制限事項

  • カスタムテンプレートは表示の上書きです。 カートに対してロジックを実行する(イベントを購読する、アイテムを追加する、変更に反応する)には、カスタムスクリプトCart SDK を使ってください。
  • ほぼすべてのブロックがカスタムテンプレートをサポートしています。 例外は、Shopify 自身の決済ボタンをホストする Express payments ブロックと、Cart items コンテナ自体です。ただし、その中の Product 行はカスタムテンプレートをサポートしています。
  • テンプレートはブロックの本質的な動作を変えることはできません。 変わるのはブロックのデータの見せ方であって、その背後にあるデータや動作ではありません。

各ブロックの props

すべてのブロックはそれぞれ独自のデータを渡します。型と実例付きの完全な props の表は、各ブロックのページにあります: Custom code ブロックは、ブロックのレンダリングを置き換えるのではなくマークアップを追加する唯一の場所なので、props も異なります: カート全体と、カートへの追加アクションです。Custom code ブロック → Props を参照してください。