Build an integration with an embedded formPublic preview
The following guide describes how to use the embedded form with Checkout Sessions.
You can also build and preview your embedded Checkout form through Checkout studio, which provides a centralized Dashboard page for configuring and monitoring your Checkout integrations.
Set up StripeServer-side
First, create a Stripe account or sign in.
Use our official libraries to access the Stripe API from your application:
Enable payment methods
By default, Stripe uses your payment methods settings to determine which payment methods the embedded form presents. You can also configure specific payment methods on your Checkout Session using the payment_method_types attribute.
Create a Checkout SessionServer-side
Create a Checkout Session on your server to control the payment flow. The Checkout Session defines your line items, shipping options, and other settings for the payment.
curl https://api.stripe.com/v1/checkout/sessions \ -u "sk_test_BQokikJOvBiI2HlWgH4olfQ2:" \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=form \ -d return_url={{RETURN_URL}} \ -d integration_identifier=embedded_web_0001
Set ui_ to form to integrate with the embedded form. The returned CheckoutSession object includes a client secret, which the client uses to securely display the checkout interface.
The Checkout Sessions API supports an optional integration_ parameter you can set when creating a session. Use it to label this form integration with a recognizable name and measure its conversion independently from other Checkout integrations you run.
You can also configure the following options on the CheckoutSession:
- automatic_tax: Enable automatic tax calculation
- automatic_tax[address_collection_precision]: Control billing address collection in embedded forms for tax calculation when automatic tax is enabled
- billing_address_collection: Collect billing addresses
- customer_email: Prefill the customer’s email address
- customer: Prefill customer data from an existing
Customerobject - name_collection: Collect your customers’ business name, individual name, or both
- shipping_address_collection: Collect shipping addresses
- shipping_options: Provide shipping rate options
- submit_type: Specify the type of transaction being performed
- phone_number_collection: Collect your customer’s phone number
- tax_id_collection: Collect tax IDs
- allow_promotion_codes: Allow customer-redeemable promotion codes
Unsupported CheckoutSession parameters
The embedded form doesn’t support consent_.
Set up Stripe ElementsClient-side
The embedded form is available as a feature of Stripe.js. Install React Stripe.js and the Stripe.js loader from the npm public registry.
npm install --save @stripe/react-stripe-js @stripe/stripe-js
Create clientSecret as a Promise<string> | string containing the client secret returned by your server. Wrap your application with the CheckoutFormProvider component, passing in clientSecret and the stripe instance.
import React, {useMemo} from 'react'; import {CheckoutFormProvider, CheckoutForm} from '@stripe/react-stripe-js/checkout'; import {loadStripe} from '@stripe/stripe-js'; const stripePromise = loadStripe('pk_test_TYooMQauvdEDq54NiTphI7jx'); const App = () => { const clientSecret = useMemo(() => ( fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret) ), []); return ( <CheckoutFormProvider stripe={stripePromise} options={{clientSecret}} > <CheckoutForm /> </CheckoutFormProvider> ); }; export default App;
Create and mountClient-side
The embedded form contains an iframe that securely sends the payment information to Stripe over an HTTPS connection.
The CheckoutForm component is already rendered inside CheckoutFormProvider in the previous step. No additional mounting is required for React.
You can specify the layout to render the embedded form as a single-step or multi-step embedded form.
Prefill customer email
You can prefill the customer’s email address using one of two approaches, depending on whether you want the email to be editable.
Set the email on the Checkout Session (non-editable)
Pass customer_email when creating the Checkout Session on your server. The email is displayed in the embedded form but the customer can’t change it. You can also pass a Customer ID to the customer field to prefill the email stored on the Customer.
Set a default email on the client (editable)
Pass defaultValues. when initializing the SDK to prefill an editable email. The customer can modify this value in the embedded form.
<CheckoutFormProvider stripe={stripePromise} options={{ clientSecret, defaultValues: { email: 'customer@example.com', }, }} > <CheckoutForm /> </CheckoutFormProvider>
Finalize paymentClient-side
The Checkout Session you created on the server automatically determines the line items, total amount, and available payment methods. The embedded form uses this information to display the appropriate interface.
Handle payment confirmation
Handle the confirm event when your customer finalizes their payment:
import React, {useMemo} from 'react'; import {CheckoutFormProvider, CheckoutForm, useCheckoutForm} from '@stripe/react-stripe-js/checkout'; import {loadStripe} from '@stripe/stripe-js'; const stripePromise = loadStripe('pk_test_TYooMQauvdEDq54NiTphI7jx'); const CheckoutPage = () => { const checkoutState = useCheckoutForm(); if (checkoutState.type === 'error') { return <div>Error: {checkoutState.error.message}</div>; } const onConfirm = (event) => { if (checkoutState.type === 'success') { checkoutState.checkout.confirm({formConfirmEvent: event}); } }; return <CheckoutForm onConfirm={onConfirm} />; }; const App = () => { const clientSecret = useMemo(() => ( fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret) ), []); return ( <CheckoutFormProvider stripe={stripePromise} options={{clientSecret}} > <CheckoutPage /> </CheckoutFormProvider> ); }; export default App;
Handle errors
The embedded form automatically shows localized customer-facing error messages during client confirmation. If a problem prevents the confirm method from continuing, the confirm method can raise an exception. Catch and handle those exceptions.
const onConfirm = async (event) => { if (checkoutState.type === 'success') { try { await checkoutState.checkout.confirm({formConfirmEvent: event}); } catch (error) { console.error('Payment confirmation error:', error); } } };
Customize redirect behavior
By default, after a successful payment, the embedded form redirects your customer to the return_ that you specify when you create the Checkout Session. To prevent redirects for payment methods that don’t require a redirect, such as cards, set redirect to 'if_ when calling confirm. To learn more, see Customize redirect behavior.
Handle post-payment eventsServer-side
The Checkout Session defines your line items, shipping options, and other settings for the payment. After a customer confirms payment on the client, handle the result on your server rather than relying on client-side state.
- Webhooks Recommended: Listen for the checkout.session.completed event, which Stripe sends when the payment succeeds. This approach ensures you’re notified even if the customer closes their browser before the redirect.
- Return page: Retrieve the Checkout Session using its ID to check the payment status and show the appropriate result to your customer on the page you set as the
return_.url
Learn how to fulfill orders after receiving a payment.
Test the integration
Before you go live, test each payment method integration. Click Pay to complete the payment, which redirects you to the specified return page.
If you see the return page, and the payment appears in the list of successful payments in the Dashboard, your integration is working.
Use Stripe’s test card numbers to test card payments. For example:
Customize the layout and appearance
You can customize the embedded form by setting its options or by using the Appearance API.
Layout
Use the layout option to control how the embedded form presents checkout steps.
- Expanded: Use this layout for a single-step checkout. It’s ideal for traditional checkout forms that sit directly on the web page.
- Compact Private preview: Use this layout for multi-step checkout. It’s ideal for more compact UI layouts like modals, popups, and chat UIs.
When you leave layout undefined, Stripe renders the layout it determines has the best conversion.
Request access to the compact layout
The compact layout displays the embedded form as a multi-step checkout flow. It's available by request in private preview. Enter your email address below to request access.
const checkoutFormOptions = { layout: 'expanded', }; <CheckoutForm options={checkoutFormOptions} onConfirm={onConfirm} />
Embedded form options
You can configure the appearance of each express payment method button and pass saved contacts using options.
const checkoutFormOptions = { expressCheckout: { buttonTheme: { applePay: 'white-outline' }, paymentMethods: { applePay: 'always' } } }; <CheckoutForm options={checkoutFormOptions} onConfirm={onConfirm} />
The embedded form supports the following options:
expressCheckout. | Specify a theme per one-click payment button. See buttonTheme. |
expressCheckout. | Specify which one-click payment buttons show. See paymentMethods. |
contacts | An array of objects representing saved addresses, each containing name, address, and phone properties. See contacts. |
Appearance API
You can use the Appearance API to control the style of the embedded form by applying a theme or updating specific details. However, the embedded form doesn’t support the rules option.
For instance, choose the “flat” theme and override the primary text color.
const appearance = { theme: 'flat', variables: { colorPrimaryText: '#262626' } }; <CheckoutFormProvider stripe={stripePromise} options={{, appearance }} > <CheckoutForm /> </CheckoutFormProvider>clientSecret
Disclose Stripe to your customers
Stripe collects information on customer interactions with Elements to provide services to you, prevent fraud, and improve its services. This includes using cookies and IP addresses to identify which Elements a customer saw during a single checkout session. You’re responsible for disclosing and obtaining all rights and consents necessary for Stripe to use data in these ways. For more information, visit our privacy center.