📄 ページテンプレート中級
ギフトカード受け取りページ
ギフトカード受け取り時の専用ページテンプレート。カード額面、残高、QR コード、カードコードをコピー可能な形式で表示し、ギフトカード購入者が受け取ったカード情報を確認・管理できる。
用途
顧客がメール内のリンクをクリックしてギフトカードを受け取るとき。カード額面と残高を確認し、カードコードをコピーして保存する。
設置場所
templates/gift_card.liquid に設置。Shopify がギフトカード受け取りメール内の URL から自動的にこのテンプレートを読み込む。theme.liquid の代わりに `{% layout none %}` で独立した HTML を出力する。
注意点
Storefront API ではギフトカード情報が取得できないため、このテンプレートは admin API データをベースに Liquid で直接レンダリングされる仕様。QR コード生成に Shopify 提供の vendor/qrcode.js を使うため、asset URL が正しく解決されていることを確認する。settings.currency_code_enabled が有効な場合は通貨コード付き金額(例: ¥10,000 JPY)、無効な場合は通貨記号のみ(例: ¥10,000)で表示される。expired や enabled == false 判定でカード失効時の「Expired」バッジを出すため、ギフトカード有効期限の設定がなければバッジは表示されない。
コード
204 行 / liquid{% comment %} Unfortunataly gift cards are not supported yet via the Storefront API {% endcomment %}
{% comment %} Based on: https://github.com/Shopify/dawn/blob/v7.0.1/templates/gift_card.liquid {% endcomment %}
{% layout none %}
<!doctype html>
<html lang="{{ request.locale.iso_code }}">
<head>
<script src="{{ 'vendor/qrcode.js' | shopify_asset_url }}" defer></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="{{ settings.color_background }}">
<link rel="canonical" href="{{ canonical_url }}">
<link rel="preconnect" href="https://cdn.shopify.com" crossorigin>
{%- if settings.favicon != blank -%}
<link rel="icon" type="image/png" href="{{ settings.favicon | image_url: width: 32, height: 32 }}">
{%- endif -%}
{%- unless settings.type_header_font.system? -%}
<link rel="preconnect" href="https://fonts.shopifycdn.com" crossorigin>
{%- endunless -%}
{%- assign formatted_initial_value = gift_card.initial_value | money_without_trailing_zeros | strip_html -%}
<title>{{ "Here's your {{ value }} gift card for {{ shop }}!" | t: value: formatted_initial_value, shop: shop.name }}</title>
<meta name="description" content="Your gift card">
{{ content_for_header }}
{%- liquid
assign body_font_bold = settings.type_body_font | font_modify: 'weight', 'bold'
assign body_font_italic = settings.type_body_font | font_modify: 'style', 'italic'
assign body_font_bold_italic = body_font_bold | font_modify: 'style', 'italic'
%}
{% style %}
{{ settings.type_body_font | font_face: font_display: 'swap' }}
{{ body_font_bold | font_face: font_display: 'swap' }}
{{ body_font_italic | font_face: font_display: 'swap' }}
{{ body_font_bold_italic | font_face: font_display: 'swap' }}
{{ settings.type_header_font | font_face: font_display: 'swap' }}
:root {
--font-body-family: {{ settings.type_body_font.family }}, {{ settings.type_body_font.fallback_families }};
--font-body-style: {{ settings.type_body_font.style }};
--font-body-weight: {{ settings.type_body_font.weight }};
--font-heading-family: {{ settings.type_header_font.family }}, {{ settings.type_header_font.fallback_families }};
--font-heading-style: {{ settings.type_header_font.style }};
--font-heading-weight: {{ settings.type_header_font.weight }};
--font-body-scale: {{ settings.body_scale | divided_by: 100.0 }};
--font-heading-scale: {{ settings.heading_scale | times: 1.0 | divided_by: settings.body_scale }};
--color-base-text: {{ settings.colors_text.red }}, {{ settings.colors_text.green }}, {{ settings.colors_text.blue }};
--color-shadow: {{ settings.colors_text.red }}, {{ settings.colors_text.green }}, {{ settings.colors_text.blue }};
--color-base-background-1: {{ settings.colors_background_1.red }}, {{ settings.colors_background_1.green }}, {{ settings.colors_background_1.blue }};
--color-base-background-2: {{ settings.colors_background_2.red }}, {{ settings.colors_background_2.green }}, {{ settings.colors_background_2.blue }};
--color-base-solid-button-labels: {{ settings.colors_solid_button_labels.red }}, {{ settings.colors_solid_button_labels.green }}, {{ settings.colors_solid_button_labels.blue }};
--color-base-outline-button-labels: {{ settings.colors_outline_button_labels.red }}, {{ settings.colors_outline_button_labels.green }}, {{ settings.colors_outline_button_labels.blue }};
--color-base-accent-1: {{ settings.colors_accent_1.red }}, {{ settings.colors_accent_1.green }}, {{ settings.colors_accent_1.blue }};
--color-base-accent-2: {{ settings.colors_accent_2.red }}, {{ settings.colors_accent_2.green }}, {{ settings.colors_accent_2.blue }};
--gradient-base-background-1: {% if settings.gradient_background_1 != blank %}{{ settings.gradient_background_1 }}{% else %}{{ settings.colors_background_1 }}{% endif %};
--page-width: {{ settings.page_width | divided_by: 10 }}rem;
--page-width-margin: {% if settings.page_width == '1600' %}2{% else %}0{% endif %}rem;
--buttons-radius: {{ settings.buttons_radius }}px;
--buttons-border-width: {% if settings.buttons_border_opacity > 0 %}{{ settings.buttons_border_thickness }}{% else %}0{% endif %}px;
--buttons-border-opacity: {{ settings.buttons_border_opacity | divided_by: 100.0 }};
--buttons-shadow-opacity: {{ settings.buttons_shadow_opacity | divided_by: 100.0 }};
--buttons-shadow-horizontal-offset: {{ settings.buttons_shadow_horizontal_offset }}px;
--buttons-shadow-vertical-offset: {{ settings.buttons_shadow_vertical_offset }}px;
--buttons-shadow-blur-radius: {{ settings.buttons_shadow_blur }}px;
--buttons-border-offset: {% if settings.buttons_radius > 0 or settings.buttons_shadow_opacity > 0 %}0.3{% else %}0{% endif %}px;
--inputs-radius: {{ settings.inputs_radius }}px;
--inputs-border-width: {{ settings.inputs_border_thickness }}px;
--inputs-border-opacity: {{ settings.inputs_border_opacity | divided_by: 100.0 }};
--inputs-shadow-opacity: {{ settings.inputs_shadow_opacity | divided_by: 100.0 }};
--inputs-shadow-horizontal-offset: {{ settings.inputs_shadow_horizontal_offset }}px;
--inputs-shadow-vertical-offset: {{ settings.inputs_shadow_vertical_offset }}px;
--inputs-shadow-blur-radius: {{ settings.inputs_shadow_blur }}px;
}
{% endstyle %}
{%- unless settings.type_body_font.system? -%}
<link rel="preload" as="font" href="{{ settings.type_body_font | font_url }}" type="font/woff2" crossorigin>
{%- endunless -%}
{%- unless settings.type_header_font.system? -%}
<link rel="preload" as="font" href="{{ settings.type_header_font | font_url }}" type="font/woff2" crossorigin>
{%- endunless -%}
{{ 'template-giftcard.css' | asset_url | stylesheet_tag }}
</head>
<body class="gradient">
<header class="gift-card__title">
<span class="h2">{{ shop.name }}</span>
<h1 class="gift-card__heading">Your gift card</h1>
<div class="gift-card__price">
<p>
{% if settings.currency_code_enabled %}
{{ gift_card.initial_value | money_with_currency }}
{% else %}
{{ gift_card.initial_value | money }}
{% endif %}
</p>
{%- if gift_card.enabled == false or gift_card.expired -%}
<p class="gift-card__label badge badge--background-1">Expired</p>
{%- endif -%}
</div>
{% if settings.currency_code_enabled %}
{%- assign gift_card_balance = gift_card.balance | money_with_currency -%}
{% else %}
{%- assign gift_card_balance = gift_card.balance | money -%}
{% endif %}
{%- if gift_card.balance != gift_card.initial_value -%}
<p class="gift-card__label caption-large">{{ "Remaining {{ balance }}" | t: balance: gift_card_balance }}</p>
{%- endif -%}
</header>
<main class="gift-card">
<div class="gift-card__image-wrapper">
<img src="{{ 'gift-card/card.svg' | shopify_asset_url }}" alt="" class="gift-card__image" height="{{ 570 | divided_by: 1.5 }}" width="570" loading="lazy">
</div>
<div class="gift-card__qr-code" data-identifier="{{ gift_card.qr_identifier }}"></div>
<div class="gift-card__information">
<input
type="text"
class="gift-card__number"
value="{{ gift_card.code | format_code }}"
aria-label="Gift card code"
readonly
>
<div class="gift-card__copy-code">
<button class="link gift-card__copy-link">Copy code</button>
<span class="gift-card__copy-success form__message" role="status"></span>
<template>
{%- render 'icon-success' -%}Code copied successfully
</template>
</div>
{%- if gift_card.pass_url -%}
<a href="{{ gift_card.pass_url }}" class="gift_card__apple-wallet">
<img src="{{ 'gift-card/add-to-apple-wallet.svg' | shopify_asset_url }}" width="120" height="40" alt="{{ 'gift_cards.issued.add_to_apple_wallet' | t }}" loading="lazy">
</a>
{%- endif -%}
<div class="gift-card__buttons no-print">
<a
href="{{ shop.url }}"
class="button"
target="_blank"
rel="noopener"
aria-describedby="a11y-new-window-message"
>
Continue shopping
</a>
<button
class="button button--secondary"
onclick="window.print();"
>
Print
</button>
</div>
</div>
</main>
<div hidden>
<span id="a11y-new-window-message">Opens in a new window.</span>
</div>
</body>
</html>
<script>
var string = { qrImageAlt: "QR code — scan to redeem gift card" };
document.addEventListener('DOMContentLoaded', function() {
new QRCode( document.querySelector('.gift-card__qr-code'), {
text: document.querySelector('.gift-card__qr-code').dataset.identifier,
width: 120,
height: 120,
imageAltText: string.qrImageAlt
});
});
var template = document.getElementsByTagName("template")[0];
var clonedTemplate = template.content.cloneNode(true);
var isMessageDisplayed = false
document
.querySelector('.gift-card__copy-link')
.addEventListener('click', () => {
navigator.clipboard.writeText(document.querySelector('.gift-card__number').value).then(function () {
if (!isMessageDisplayed) {
document.querySelector('.gift-card__copy-success').appendChild(clonedTemplate);
isMessageDisplayed = true
}
});
});
</script>
出典・ライセンス
- License:
- MIT
このコードは instantcommerce 著作の MIT ライセンスソースです。 原本の著作権は instantcommerce が保有します。日本語訳は ALSEL によるものです。
関連項目
📄 ページテンプレート初級
ページテンプレート
Shopify の汎用ページテンプレート。ページのタイトルと本文コンテンツを Shopify 管理画面から取得して表示する基本的な構造。
📁 liquid·MIT·5 行
📄 ページテンプレート初級
リダイレクト
ヘッドレステーマで Shopify ストアフロントへのリダイレクト機能を提供するセクション。管理画面に「リダイレクト」という名称で登場し、ページから別 URL への誘導を実装する基盤となる。
📁 shopify-headless-theme·MIT·7 行
📄 ページテンプレート初級
トップページの基本テンプレート
Shopify Liquid の最小限のテンプレート例。HTML に日付変数を埋め込み、商品ページへのリンクを配置する基本構造を示す。
📁 liquid·MIT·7 行
📄 ページテンプレート初級
固定ページのテンプレート
Shopify 管理画面で作成した固定ページ(利用規約、プライバシーポリシーなど)を表示するテンプレート。ページタイトルと本文コンテンツを描画する。
📁 mcliquid-theme·MIT·8 行
📄 ページテンプレート初級
ページの基本テンプレート
固定ページ(About など)の基本レイアウト。ページタイトルとコンテンツを HTML の article 要素でマークアップし、管理画面で編集したテキストを表示する。
📁 liquid·MIT·9 行
📄 ページテンプレート初級
固定ページのテンプレート
固定ページ(ポリシー、会社概要、利用規約など)の基本レイアウト。ページタイトルと本文を中央揃えで表示する。
📁 ks-bootshop·MIT·10 行