Skip to main content

Customization

Customize the appearance and behavior of secure payment fields. See the SecureFieldsConfig reference for complete technical details.

Card Networks​

Specify which card networks your payment form accepts:

const config: SecureFieldsConfig = {
brands: ['VISA', 'MASTERCARD', 'AMERICAN_EXPRESS', 'CARTE_BANCAIRE'],
// ...other config
}

To accept Oney private cards, add 'ONEY' to this list — their CVV field collects a date of birth instead of a security code. See Oney private cards.

Field Configuration​

Configure where each secure field appears in your form. The holderName field is optional and depends on your PSP requirements.

fields: {
cardNumber: {
target: 'card-number-container',
placeholder: '1234 5678 9012 3456',
ariaLabel: 'Credit Card Number',
iframeTitle: 'Secure Card Number Input'
},
cvv: {
target: 'cvv-container',
placeholder: 'CVV',
ariaLabel: 'Card Security Code',
iframeTitle: 'Secure CVV Input'
},
expDate: {
target: 'exp-date-container',
placeholder: 'MM/YY',
ariaLabel: 'Expiry Date',
iframeTitle: 'Secure Expiry Date Input'
},
holderName: {
target: 'holder-name-container',
placeholder: 'John Doe',
ariaLabel: 'Cardholder Name',
iframeTitle: 'Secure Cardholder Name Input'
}
}

Field Properties:

PropertyTypeRequiredDescription
targetstringYesID of the DOM element where the field renders
placeholderstringNoPlaceholder text
ariaLabelstringNoAccessible name of the input. Defaults to an English label such as "Card number"
iframeTitlestringNoiframe title attribute
descriptionstringNoHelp text read with the field, such as the expected format
errorMessagesobjectNoPer-validation-error text announced to screen readers — see Accessible error messages
brandSelectorLabelstringNoCard number only: accessible name of the co-badge brand list. Defaults to "Card brand"

Set lang at the top level of the config to the language of these texts, as a BCP 47 tag such as 'fr'. It defaults to your page's <html lang>, then to 'en'. See Accessibility for what each property is for.

Accessible error messages​

The field's <input> lives inside a cross-origin iframe, so it cannot carry an aria-describedby pointing at an error message you render on your own page — that attribute only resolves inside the same document. Passing errorMessages lets the field announce the right message itself, from inside the frame, where its own aria-describedby can reach it:

fields: {
cardNumber: {
target: 'card-number-container',
placeholder: '1234 5678 9012 3456',
ariaLabel: 'Credit Card Number',
iframeTitle: 'Secure Card Number Input',
errorMessages: {
empty: 'The card number is required',
length: 'The card number is incomplete',
format: 'The card number is invalid',
},
},
}

errorMessages accepts a subset of empty, format, length and expired — only the keys your field can raise are used. Keep rendering your own visible message on the host page from the same source text, with role="alert"; the two are independent and the field's built-in announcement does not replace it. The field is announced invalid once the user has left it, or after a rejected submit() — a partially typed value is not read out as invalid while the user is still typing. The message then stays in the input's description, so it is read again when the user comes back to the field.

Hosted form mode

If you use mode: 'hosted_form', this is filled in for you from the texts you pass in hostedForm — you do not need to set errorMessages yourself.

See the SecureFieldsFieldConfig reference for the full error key list.

Brand Selector​

Enable the built-in brand selector for co-branded cards:

const config: SecureFieldsConfig = {
brands: ['VISA', 'MASTERCARD', 'CARTE_BANCAIRE'],
brandSelector: true,
// ...other config
}

When enabled, a dropdown appears when multiple brands are detected. When disabled, you must handle brand selection yourself and pass selectedNetwork to the submit() method. See Collect card details for manual brand selection.

Styling​

Customize field appearance using the styles property:

styles: {
input: {
fontSize: '16px',
color: '#333',
':focus': {
color: '#0070f3'
},
'::placeholder': {
color: '#999'
}
}
}

Focus indicator​

The input inside the frame has no outline, and the style properties below cannot add one. Draw the focus indicator on the field's container from the focus and blur events — see Draw the focus indicator.

Custom Fonts​

info

For security reasons, custom fonts must be hosted on a secure HTTPS server. Contact your Purse integration team to enable custom font files.

styles: {
fontSrc: 'https://fonts.example.com/myfont.woff2',
input: {
fontFamily: 'MyCustomFont, sans-serif'
}
}

Pseudo-Classes​

Supported pseudo-classes for state-based styling:

  • :empty — Field is empty
  • :focus — Field has focus
  • :valid — Field contains valid input
  • :invalid — Field contains invalid input, once the user has left it or after a rejected submit()
  • :autocomplete — Field was autocompleted
  • ::placeholder — Placeholder text

Style Properties​

  • fontFamily
  • fontSize
  • lineHeight
  • fontWeight
  • color
  • backgroundColor
  • placeholderColor

Complete Example​

const config: SecureFieldsConfig = {
brands: ['VISA', 'MASTERCARD', 'AMERICAN_EXPRESS', 'CARTE_BANCAIRE'],
brandSelector: true,
fields: {
cardNumber: {
target: 'card-number-container',
placeholder: '1234 5678 9012 3456',
ariaLabel: 'Credit Card Number',
iframeTitle: 'Secure Card Number Input'
},
cvv: {
target: 'cvv-container',
placeholder: 'CVV',
ariaLabel: 'Card Security Code',
iframeTitle: 'Secure CVV Input'
},
expDate: {
target: 'exp-date-container',
placeholder: 'MM/YY',
ariaLabel: 'Expiry Date',
iframeTitle: 'Secure Expiry Date Input'
},
holderName: {
target: 'holder-name-container',
placeholder: 'John Doe',
ariaLabel: 'Cardholder Name',
iframeTitle: 'Secure Cardholder Name Input'
}
},
styles: {
fontSrc: 'https://fonts.example.com/custom-font.woff2',
input: {
fontFamily: 'CustomFont, Arial, sans-serif',
fontSize: '16px',
color: '#1a1a1a',
':focus': {
color: '#0070f3'
},
':invalid': {
color: '#d32f2f'
},
'::placeholder': {
color: '#999999'
}
}
}
}

const secureForm = await sf.initSecureFields({
tenantId: '${VAULT_TENANT_ID}',
config: config,
});

Next Steps​