Skip to content

Gift card support guide

Diagnostic and troubleshooting reference for the gift-card landing page — JSON+sections migration, locale-aware date, QR code Custom Element, clipboard copy, Apple Wallet integration, Google Wallet pass setup, recipient form explanation, and the 3 distinct visual states (Active / Expired / Depleted). For merchant setup and configuration, see Gift card guide.


FAQ

Q1: Gift-card expiry date shows in English on a French / Arabic / Japanese store

This was a known English-leakage defect (D-43) in the pre-06.9 theme. The gift-card date used:

liquid
{{ gift_card.expires_on | date: '%B %e, %Y' }}

This always outputs English month names regardless of locale.

Fixed in Phase 06.9 via time_tag filter:

liquid
{{ gift_card.expires_on | time_tag: format: 'date' }}

time_tag outputs a locale-aware <time> element that Shopify renders with the store's active locale.

To verify the fix is in place:

bash
curl -s https://your-store.myshopify.com/gift_cards/{code} | grep 'expires_on\|time>'
# Expected: <time datetime="...">29 avril 2027</time> (on a French store)

If you are still seeing English dates after upgrading to Uisce 06.9, confirm the theme was pushed to the live store:

bash
scripts/push-presets.sh

Q2: QR code doesn't render — blank or broken image

The QR code is generated by the <gift-card-qr> Custom Element using vendor/qrcode.js. Three possible causes:

  1. vendor/qrcode.js failed to load. DevTools → Network → filter qrcode — should return HTTP 200. If 404, the asset is missing from the theme push.
  2. <gift-card-qr> Custom Element failed to upgrade. Run the console snippet below → inspect gift_card.qr. If false, the <canvas> was not rendered — the Custom Element may have failed to initialize.
  3. Canvas API blocked. Some browser extensions (privacy shields, canvas fingerprint protection) block canvas.getContext('2d'). Test in an incognito window or a different browser.

Diagnostic steps:

  1. Run the console snippet → gift_card.qr — should be true if the canvas rendered
  2. DevTools → Console → check for any error from gift-card.js
  3. DevTools → Elements → find <gift-card-qr> — should have a <canvas> child element

Expected QR code size: 150×150 px at screen resolution; scales up to 300×300 px for print via @media print.

Q3: Copy code button doesn't work

The <gift-card-copy> Custom Element uses the Clipboard API (navigator.clipboard.writeText()). Two requirements:

  1. HTTPS context. The Clipboard API requires a secure origin. Dev stores use HTTPS — this should not be an issue on Shopify-hosted storefronts.
  2. Browser support. navigator.clipboard is available in all modern browsers (Chrome 66+, Firefox 63+, Safari 13.1+). Edge 79+.

If the copy button still doesn't work:

  1. Run the console snippet → gift_card.copy — should be true if <gift-card-copy> element is present
  2. DevTools → Console → look for DOMException: NotAllowedError — this means clipboard permission was denied. In Chrome, check the lock icon in the address bar → Permissions → Clipboard.
  3. If navigator.clipboard is undefined: the browser is extremely outdated or the page is serving over HTTP (not HTTPS). Shopify storefronts are always HTTPS.

Fallback behavior: The gift-card code is also rendered in plain text in a <code> element. Visitors can manually select and copy the code if the button fails.

Q4: Apple Wallet button is missing

The Apple Wallet button only appears when gift_card.pass_url is non-nil. This is populated by Shopify when the Apple Gift Card Passbook integration is active.

To check:

  1. Run the console snippet → gift_card.apple_wallet — will be true if the button is present
  2. If false: the Apple integration is not enabled in your Shopify admin

To enable:

  1. Shopify admin → Settings → Payments → Gift cards
  2. Enable Apple Wallet passes
  3. Complete the Apple developer certificate setup (requires an Apple developer account for pass signing)
  4. After setup, new gift cards will have pass_url populated automatically

Note: The Apple Wallet button cannot be faked or added manually — it requires Shopify to generate a valid Apple Wallet pass URL for each gift card. Existing gift cards issued before enabling the integration may not have pass_url until re-issued.

Q5: Google Wallet button is missing

The Google Wallet button appears when section.settings.google_wallet_url_template is non-empty in the theme editor.

To configure:

  1. Install a Google Wallet pass provider app (Walletly, PassKit, etc.)
  2. Obtain the URL template from the app
  3. Theme editor → Sections → Main gift card → Google Wallet URL template
  4. Paste the URL template with &#123;&#123;code&#125;&#125; and &#123;&#123;balance&#125;&#125; placeholders
  5. Save

Verify the button is rendering:

Run the console snippet → gift_card.google_wallet — should be true if the <a class="gift-card-page__google-wallet"> element is present.

Q6: Recipient name field is missing from the gift-card landing page

This is intentional behavior (D-40 decision). The recipient is set at purchase time on the cart line-item properties — NOT on the gift-card landing page.

When a customer purchases a gift card product that has recipient properties configured:

  • properties[Recipient name] — filled at checkout
  • properties[Recipient email] — Shopify sends the gift card link to this address
  • properties[Gift card message] — optional personal message

The gift-card landing page (/gift_cards/{code}) is a redemption artifact — the recipient has already been set. Adding a recipient form on the landing page would allow anyone with the URL to change the recipient, which is a security issue.

If you want to add a recipient form: Use a Shopify gift-card recipient properties app that adds the form to the product page at purchase time, not to the landing page.


Console diagnostic snippet

Paste into Chrome DevTools console (F12 → Console tab) on any page of the live store. Reports gift-card state when on a gift-card page; also reports footer state on every page.

js
(function () {
  var path = location.pathname;
  var report = { path: path, surfaces: {} };
  // Footer always
  var footer = document.querySelector('.footer');
  report.surfaces.footer = {
    present: !!footer,
    policies: !!document.querySelector('.footer__policies'),
    localization: !!document.querySelector('.footer__localization'),
    newsletter: !!document.querySelector('.footer__newsletter-block customer-form'),
    payment_icons_aria: Array.from(document.querySelectorAll('.footer__payment span[aria-label]')).length,
  };
  // 404
  if (document.querySelector('.section-404')) {
    report.surfaces['404'] = {
      hero: !!document.querySelector('.section-404__hero svg'),
      search: !!document.querySelector('.section-404__search'),
      recently_viewed: !!document.querySelector('recently-viewed'),
      noindex: document.querySelector('meta[name="robots"]')
        ? document.querySelector('meta[name="robots"]').content
        : null,
    };
  }
  // Password
  if (document.querySelector('.password-page')) {
    report.surfaces.password = {
      logo: !!document.querySelector('.password-page__logo img'),
      hero: !!document.querySelector('.password-page__hero svg'),
      countdown: !!document.querySelector('count-down'),
      newsletter: !!document.querySelector('.password-page__newsletter customer-form'),
      social: !!document.querySelector('.password-page__social'),
      localization: !!document.querySelector('.password-page__localization'),
    };
  }
  // Gift-card
  if (document.querySelector('.gift-card-page')) {
    report.surfaces.gift_card = {
      qr: !!document.querySelector('gift-card-qr canvas'),
      copy: !!document.querySelector('gift-card-copy'),
      balance: document.querySelector('.gift-card-page__balance')
        ? document.querySelector('.gift-card-page__balance').textContent.trim()
        : null,
      state:
        ['active', 'expired', 'depleted'].filter(function (s) {
          return !!document.querySelector('.gift-card-page--state-' + s);
        })[0] || 'active',
      apple_wallet: !!document.querySelector('.gift-card-page__apple-wallet'),
      google_wallet: !!document.querySelector('.gift-card-page__google-wallet'),
    };
  }
  console.table(report.surfaces);
  return report;
})();

What to look for on a gift-card page:

  • gift_card.qr === true — QR code <canvas> rendered successfully
  • gift_card.copy === true<gift-card-copy> element is present
  • gift_card.balance — current balance text (e.g., "$25.00")
  • gift_card.state — one of active, expired, depleted
  • gift_card.apple_wallet === true — Apple Wallet button present (requires Shopify integration)
  • gift_card.google_wallet === true — Google Wallet button present (requires google_wallet_url_template setting)

Curl cheat-sheet (D-67)

bash
curl -L -s -o /dev/null -w "%{http_code}" https://your-store.myshopify.com/policies/privacy-policy
# Expected: 200

Topic 2 — 404 status code (for reference)

bash
curl -I https://your-store.myshopify.com/not-a-real-path-12345
# Expected: HTTP/2 404

Topic 3 — Password form action (for reference)

bash
curl -I https://your-store.myshopify.com/password
# Expected: HTTP/2 200

Topic 4 — Gift-card noindex,nofollow header

Verify the gift-card landing page emits the correct noindex,nofollow signal:

bash
curl -I https://your-store.myshopify.com/gift_cards/{your-gift-card-code}
# Expected headers:
#   x-robots-tag: noindex, nofollow   (Shopify platform header)
# AND in page source:
#   <meta name="robots" content="noindex,nofollow">  (Uisce theme layout/gift-card.liquid)

This defense-in-depth approach prevents gift-card redemption URLs from being indexed by search engines.

Topic 5 — Apple Wallet pass URL availability

bash
# Inspect page source for the pass URL
curl -s -b cookies.txt https://your-store.myshopify.com/gift_cards/{code} | grep 'apple-wallet'
# Expected: <a href="https://..." class="gift-card-page__apple-wallet">

# Verify the pass URL responds
curl -I {apple_pass_url_from_page_source}
# Expected: HTTP/2 200

Topic 6 — Google Wallet template substitution

Verify the &#123;&#123;code&#125;&#125; and &#123;&#123;balance&#125;&#125; placeholders were substituted correctly:

bash
curl -s -b cookies.txt https://your-store.myshopify.com/gift_cards/{code} | grep 'google-wallet'
# Expected: <a href="https://pay.google.com/...?code=XXXX-XXXX-XXXX-XXXX&amp;amount=50.0" ...>

If &#123;&#123;code&#125;&#125; or &#123;&#123;balance&#125;&#125; appear literally in the href, the URL template substitution failed — check the google_wallet_url_template setting uses &#123;&#123;code&#125;&#125; and &#123;&#123;balance&#125;&#125; as placeholders exactly.

Topic 7 — Cache-control for gift-card assets

bash
curl -I https://your-store.myshopify.com/cdn/shop/t/1/assets/gift-card.css
# Expected: cache-control: public, max-age=31536000 (Shopify CDN strong cache)

curl -I https://your-store.myshopify.com/cdn/shop/t/1/assets/gift-card.js
# Expected: cache-control: public, max-age=31536000

After pushing theme changes, the CDN URL includes a new version parameter — cache busts automatically. No manual cache invalidation required.

Built for the Shopify Theme Store.