Configuration
Odus Elements is configured at two levels:
- Global — via the
ElementsConfigobject passed to theOdusElementsconstructor. - Per-element — via
MountOptionspassed toupdate()after mounting individual elements.
ElementsConfig
| Option | Type | Required | Description |
|---|---|---|---|
apiKey | string | ✅ | Your Odus publishable key |
environment | 'test' | 'live' | ✅ | API environment |
returnUrl | string | ✅ | URL to redirect to after 3DS authentication or other redirect flows |
locale | Locale | Language for all elements (auto-detected by default) | |
callbacks | Callbacks | Payment lifecycle event handlers | |
additionalPaymentMethods | AdditionalPaymentMethods | Express payment method config (e.g., Apple Pay) |
const checkout = new OdusElements({
apiKey: 'pk_test_your_publishable_key',
environment: 'test',
returnUrl: 'https://your-website.com/checkout/return',
locale: 'en',
callbacks: {
onPaymentSucceeded: (result) => console.log('Succeeded', result),
onPaymentFailed: (error) => console.error('Failed', error),
onActionRequired: (url) => {
window.location.href = url;
},
},
});
Callbacks
Handle payment lifecycle events by passing callback functions in the callbacks option.
In reactive frameworks (React, Vue, Svelte), callbacks defined at mount time capture state via closure and can become stale when dependencies change. Use setCallbacks() to update callbacks without remounting:
// React example
useEffect(() => {
checkoutRef.current?.setCallbacks({
onPaymentSucceeded: () => trackPurchase(priceId, quantity),
onPaymentFailed: (result) => logError(priceId, result),
});
}, [priceId, quantity]);
Only the callbacks you pass are replaced — omitted callbacks remain unchanged.
onPaymentSucceeded
Fires when a payment is successfully authorized. Does not fire for redirect-based flows (PayPal, 3DS).
onPaymentSucceeded: (result) => {
// result is the payment status: 'authorized'
window.location.href = '/checkout/success';
};
onPaymentFailed
Fires when a payment fails. Does not fire for redirect-based flows.
onPaymentFailed: (result) => {
// result is a user-friendly error message
console.error('Payment failed:', result);
};
onActionRequired
Fires when a payment requires a redirect (e.g., 3DS authentication, PayPal authorization).
onActionRequired: (redirectUrl) => {
window.location.href = redirectUrl;
};
Unlike Drop-in Checkout, Elements has no manualActionHandling toggle — onActionRequired always fires when a redirect is needed. Handle the URL however you like (navigate, open in a modal, etc.).
Localization
Elements auto-detects the customer's browser language by default. Override this globally in ElementsConfig:
const checkout = new OdusElements({
// ...other options
locale: 'fr',
});
Supported Locales
| Code | Language |
|---|---|
en | English |
fr | French |
de | German |
es | Spanish |
it | Italian |
pl | Polish |
pt | Portuguese |
tr | Turkish |
cs | Czech |
nl | Dutch |
sk | Slovak |
Additional Payment Methods
Configure express payment methods through the additionalPaymentMethods option.
Apple Pay
const checkout = new OdusElements({
// ...other options
additionalPaymentMethods: {
applePay: {
displayName: 'My Store',
countries: ['US', 'GB'],
requiredBillingContactFields: ['postalAddress'],
requiredShippingContactFields: ['email', 'name'],
},
},
});
| Option | Type | Description |
|---|---|---|
displayName | string | Name shown in the Apple Pay payment sheet |
countries | string[] | ISO country codes where Apple Pay is available |
requiredBillingContactFields | ApplePayContactField[] | Billing fields to request (Apple docs) |
requiredShippingContactFields | ApplePayContactField[] | Shipping fields to request (Apple docs) |
ApplePayContactField values: email, name, phone, postalAddress, phoneticName
PayPal requires no additional configuration — simply mount the express.payPal element and it renders automatically after associatePayment() is called, provided the payment supports PayPal.
Per-Element Options (MountOptions)
Customize individual elements via update() after mounting:
checkout.elements.contact.email.mount('#email-container');
checkout.elements.contact.email.update({
locale: 'fr',
disabled: true,
initialValue: 'user@example.com',
});
// Limit street address to 100 characters
checkout.elements.address.street.mount('#street-container');
checkout.elements.address.street.update({ maxLength: 100 });
| Option | Type | Description |
|---|---|---|
locale | string | Override the global locale for this element |
disabled | boolean | Render the element in a disabled state |
initialValue | varies | Pre-fill the element (type depends on the element) |
maxLength | number | Maximum character limit for text inputs (e.g., address.street) |
callbacks | object | Per-element event callbacks |
Per-Element Events
Register event callbacks using on():
checkout.elements.contact.email.on('change', (data) => console.log('changed', data)).on('blur', () => console.log('blurred'));
| Event | Description |
|---|---|
change | Element value changed |
blur | Element lost focus |
focus | Element gained focus |
error | Element encountered a validation error |
ready | Element finished rendering and is interactive |