Forms & Content
Submitting to a shop's contact forms, and reading the small set of content pages headless shops can still show.
Forms
storefront.forms lets a headless shop submit to a Bolder contact form (the same forms
you build in the shop admin) without any Bolder-hosted markup. Useful for a contact page
or feedback form on a statically-generated site, where the form’s HTML needs to be part
of the static page for SEO but the submission still needs to reach the shop’s contacts.
get(slug, fn)
Fetches a form’s field definitions so you can render your own inputs.
storefront.forms.get('contact', (err, form) => {
if (err) return console.error(err)
console.log(form.title, form.message) // form.message is the form's body/intro text
form.contactFields.forEach(field => {
// field: { key, name, field_type, required, value, options? }
})
form.customFields.forEach(field => { /* same shape */ })
})
submit(form, data, fn)
Submits data collected from your own form UI. Pass the form object returned by get()
— submit uses it to sort your flat data object into the contact_fields/
custom_fields split the backend expects, keyed by each field’s key.
storefront.forms.get('contact', (err, form) => {
myForm.addEventListener('submit', e => {
e.preventDefault()
storefront.forms.submit(form, {
name: myForm.name.value,
email: myForm.email.value,
message: myForm.message.value, // a custom field, e.g.
}, (err, result) => {
if (err) return showErrors(err.errors)
showSuccess(form.sentMessageText)
})
})
})
On validation failure err is { success: false, errors: [{ field, messages }] }.
Content JSON endpoints
A headless shop 404s on every server-rendered page — there’s no theme to render it with — except
for a small set of shop-authored/-configured content pages that are also served as plain JSON, so
a headless integration can still show them: storefront.promos, plus storefront.plans and
storefront.points when the shop has them enabled.
storefront.promos.get(function(err, promos) { renderPromos(promos) })
| Endpoint | SDK | Mirrors | Returns |
|---|---|---|---|
GET /plans.json |
storefront.plans.get(fn) |
/plans |
Array of membership plans: { id, name, description, url, images, attributes, subscription_fees }. Each subscription_fees entry has { id, setup_fee, renewal_fee, payment_interval, interval_label, variant_id } (amounts are numeric, smallest-currency-unit). |
GET /promos.json |
storefront.promos.get(fn) |
/promos |
Array of the shop’s visible/eligible promotions — same shape as GET /promos/:id.json: { id, discount, discount_type, name, automatic, full_discount, ... }. |
GET /policies/points.json |
storefront.points.get(fn) |
/policies/points |
The shop’s points-club policy config (naming, earn/expiration rules, an example earn calculation, contact channel) — not a customer’s balance, see buyer_points under Customer Console for that. {} if the shop has the points-club addon but no settings configured. |
storefront.plans and storefront.points only exist when /shop.json reports the shop has them
enabled (plans_enabled/points_enabled) — a shop without membership plans has no
storefront.plans at all, rather than one that 404s when called. storefront.promos is always
present. All three are unauthenticated, public reads — no storefront.authAjax needed.