less than a minute read • Updated
Create a Gift Card Purchase Form in Webstudio
This tutorial shows Webstudio users how to build a working Foxy gift card purchase form
Overview
This tutorial shows how to build a minimal and an advanced add-to-cart form that sells digital gift cards.
Demo
Create a Gift Card in Foxy
In Foxy, “gift cards” are configured in the Foxy admin and issued as gift card codes that maintain a balance. A gift card code is what a customer redeems at checkout, and it can be reused until its balance reaches zero.
Operationally, selling a gift card is just selling a product that is associated with a specific item category and gift card provisioning rules. Item categories can be configured to send a “gift recipient” email using a dedicated gift recipient email template setting.
Before going further review our gift card docs here.
Once you have created your gift card, setup your gift card email, and saved your gift card SKU you can continue.
The simplest Webstudio Gift Card form
A minimal Webhook form that only asks for:
Recipient email (where the gift card email will be delivered)
Amount (a free number input)
Follow these steps:
Advanced dynamic Gift Card form
This advanced gift card purchase form creates a Foxy add-to-cart experience on a Webstudio site using a Webhook form that posts directly to your Foxy cart. Customers can choose whether the gift card is for themselves or “Someone Else.” If they choose “Someone Else,” the form reveals additional fields for the recipient’s name, the sender’s name, and an optional message.
The customer then selects a preset amount or chooses “Custom” to enter a different amount. The included script automatically sets the item price and updates the Foxy product code to gift_card_<SKU> (based on the selected amount), ensuring the correct gift card SKU is added to the cart. The recipient email address is always required so Foxy can deliver the gift card by email.
You can copy and paste this code inside the Webstudio page:
<form
foxy-form
action="https://YOUR-STOREDOMAIN.foxycart.com/cart"
method="post"
class="gift-card-form"
>
<!-- Required hidden fields -->
<input type="hidden" name="name" value="Gift Card" />
<!-- IMPORTANT: code is the SKU identifier (gift_card_<SKU>). Script will overwrite based on amount. -->
<input type="hidden" name="code" value="gift_card_GC50" />
<!-- Include category only if your setup requires it -->
<input type="hidden" name="category" value="gift_card" />
<!-- Who is this for? -->
<div class="form-section">
<label for="who_is_this_for">Who is this for?</label>
<select id="who_is_this_for" name="who_is_this_for">
<!-- Text matters because script reads the visible option text -->
<option value="">Myself</option>
<option value="">Someone Else</option>
</select>
</div>
<!-- Recipient name (shown only when Someone Else) -->
<div class="form-section" style="display: none;">
<label for="shipto">Recipient's name</label>
<input
type="text"
id="shipto"
name="shipto"
placeholder="Who is receiving this gift?"
maxlength="256"
/>
</div>
<!-- Sender name (shown only when Someone Else) -->
<div class="form-section" style="display: none;">
<label for="from">Your name</label>
<input
type="text"
id="from"
name="from"
placeholder="Who is sending this gift?"
maxlength="256"
/>
</div>
<!-- Recipient email (always shown + required) -->
<div class="form-section">
<label for="gift_recipient_email">Recipient Email Address</label>
<input
type="email"
id="gift_recipient_email"
name="gift_recipient_email"
placeholder="Where do you want the digital voucher emailed to?"
required
maxlength="256"
/>
</div>
<!-- Message (optional; shown only when Someone Else) -->
<div class="form-section" style="display: none;">
<label for="gift_recipient_message">Message (optional)</label>
<textarea
id="gift_recipient_message"
name="gift_recipient_message"
maxlength="5000"
></textarea>
</div>
<!-- Amount selector -->
<div class="form-section">
<label for="price-select">Amount</label>
<!-- x:amount stores the chosen denomination as a line-item option -->
<select id="price-select" name="x:amount" required>
<option value="50">€50</option>
<option value="100">€100</option>
<option value="150">€150</option>
<option value="200">€200</option>
<option value="250">€250</option>
<option value="300">€300</option>
<option value="350">€350</option>
<option value="400">€400</option>
<option value="450">€450</option>
<option value="500">€500</option>
<option value="custom">Custom</option>
</select>
</div>
<!-- Custom amount (only shown when Amount = Custom) -->
<div id="price-custom" class="form-section" style="display: none;">
<label for="price-input">Custom Amount</label>
<!-- This MUST be name="price" so Foxy uses it as the line-item price -->
<input
type="number"
id="price-input"
name="price"
min="1"
step="1"
inputmode="decimal"
/>
</div>
<button type="submit">Add to cart</button>
</form>
<script>
const form =
document.querySelector('form[foxy-form]') || document.querySelector('form');
// --- Elements ---------------------------------------------------------
const whoIsThisFor = form.querySelector('#who_is_this_for');
const shipto = form.querySelector('#shipto');
const from = form.querySelector('#from');
const recipientEmail = form.querySelector('#gift_recipient_email');
const recipientMessage = form.querySelector('#gift_recipient_message');
const priceSelect = form.querySelector('#price-select');
const priceInput = form.querySelector('#price-input'); // name="price"
const priceCustomWrap = document.getElementById('price-custom');
const codeInput = form.querySelector('input[name="code"]');
// --- Map denomination -> SKU (recommended if SKU != amount) -----------
// IMPORTANT: `code` must be gift_card_<SKU> (SKU is the product code in Foxy)
// If your SKUs are literally "50", "100", etc., you can use { "50":"50", ... }.
const skuByAmount = {
'50': 'GC50',
'100': 'GC100',
'150': 'GC150',
'200': 'GC200',
'250': 'GC250',
'300': 'GC300',
'350': 'GC350',
'400': 'GC400',
'450': 'GC450',
'500': 'GC500',
};
// --- Helpers ----------------------------------------------------------
const setRequired = (el, required) => {
if (!el) return;
el.required = !!required;
if (required) el.setAttribute('required', '');
else el.removeAttribute('required');
};
const showSection = (el, show) => {
if (!el) return;
const section = el.closest('.form-section') || el.parentElement;
if (section) section.style.display = show ? 'block' : 'none';
if (!show) el.value = '';
};
const getWhoText = () => {
if (!whoIsThisFor) return '';
return (
whoIsThisFor.options?.[whoIsThisFor.selectedIndex]?.text?.trim() || ''
);
};
// --- Myself vs Someone Else ------------------------------------------
const updateRecipientFields = () => {
const whoText = getWhoText();
const isSomeoneElse = whoText.toLowerCase() === 'someone else';
showSection(shipto, isSomeoneElse);
setRequired(shipto, isSomeoneElse);
showSection(from, isSomeoneElse);
setRequired(from, isSomeoneElse);
showSection(recipientMessage, isSomeoneElse);
setRequired(recipientMessage, false);
// Always show + require recipient email
showSection(recipientEmail, true);
setRequired(recipientEmail, true);
};
// --- Amount + custom amount + code -----------------------------------
const updatePriceAndCode = () => {
if (!priceSelect) return;
const selected = priceSelect.value;
if (selected !== 'custom') {
if (priceCustomWrap) priceCustomWrap.style.display = 'none';
// Set the price to the selected denomination (still submits via name="price")
if (priceInput) priceInput.value = selected;
setRequired(priceInput, false);
// Set code = gift_card_<SKU>
const sku = skuByAmount[selected] || selected;
if (codeInput) codeInput.value = 'gift_card_' + sku;
} else {
if (priceCustomWrap) priceCustomWrap.style.display = 'block';
// Custom price must be entered by user
if (priceInput) priceInput.value = '';
setRequired(priceInput, true);
// If you have a single SKU for custom amounts, use it here:
// codeInput.value = 'gift_card_<YOUR_CUSTOM_SKU>';
if (codeInput) codeInput.value = 'gift_card_custom';
}
};
// --- Init -------------------------------------------------------------
updateRecipientFields();
updatePriceAndCode();
// --- Listeners --------------------------------------------------------
if (whoIsThisFor)
whoIsThisFor.addEventListener('change', updateRecipientFields);
if (priceSelect) priceSelect.addEventListener('change', updatePriceAndCode);
</script>
Notes: what you must adapt/change