JavaScript API
The GiftPrint storefront widget exposes a JavaScript API on window.GiftPrintWidget for developers who want to build custom UIs, pre-fill messages from external sources, or integrate gift notes with custom checkout flows.
For the complete method reference, see JavaScript API reference.
When the API is available
The widget tries to initialize immediately, again on DOMContentLoaded, and then polls every 300 ms up to 10 times — so within ~3 seconds of the page rendering it is either mounted or absent (block not added / disabled by merchant). There is no giftprint:ready event. Listen for giftprint:change (dispatched on every user-driven state change — toggle, template, message, recipient, sender) or poll for window.GiftPrintWidget:
// Option 1: React to state changes (fires on init and on every change)
document.addEventListener('giftprint:change', (e) => {
console.log('Widget state changed:', e.detail);
});
// Option 2: Poll for availability (with timeout)
let attempts = 0;
const checkWidget = () => {
if (window.GiftPrintWidget) {
window.GiftPrintWidget.setMessage('Hello!');
} else if (attempts < 20) {
attempts++;
setTimeout(checkWidget, 50);
}
};
checkWidget();
If the widget is not present (block not added to page, or disabled by merchant), window.GiftPrintWidget is undefined and all methods are no-ops.
Methods affected by merchant settings
Three API methods become silent no-ops when the merchant has hidden the corresponding field in GiftPrint app → Settings → General → Storefront Widget:
setRecipient(name)— no-op when "Show 'To' field" is OFF.setSender(name)— no-op when "Show 'From' field" is OFF.setTemplate(id)— no-op when template selection mode is Fixed (template is locked to the shop default).
Fixed mode also removes the card preview from the page entirely. setMessage(), setRecipient() and setSender() still update the inputs and the cart properties — there is simply no preview element for them to redraw.
Calls don't throw — they just silently do nothing. Use window.GiftPrintWidget.getConfig() if you need to detect which fields are active before driving them programmatically. State queried via getState() reflects the actual DOM state and may return empty strings for hidden fields.
Common patterns
Pre-fill message from URL parameter
Let visitors share gift notes via links:
const params = new URLSearchParams(window.location.search);
const message = params.get('gift_message');
if (message) {
// Poll until the widget is mounted, then set the message
const apply = () => {
if (window.GiftPrintWidget) {
window.GiftPrintWidget.setMessage(message);
window.GiftPrintWidget.enable();
} else {
setTimeout(apply, 50);
}
};
apply();
}
Usage: /products/candle?gift_message=Happy+Birthday!
Lock template to one design
Force all gift notes to use a specific template:
window.GiftPrintWidget.setTemplate('luxury');
// Optional: hide the template picker so users can't change it
document.querySelectorAll('.giftprint-widget__thumbs').forEach(el => {
el.style.display = 'none';
});
Use this if your store's brand identity requires a single consistent design.
Disable default UI, build custom interface
Replace the entire widget with your own HTML and CSS. Use destroy() (not disable()) — disable() unticks the toggle and removes the cart properties, so the gift note would not actually submit. destroy() hides the chrome but forces the toggle on so submissions keep working.
// Hide default widget but keep the gift note submitting
window.GiftPrintWidget.destroy();
// Create custom UI structure
const customUI = document.createElement('div');
customUI.className = 'custom-gift-selector';
const heading = document.createElement('h3');
heading.textContent = 'Personalize Your Gift';
customUI.appendChild(heading);
const select = document.createElement('select');
select.id = 'custom-template';
select.innerHTML = '<option value="luxury">Luxury Design</option><option value="botanical">Botanical</option>';
customUI.appendChild(select);
const textarea = document.createElement('textarea');
textarea.id = 'custom-message';
textarea.placeholder = 'Your message...';
customUI.appendChild(textarea);
const button = document.createElement('button');
button.id = 'custom-add-to-cart';
button.textContent = 'Add to Cart';
customUI.appendChild(button);
// Insert into page
document.querySelector('.product-form').appendChild(customUI);
// Drive hidden inputs with API calls
select.addEventListener('change', (e) => {
window.GiftPrintWidget.setTemplate(e.target.value);
});
textarea.addEventListener('input', (e) => {
window.GiftPrintWidget.setMessage(e.target.value);
});
button.addEventListener('click', () => {
// Widget has already updated hidden inputs; just submit the form
document.querySelector('.product-form').submit();
});
The hidden inputs (which add template and message to the cart) are updated automatically — your custom UI just needs to call the API methods.
Show character limit warning
The textarea already carries maxlength="charLimit", so the browser stops typing at the hard limit. Use this if you also want a visual warning at the optimal limit:
document.addEventListener('giftprint:change', () => {
const config = window.GiftPrintWidget.getConfig();
const textarea = document.querySelector('[data-giftprint-textarea]');
if (textarea) {
textarea.addEventListener('input', () => {
const length = textarea.value.length;
const optimal = config.optimalCharLimit;
const max = config.charLimit;
if (length > max) {
textarea.style.borderColor = 'red';
} else if (length > optimal) {
textarea.style.borderColor = 'orange';
} else {
textarea.style.borderColor = '';
}
});
}
});
Validate before "Add to Cart"
Prevent submission if message is empty when widget is enabled:
document.querySelector('.product-form').addEventListener('submit', (e) => {
const state = window.GiftPrintWidget.getState();
if (state.enabled && !state.message.trim()) {
e.preventDefault();
alert('Please enter a gift message');
return false;
}
});
Reading state and configuration
Get current selections
const state = window.GiftPrintWidget.getState();
console.log(state);
// {
// enabled: true,
// template: "luxury",
// message: "Happy Birthday!",
// to: "Sara",
// from: "Alex"
// }
Use this to:
- Validate before cart submission
- Display a summary of selections
- Read values for custom UIs (including the recipient and sender name fields)
Get widget configuration
const config = window.GiftPrintWidget.getConfig();
console.log(config);
// {
// charLimit: 500,
// optimalCharLimit: 120,
// templates: ["minimal", "botanical", "luxury", ...],
// defaultTemplate: "luxury"
// }
Use this to:
- Display template options dynamically (instead of hardcoding)
- Mirror
charLimitinto your own custom input (the built-in textarea already has it asmaxlength) - Show warnings at
optimalCharLimit
Debugging
Open the browser console on a product page with the widget and try:
// Check if widget is loaded
console.log(window.GiftPrintWidget);
// Get current state
console.log(window.GiftPrintWidget.getState());
// Get configuration
console.log(window.GiftPrintWidget.getConfig());
// Try setting a message
window.GiftPrintWidget.setMessage('Test message');
// Check if it worked
console.log(window.GiftPrintWidget.getState());
If window.GiftPrintWidget is undefined:
- Verify the Gift Note Widget block is added to the product page template
- Check that the GiftPrint app is installed and that Enable widget is on in Settings → General → Storefront Widget
- Refresh the page
If methods don't produce visible changes:
- Check the widget state with
getState()— if it shows the changes, the API works but the UI might be hidden - Verify the widget is enabled with
enable()to show the UI - Check theme JavaScript errors in the browser console
Persistence across pages
Widget state is per-page. When you navigate away from the product page:
- Template and message selections are saved to the hidden form inputs
- The selections are sent to the cart when customer clicks "Add to Cart"
- On a new product page, the widget loads fresh with the merchant's default template and empty message
If you want to preserve state across pages (e.g., pre-filling the same message on every product), use URL parameters or browser localStorage:
// Save to localStorage
window.GiftPrintWidget.setMessage('My message');
localStorage.setItem('giftprint_message', 'My message');
// Restore on next page
const saved = localStorage.getItem('giftprint_message');
if (saved) {
window.GiftPrintWidget.setMessage(saved);
}
Permissions and security
The JavaScript API has no special permissions — it operates entirely within the browser and the Shopify cart. Message and template data flow to cart properties, just like user typing.
No authentication or API keys needed.