Coupon

Let buyers apply or remove a coupon code with a secure, fully styleable input.

The Coupon component (fs-coupon) renders a coupon code field and Apply button inside a secure iframe served from FastSpring's domain. Applying or removing a code updates the session through the SDK, and components that show session-derived values, such as totals, refresh automatically.

This page is the complete reference for the Coupon component: how to mount it, the options it accepts, the states it exposes for styling, and every style category and property available. For setup context, see the Integration Guide.

Mount

Add a target element to your HTML:

<div id="coupon-element"></div>

Then create the component from your sdk instance and mount it:

const couponComponent = sdk.components.create('fs-coupon', {
    // options + style go here
});

couponComponent.mount('#coupon-element');

Component options

Top-level options passed alongside style:

OptionTypeDefaultDescription
presentation'collapsed' | 'expanded''collapsed'Field visibility. 'collapsed': the field is hidden behind a "Have a coupon code?" link. 'expanded': the field is always visible.
labelMode'floating' | 'fixed''floating'Label placement. 'floating': the label sits inside the input and moves up on focus or when filled. 'fixed': a static label sits above the field, and the field shows a real placeholder.

What the buyer sees

No coupon yet

A "Have a coupon code?" link ('collapsed'), or a "Coupon Code" field and Apply button ('expanded'). Clicking the link reveals the field and focuses it. Apply stays disabled until a code is entered.

Coupon applied

A centered "{code} applied!" chip in teal, with the code in italics and a × to remove it. It also shows on load when the session already has a coupon, including after a page reload.

Code changed

The session updates and onSessionUpdated fires with the new coupon and couponApplied values. Totals in other components, such as the Pay button, refresh without a reload.

Setting a coupon when you create the session

To start the checkout with a coupon already applied, pass cart.couponCode when you create the session with the Sessions API. The component then opens on the applied chip.

How styling works

Styling is configured through a style object passed at component creation. Each state contains one or more style categories (input, button, chip, etc.) that group related properties.

sdk.components.create('fs-coupon', {
    style: {
        state: {
            default:  { /* base styles */ },
            hover:    { /* applied on hover */ },
            focus:    { /* applied on focus */ },
            disabled: { /* applied to disabled controls */ },
            error:    { /* applied in error state */ },
        },
    },
});

Style precedence: FastSpring uses the first value it finds, in this order:

  1. The style you set for the current state (e.g., state.focus.input)
  2. The style you set for the default state (e.g., state.default.input)
  3. globalStyles passed to FastSpring.init()
  4. FastSpring's built-in default (the Default column in the tables below)

Coming from the Card component? The input category uses the same property names as the Card's input where the two overlap, so shared keys carry over. Not every Card key is supported (for example, transition).

Available states

StateWhen applied
defaultAlways (the base styling)
hoverThe pointer is over the link, the Apply button or the remove icon
focusThe input has keyboard focus
disabledDuring the apply or remove round-trip. Apply is also disabled while the field is empty
errorThe backend rejects the code after the buyer clicks Apply

For what each state changes out of the box, see Default values per state.

Style categories

Each category below targets a specific part of the Coupon component. Select a card to jump to its full property reference.

The default font family for every category is Helvetica Neue, helvetica, arial, sans-serif, written as Helvetica Neue stack in the tables below. The component's base text is 14px in #4B5563.

input: the coupon field

PropertyTypeDefaultDescription
backgroundColorstring#fffInput background. background is accepted as a legacy alias.
colorstring#4B5563Text color
borderColorstring#DEE2E6Border color
borderRadiusstring4pxCorner radius
fontSizestring16pxFont size
fontFamilystringHelvetica Neue stackFont family
heightstring48pxInput height. The Apply button matches it.
paddingstring22px 16px 8px 16px (floating), 12px 16px (fixed)Inner padding
placeholderColorstringtransparentPlaceholder color. Transparent in floating mode, where the label acts as the placeholder; set a visible color when using labelMode: 'fixed'.

state.error.input styles the field while the backend has rejected the code. It accepts borderColor and color (both default #EB1431), plus backgroundColor and fontFamily (defaults: the resting values above). These are the same four properties state.error.input takes on Card and Email.

The field label is #64748B. In floating mode it moves to the top at .8rem when the field is focused or filled; in fixed mode it sits above the field at 14px, and the empty field shows the placeholder "Enter Coupon Code".

button: the Apply button

PropertyTypeDefaultDescription
backgroundstring#008AFFButton background
colorstring#fffButton label color
fontWeightstring | number400Button label weight
borderRadiusstring4pxCorner radius

The button is 83px wide, with a 16px Helvetica Neue stack label.

chip: the applied-code chip

PropertyTypeDefaultDescription
backgroundstringtransparentChip background
colorstring#27B2A8Applied-code text color
borderRadiusstring0Corner radius
paddingstring4pxChip padding
gapstring8pxGap between the text and remove icon
fontFamilystringHelvetica Neue stackFont family
fontSizestring12pxFont size
fontWeightstring | number400Font weight
iconSizestring16pxRemove-icon size
iconColorstring#7D8A9BRemove-icon color

The applied code itself is shown in italics.

inlineError: inline validation error messages

Shown 4px below the field when the backend rejects a code. Same category name and properties as on Card and Email, so one error style block works across all three.

PropertyTypeDefaultDescription
colorstring#EB1431Error text color
fontSizestring12pxError font size
fontWeightstring | number400Error font weight
fontFamilystringHelvetica Neue stackError font family (follows the component font)
backgroundColorstringtransparentError message background

Deprecated: error is the old name for this category. It still applies, logs one console warning per component, and loses to inlineError when both are set. inlineError.color no longer sets the field's error border; use state.error.input.borderColor.

toggle: the coupon link

Styles the "Have a coupon code?" link shown in 'collapsed' presentation. The link is underlined and centered.

PropertyTypeDefaultDescription
colorstring#008AFFLink text color

Default values per state

Out of the box, the Coupon component visually changes for hover, focus, disabled, and error.

hover

Applied when the pointer is over an element.

PropertyDefault override value
toggle.color#2563EB
button.background#2563EB
chip.iconColor#4B5563

focus

Applied when the input has keyboard focus.

PropertyDefault override value
input.borderColor#2563EB
Focus glow0 0 0 4px rgba(0, 138, 255, .2) (soft blue glow)
Floating label color#2563EB

disabled

Applied during the apply or remove round-trip. The Apply button also looks disabled while the field is empty.

PropertyDefault override value
input.backgroundColor#E7E7E7
input.color#64748B
button.background#84C6FF

error

Applied when the backend rejects the code. The inlineError message appears 4px below the field.

PropertyDefault override value
input.borderColor#EB1431
input.color#EB1431
Focus glow0 0 0 4px color-mix(in srgb, #EB1431 15%, transparent)
Floating label color#EB1431

Under error, input accepts borderColor, color, backgroundColor and fontFamily, and inlineError accepts all its properties. inlineError styling is also accepted under default; the error value wins when both are set.

Full example

sdk.components.create('fs-coupon', {
    presentation: 'expanded',
    style: {
        state: {
            default: {
                input:  { background: '#0b1220', color: '#f1f5f9', borderColor: '#283449', borderRadius: '10px', placeholderColor: '#64748b' },
                button: { background: '#6366f1', color: '#ffffff', fontWeight: '600', borderRadius: '10px' },
                chip:   { color: '#a5b4fc', iconColor: '#64748b' },
                inlineError: { color: '#fca5a5', backgroundColor: '#1f1a2e' },
                toggle: { color: '#818cf8' },
            },
            focus: { input: { borderColor: '#6366f1' } },
            error: { input: { borderColor: '#f87171', color: '#fecaca' } },
            hover: { button: { background: '#4f46e5' }, toggle: { color: '#a5b4fc' } },
            disabled: { button: { background: '#3730a3' } },
        },
    },
}).mount('#coupon-element');