ECサイトでは、「この商品は特定のお客様にだけ販売したい」というケースがあります。会員限定商品や講座受講者向けの教材、取引先専用の卸商品など、誰でも自由に購入できてしまうと運営上のトラブルや意図しない販売につながりかねない商品です。
本記事では、Shopifyの商品ページにパスコード認証付きの購入ボタンを実装する方法を解説します。メタフィールドにパスコードを設定した商品だけ購入ボタンを非表示にし、認証フォームを表示して正しいパスコードを入力したお客様だけが購入に進める仕組みを、コピペで使えるコード付きで紹介します。アプリ不要・テーマカスタマイズのみで実現でき、案内文はすべて管理画面から編集できる設計です。
本記事の内容
Shopify商品ページにパスコード認証を実装する方法
1.実装する機能の完成イメージと仕組み
2.パスコード認証の実装手順6つ
3.実装時の注意点3つ
実装する機能の完成イメージと仕組み
機能の仕様
・商品メタフィールド「パスコード」が空欄の商品 → 通常どおり購入ボタンを表示
・パスコードが設定された商品 → 購入ボタンを非表示にし、パスコード入力フォームを表示
・ボックス内のフォームに正しいパスコードを入力 → ボックスが消えて購入ボタンが表示される
・タイトル・案内文などは、すべてテーマエディタから編集可能
ポイントは、パスコードを商品ごとのメタフィールドに持たせていることです。購入制限が必要な商品にだけパスコードを入力しておけば、それ以外の商品は今までどおり販売できます。購入を許可したお客様には店舗側からパスコードを伝え、そのお客様だけが購入に進める、という運用になります。
パスコード認証の実装手順6つ
ここからは実装手順です。今回は購入ボタンを出力しているスニペット(Dawn系テーマでは buy-buttons.liquid)をカスタマイズしていきます。テーマによってファイル名は異なりますが、考え方は同じです。作業前に必ずテーマを複製してバックアップを取っておきましょう。
手順1:商品メタフィールド「パスコード」を作成
まず、パスコードを保存する場所を作ります。
管理画面の「設定」→「カスタムデータ」→「商品」→「定義を追加」から、次の内容でメタフィールドを作成します。
・名前:パスコード
・ネームスペースとキー:custom.passcode
・タイプ:1行のテキスト
作成すると、各商品の編集ページ下部にある「メタフィールド」欄にパスコードの入力欄が表示されるようになります。ここが空欄なら通常販売、入力されていればパスコード認証あり、という切り替えスイッチになります。
手順2:購入ボタンブロックに管理画面用の設定項目を追加
次に、案内文などをテーマエディタから編集できるようにします。sections/main-product.liquid の schema 内にある buy_buttons ブロックの settings 配列に、以下を追加します。
{
"type": "header",
"content": "パスコード"
},
{
"type": "text",
"id": "passcode_title",
"default": "パスコード",
"label": "パスコードタイトル"
},
{
"type": "textarea",
"id": "passcode_text",
"default": "お伝えしたパスコードを入力して、購入にお進みください。",
"label": "パスコード案内文"
},
{
"type": "text",
"id": "passcode_placeholder",
"default": "パスコード",
"label": "パスコード入力欄の文字"
},
{
"type": "text",
"id": "passcode_submit_text",
"default": "送信",
"label": "送信ボタンテキスト"
},
{
"type": "text",
"id": "passcode_error_text",
"default": "パスコードが違います。もう一度入力してください",
"label": "エラーテキスト"
}
これで、テーマエディタの商品ページで購入ボタンのブロックを選択すると、「パスコード」という設定グループが表示されるようになります。文言の修正にコード編集が不要になるので、運用がぐっと楽になります。
手順3:buy-buttons.liquidにパスコードボックスを実装
snippets/buy-buttons.liquid を開き、購入フォームの直前に以下のコードを貼り付けます。メタフィールドにパスコードが設定されている場合だけ、パスコードボックスを出力する内容です。
{%- liquid
assign gate_passcode = product.metafields.custom.passcode.value | strip
-%}
{%- if gate_passcode != blank -%}
<passcode-gate class="passcode-gate" data-passcode="{{ gate_passcode | escape }}">
<div class="passcode-gate__title">{{ block.settings.counseling_title }}</div>
<p class="passcode-gate__text">{{ block.settings.counseling_text | newline_to_br }}</p>
<a class="passcode-gate__reservation-btn" href="{{ block.settings.reservation_link | default: '#' }}">
{{ block.settings.reservation_button_text }}
</a>
<div class="passcode-gate__title passcode-gate__title--passcode">{{ block.settings.passcode_title }}</div>
<p class="passcode-gate__text">{{ block.settings.passcode_text | newline_to_br }}</p>
<p class="passcode-gate__error" hidden>{{ block.settings.passcode_error_text }}</p>
<form class="passcode-gate__form">
<input
type="text"
class="passcode-gate__input"
placeholder="{{ block.settings.passcode_placeholder }}"
autocomplete="off"
autocapitalize="characters"
autocorrect="off"
spellcheck="false"
>
<button type="submit" class="passcode-gate__submit">{{ block.settings.passcode_submit_text }}</button>
</form>
</passcode-gate>
{%- endif -%}
続いて、同じファイル内にある購入フォームのラッパー(Dawn系なら class="product-form" の div)に、パスコード設定時だけ非表示用のクラスが付くようにします。
<div
class="product-form{% if gate_passcode != blank %} passcode-hidden{% endif %}"
>
✔︎ポイント:数量選択・カートに追加ボタン・動的チェックアウトボタンを含むフォーム全体を丸ごと隠すのがコツです。ボタン単体を隠すだけだと、動的チェックアウトから購入できてしまいます。
手順4:JavaScriptでパスコード判定を実装
次に、フォーム送信時にパスコードを照合する処理です。手順3で貼り付けたコードの下に、そのまま追加してください。カスタム要素(passcode-gate)として定義しているので、テーマの他のJSと干渉しません。
<script>
if (!customElements.get('passcode-gate')) {
customElements.define(
'passcode-gate',
class PasscodeGate extends HTMLElement {
normalizeInput() {
const normalized = this.input.value
.replace(/[!-~]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 0xFEE0))
.replace(/[^\x21-\x7E]/g, '')
.toUpperCase();
if (this.input.value !== normalized) {
this.input.value = normalized;
}
}
connectedCallback() {
this.form = this.querySelector('.passcode-gate__form');
this.input = this.querySelector('.passcode-gate__input');
this.error = this.querySelector('.passcode-gate__error');
this.composing = false;
this.input.addEventListener('compositionstart', () => {
this.composing = true;
});
this.input.addEventListener('compositionend', () => {
this.composing = false;
this.normalizeInput();
});
this.input.addEventListener('input', () => {
if (this.composing) return;
this.normalizeInput();
});
this.form.addEventListener('submit', (event) => {
event.preventDefault();
const entered = this.input.value.trim().toUpperCase();
const passcode = (this.dataset.passcode || '').trim().toUpperCase();
if (entered !== '' && entered === passcode) {
this.error.hidden = true;
this.hidden = true;
const productForm = this.parentElement.querySelector('.product-form.passcode-hidden');
if (productForm) productForm.classList.remove('passcode-hidden');
} else {
this.error.hidden = false;
}
});
}
}
);
}
</script>
処理の流れはシンプルで、送信ボタンが押されたら入力値とメタフィールドの値を比較し、一致すればボックスを隠して購入フォームを表示、不一致ならエラーメッセージを表示します。normalizeInput では全角文字の半角変換と大文字化を行っています(詳しくは注意点の章で解説します)。
手順5:CSSでパスコードボックスをデザイン
最後に見た目を整えます。テーマのカスタムCSSファイル(なければ assets に custom.css を作成して theme.liquid で読み込み)に以下を追加します。色やサイズはお好みで調整してください。
/* パスコード認証 */
.passcode-hidden {
display: none !important;
}
.passcode-gate {
display: block;
background-color: #f3f3ee;
border-radius: 5px;
padding: 24px 40px 49px;
}
.passcode-gate[hidden] {
display: none !important;
}
.passcode-gate__title {
font-weight: 500;
font-size: 20px;
line-height: 55px;
letter-spacing: 0.05em;
color: #596783;
}
.passcode-gate__title--passcode {
margin-top: 16px;
}
.passcode-gate__text {
font-size: 13px;
line-height: 22px;
color: #495775;
margin: 0;
}
.passcode-gate__error {
margin: 12px 0 0;
font-weight: 700;
font-size: 13px;
color: #ff0000;
text-align: center;
}
.passcode-gate__form {
display: flex;
width: 100%;
margin-top: 12px;
}
.passcode-gate__input {
flex: 1 1 auto;
min-width: 0;
height: 50px;
padding: 0 16px;
background-color: #ffffff;
border: 1px solid #d9d9d9;
border-right: none;
border-radius: 5px 0 0 5px;
font-size: 16px;
}
.passcode-gate__submit {
flex: 0 0 auto;
height: 50px;
padding: 0 24px;
background-color: #596783;
border: none;
border-radius: 0 5px 5px 0;
font-weight: 500;
font-size: 16px;
color: #ffffff;
cursor: pointer;
}
✔︎ポイント:.passcode-gate[hidden] のスタイルを忘れずに入れてください。.passcode-gate に display: block を指定しているため、これがないとJS側で hidden 属性を付けてもボックスが消えません。実装時にハマりやすいポイントです。
手順6:商品にパスコードを設定して動作確認
実装は以上です。テスト用の商品を開き、メタフィールド「パスコード」に任意の値(例:ABC123)を入力して保存し、次の4点を確認しましょう。
1.パスコード設定済み商品でパスコードボックスが表示され、購入ボタンが消えている
2.間違ったパスコードでエラーメッセージが表示される
3.正しいパスコードでボックスが消え、購入ボタンが表示される
4.パスコード未設定の商品は今までどおり購入ボタンが表示されている
すべて確認できればオッケーです。
実装時の注意点3つ
注意点1:スマホの全角入力(IME)対策は必須
実はこの実装でいちばんつまずきやすいのがここです。iPhoneの日本語キーボードで入力すると、文字が「変換中(未確定)」の状態を経由します。このタイミングでJSが入力欄の値を書き換えると、変換中の文字が強制確定されて同じ文字が連続入力されるバグが起きます。
手順4のコードでは compositionstart / compositionend イベントで変換中かどうかを判定し、変換確定後にまとめて「全角→半角変換+大文字化」する作りにしています。全角で「abc123」と入力されても自動で「ABC123」に整形されるので、お客様側の入力ミスによる問い合わせも減らせます。
注意点2:パスコードはページのソースに含まれる
この仕組みはフロントエンド(ブラウザ側)でパスコードを照合しているため、ページのソースコードを見ればパスコードの値を確認できてしまいます。会員限定販売のような厳密なアクセス制御ではなく、あくまで「パスコードを知っているお客様への案内・導線」としての機能と考えてください。より厳密に制限したい場合は、顧客タグを使ったB2B機能や専用アプリの利用を検討しましょう。
注意点3:クイックビューなど他の購入経路に注意
テーマによっては、商品ページ以外にもカートに追加できる導線があります。コレクションページのクイックビュー、画面下部に追従するカート追加バー、おすすめ商品のカードなどです。buy-buttons.liquid のような共通スニペットに実装しておけばクイックビューにも同じ制御が効きますが、テーマ独自の購入導線がないか、実装後にひととおり確認しておくと安心です。
まとめ
今回は、Shopifyの商品ページにパスコード認証付きの購入ボタンを実装する方法を紹介しました。メタフィールドを切り替えスイッチにすることで、アプリなしでも「特定の商品だけ購入を制限する」運用が実現できます。購入制限商品を扱うECのほか、招待制商品や卸先限定商品などにも応用できる仕組みなので、ぜひ試してみてください。
この記事を書いた人
![]() |
濱野 恵太郎(はまの けいたろう) ・Shopifyパートナー ・ECサイト構築40サイト以上 構築から運用・保守まで一気通貫で対応しています。 |
Shopifyのカスタマイズは弊社にお任せください
弊社は、Shopify構築40社以上・運用保守20サイト以上の実績を持つShopify専門の制作会社です。今回のようなテーマカスタマイズは、月額49,500円の運用保守サービス(月5時間の改修込み・契約縛りなし)の範囲内で対応できます。「自社のテーマだとうまく動かない」「もっと複雑な販売制限がしたい」という方も、お気軽にご相談ください。
