Skip to main content
Embedded checkout allows you to embed Whop’s checkout flow on your own website. This allows you to offer your customers a seamless checkout experience without leaving your website.

React setup

Step 1: Install the package

npm install @whop/checkout

Step 2: Add the checkout element

import { WhopCheckoutEmbed } from "@whop/checkout/react";

export default function Home() {
  return (
    <WhopCheckoutEmbed
      planId="plan_XXXXXXXXX"
      returnUrl="https://yoursite.com/checkout/complete"
    />
  );
}
This component will mount an iframe with the Whop checkout embed. The returnUrl is required to handle redirects from external payment providers. When redirected, check the status query parameter:
  • success: The payment succeeded. Use the receipt information to render a success page.
  • error: The payment failed or was canceled. Remount the checkout so your customer can try again.
Keep that Plan ID handy. You’ll need to paste it into your website code, so save it somewhere you can find it.

Step 3: (optional) Configure - Programmatic controls

To get access to the controls of the checkout embed, you can use the ref prop.
const ref = useCheckoutEmbedControls();

return <WhopCheckoutEmbed ref={ref} planId="plan_XXXXXXXXX" />;

submit

To submit checkout programmatically, you can use the submit method on the checkout element.
ref.current?.submit();

getEmail

To get the email of the user who is checking out, you can use the getEmail method on the checkout element.
const email = await ref.current?.getEmail();
console.log(email);

setEmail

To set the email of the user who is checking out, you can use the setEmail method on the checkout element.
try {
  await ref.current?.setEmail("example@domain.com");
} catch (error) {
  console.error(error);
}

getAddress

To get the address of the user who is checking out, you can use the getAddress method on the checkout element.
const address = await ref.current?.getAddress();
console.log(address);

setAddress

To set the address of the user who is checking out, you can use the setAddress method on the checkout element.
This method will only work if the address form is hidden. You can hide the address form by setting the hideAddressForm prop to true.
try {
  await ref.current?.setAddress({
    name: "John Doe",
    country: "US",
    line1: "123 Main St",
    city: "Any Town",
    state: "CA",
    postalCode: "12345",
  });
} catch (error) {
  console.error(error);
}

Step 4: (optional) Configure - Available properties

planId

Required - The plan id you want to checkout.

theme

Optional - The theme you want to use for the checkout. Possible values are light, dark or system.

sessionId

Optional - The session id to use for the checkout. This can be used to attach metadata to a checkout by first creating a session through the API and then passing the session id to the checkout element.

returnUrl

Optional - The URL to redirect the user to after checkout completes.
<WhopCheckoutEmbed
  returnUrl="https://yoursite.com/checkout/complete"
  planId="plan_XXXXXXXXX"
/>

affiliateCode

Optional - The affiliate code to use for the checkout.
<WhopCheckoutEmbed affiliateCode="tristan" planId="plan_XXXXXXXXX" />

hidePrice

Optional - Turn on to hide the price in the embedded checkout form. Defaults to false

hideTermsAndConditions

Optional - Set to true to hide the terms and conditions in the embedded checkout form. Defaults to false

skipRedirect

Optional - Set to true to skip the final redirect and keep the top frame loaded. Defaults to false

onComplete

Optional - A callback function that will be called when the checkout is complete.
This option will set skipRedirect to true
<WhopCheckoutEmbed
  onComplete={(planId, receiptId) => {
    console.log(planId, receiptId);
  }}
  planId="plan_XXXXXXXXX"
/>

utm

Optional - The UTM parameters to add to the checkout URL. Note - The keys must start with utm_
<WhopCheckoutEmbed
  planId="plan_XXXXXXXXX"
  utm={{ utm_campaign: "ad_XXXXXXX" }}
/>

fallback

Optional - The fallback content to show while the checkout is loading.
<WhopCheckoutEmbed fallback={<>loading...</>} planId="plan_XXXXXXXXX" />

prefill

Optional - The prefill options to apply to the checkout embed. Used to prefill the email or address in the embedded checkout form. This setting can be helpful when integrating the embed into a funnel that collects the email prior to payment already.
<WhopCheckoutEmbed
  prefill={{ email: "example@domain.com" }}
  planId="plan_XXXXXXXXX"
/>
<WhopCheckoutEmbed
  prefill={{ address: {
    name: "John Doe",
    country: "US",
    line1: "123 Main St",
    city: "Any Town",
    state: "CA",
    postalCode: "12345",
  } }}
  planId="plan_XXXXXXXXX"
/>

hideEmail

Optional - Set to true to hide the email input in the embedded checkout form. Make sure to display the users email in the parent page when setting this attribute. Defaults to false
Use this in conjunction with the prefill attribute or the setEmail method to control the email input.
<WhopCheckoutEmbed hideEmail planId="plan_XXXXXXXXX" />

disableEmail

Optional - Set to true to disable the email input in the embedded checkout form. Defaults to false
Use this in conjunction with the prefill attribute or the setEmail method to control the email input.
<WhopCheckoutEmbed disableEmail planId="plan_XXXXXXXXX" />

hideAddressForm

Optional - Set to true to hide the address form in the embedded checkout form. Defaults to false
Use this in conjunction with the setAddress method to control the address input.
<WhopCheckoutEmbed hideAddressForm planId="plan_XXXXXXXXX" />

setupFutureUsage

Optional - The setup future usage to use for the checkout. When using the chargeUser API you need to set this to off_session. This will filter out payment methods that are not supported with that API.
<WhopCheckoutEmbed setupFutureUsage="off_session" planId="plan_XXXXXXXXX" />

onStateChange

Optional - A callback function that will be called when the checkout state changes. This can be used when programmatically submitting the checkout embed. Possible values are loading, ready, disabled.
<WhopCheckoutEmbed onStateChange={(state) => {
  console.log(state);
}} planId="plan_XXXXXXXXX" />

environment

Optional - The environment to use for the checkout. Possible values are production or sandbox. Defaults to production
When using sandbox, make sure to use a sandbox plan ID. Sandbox plans can be created in the sandbox dashboard.
<WhopCheckoutEmbed environment="sandbox" planId="plan_XXXXXXXXX" />

onAddressValidationError

Optional - A callback function that will be called when the address validation error occurs.
This method will only work if the address form is hidden. You can hide the address form by setting the hideAddressForm prop to true.
<WhopCheckoutEmbed
  hideAddressForm
  onAddressValidationError={(error) => {
    console.log(error);
  }}
  planId="plan_XXXXXXXXX"
/>

styles

Optional - Customize the padding of the checkout embed container. The styles prop accepts a container object with the following properties:
PropertyDescriptionDefault
paddingTopTop padding in pixels32
paddingBottomBottom padding in pixels32
paddingLeftLeft padding in pixels32
paddingRightRight padding in pixels32
paddingYShorthand for top and bottom padding32
paddingXShorthand for left and right padding32
Individual properties take precedence over their shorthand equivalents.
<WhopCheckoutEmbed
  planId="plan_XXXXXXXXX"
  styles={{ container: { paddingX: 0 } }}
/>
<WhopCheckoutEmbed
  planId="plan_XXXXXXXXX"
  styles={{ container: { paddingLeft: 16, paddingRight: 16, paddingTop: 0, paddingBottom: 0 } }}
/>

Full example

import { WhopCheckoutEmbed } from "@whop/checkout/react";

export default function Home() {
  return (
    <WhopCheckoutEmbed
      fallback={<>loading...</>}
      planId="plan_XXXXXXXXX"
      sessionId="ch_XXXXXXXXX"
      returnUrl="https://yoursite.com/checkout/complete"
      theme="light"
      hidePrice={false}
    />
  );
}

Other websites

Step 1: Add the script tag

To embed checkout, you need to add the following script tag into the <head> of your page:
<script
  async
  defer
  src="https://js.whop.com/static/checkout/loader.js"
></script>

Step 2: Add the checkout element

To create a checkout element, you need to include the following attributes on an element in your page:
<div
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
  data-whop-checkout-return-url="https://yoursite.com/checkout/complete"
></div>
This will mount an iframe inside of the element with the plan id you provided. The data-whop-checkout-return-url is required to handle redirects from external payment providers. When redirected, check the status query parameter:
  • success: The payment succeeded. Use the receipt information to render a success page.
  • error: The payment failed or was canceled. Remount the checkout so your customer can try again.

Step 3: (optional) Configure - Programmatic controls

First, attach an id to the checkout container:
<div id="whop-embedded-checkout" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

submit

To submit checkout programmatically, you can use the submit method on the checkout element.
wco.submit("whop-embedded-checkout");

getEmail

To get the email of the user who is checking out, you can use the getEmail method on the checkout element.
const email = await wco.getEmail("whop-embedded-checkout");
console.log(email);

setEmail

To set the email of the user who is checking out, you can use the setEmail method on the checkout element.
wco.setEmail("whop-embedded-checkout", "example@domain.com");

getAddress

To get the address of the user who is checking out, you can use the getAddress method on the checkout element.
const address = await wco.getAddress("whop-embedded-checkout");
console.log(address);

setAddress

To set the address of the user who is checking out, you can use the setAddress method on the checkout element.
This method will only work if the address form is hidden. You can hide the address form by setting the data-whop-checkout-hide-address prop to true.
try {
  await wco.setAddress("whop-embedded-checkout", {
    name: "John Doe",
    country: "US",
    line1: "123 Main St",
    city: "Any Town",
    state: "CA",
    postalCode: "12345",
  });
} catch (error) {
  console.error(error);
}

Step 4: (optional) Configure - Available attributes

data-whop-checkout-plan-id

Required - The plan id you want to checkout.
To get your plan id, you need to first create a plan in the Manage Pricing section on your whop page.

data-whop-checkout-theme

Optional - The theme you want to use for the checkout. Possible values are light, dark or system.
<div data-whop-checkout-theme="light" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-theme-accent-color

Optional - The accent color to apply to the checkout embed Possible values are
  • tomato
  • red
  • ruby
  • crimson
  • pink
  • plum
  • purple
  • violet
  • iris
  • cyan
  • teal
  • jade
  • green
  • grass
  • brown
  • blue
  • orange
  • indigo
  • sky
  • mint
  • yellow
  • amber
  • lime
  • lemon
  • magenta
  • gold
  • bronze
  • gray
<div data-whop-checkout-theme-accent-color="green" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-session

Optional - The session id to use for the checkout. This can be used to attach metadata to a checkout by first creating a session through the API and then passing the session id to the checkout element.
<div data-whop-checkout-session="ch_XXXXXXXXX" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-return-url

Optional - The URL to redirect the user to after checkout completes.
<div data-whop-checkout-return-url="https://yoursite.com/checkout/complete" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-affiliate-code

Optional - The affiliate code to use for the checkout.
<div data-whop-checkout-affiliate-code="tristan" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-hide-price

Optional - Set to true to hide the price in the embedded checkout form. Defaults to false
<div data-whop-checkout-hide-price="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-hide-submit-button

Optional - Set to true to hide the submit button in the embedded checkout form. Defaults to false
When using this Option, you will need to programmatically submit the checkout form.
<div data-whop-checkout-hide-submit-button="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-hide-tos

Optional - Set to true to hide the terms and conditions in the embedded checkout form. Defaults to false
<div data-whop-checkout-hide-tos="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-skip-redirect

Optional - Set to true to skip the final redirect and keep the top frame loaded. Defaults to false
<div data-whop-checkout-skip-redirect="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-on-complete

Optional - The callback to call when the checkout succeeds
This option will set data-whop-checkout-skip-redirect to true
<script>
  window.onCheckoutComplete = (planId, receiptId) => {
    console.log(planId, receiptId);
  };
</script>

<div
  data-whop-checkout-on-complete="onCheckoutComplete"
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
></div>

data-whop-checkout-on-state-change

Optional - The callback to call when state of the checkout changes This can be used when programmatically submitting the checkout embed. Possible values are loading, ready, disabled.
<script>
  window.onCheckoutStateChange = (state) => {
    console.log(state);
  };
</script>

<div
  data-whop-checkout-on-state-change="onCheckoutStateChange"
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
></div>

data-whop-checkout-skip-utm

By default any utm params from the main page will be forwarded to the checkout embed. Optional - Set to true to prevent the automatic forwarding of utm parameters Defaults to false

data-whop-checkout-prefill-*

Used to prefill the email or address in the embedded checkout form. This setting can be helpful when integrating the embed into a funnel that collects the email prior to payment already.
<div data-whop-checkout-prefill-email="example@domain.com" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

<div 
	data-whop-checkout-prefill-name="John Doe"
	data-whop-checkout-prefill-address-country="US"
	data-whop-checkout-prefill-address-line1="123 Main St"
	data-whop-checkout-prefill-address-line2=""
	data-whop-checkout-prefill-address-city="Any Town"
	data-whop-checkout-prefill-address-state="CA"
	data-whop-checkout-prefill-address-postal-code="12345"
	data-whop-checkout-plan-id="plan_XXXXXXXXX"
></div>

<div data-whop-checkout-prefill-address-name="John Doe" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-hide-email

Optional - Set to true to hide the email input in the embedded checkout form. Make sure to display the users email in the parent page when setting this attribute. Defaults to false
Use this in conjunction with the data-whop-checkout-prefill-email attribute or the setEmail method to control the email input.
<div data-whop-checkout-hide-email="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-disable-email

Optional - Set to true to disable the email input in the embedded checkout form. Defaults to false
Use this in conjunction with the data-whop-checkout-prefill-email attribute or the setEmail method to control the email input.
<div data-whop-checkout-disable-email="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-hide-address

Optional - Set to true to hide the address form in the embedded checkout form. Defaults to false
This method will only work if the address form is hidden. You can hide the address form by setting the data-whop-checkout-hide-address prop to true.
<div data-whop-checkout-hide-address="true" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-setup-future-usage

Optional - The setup future usage to use for the checkout. When using the chargeUser API you need to set this to off_session. This will filter out payment methods that are not supported with that API.
<div data-whop-checkout-setup-future-usage="off_session" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-environment

Optional - The environment to use for the checkout. Possible values are production or sandbox. Defaults to production
When using sandbox, make sure to use a sandbox plan ID. Sandbox plans can be created in the sandbox dashboard.
<div data-whop-checkout-environment="sandbox" data-whop-checkout-plan-id="plan_XXXXXXXXX"></div>

data-whop-checkout-on-address-validation-error

Optional - The callback to call when the address validation error occurs.
This method will only work if the address form is hidden. You can hide the address form by setting the data-whop-checkout-hide-address prop to true.
<script>
  window.onAddressValidationError = (error) => {
    console.log(error);
  };
</script>

<div
  data-whop-checkout-on-address-validation-error="onAddressValidationError"
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
></div>

data-whop-checkout-style-*

Optional - Customize the padding of the checkout embed container. The attribute pattern is data-whop-checkout-style-container-{property} where {property} is a kebab-case padding property.
AttributeDescriptionDefault
data-whop-checkout-style-container-padding-topTop padding in pixels32
data-whop-checkout-style-container-padding-bottomBottom padding in pixels32
data-whop-checkout-style-container-padding-leftLeft padding in pixels32
data-whop-checkout-style-container-padding-rightRight padding in pixels32
data-whop-checkout-style-container-padding-yShorthand for top and bottom padding32
data-whop-checkout-style-container-padding-xShorthand for left and right padding32
Individual properties take precedence over their shorthand equivalents.
<div
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
  data-whop-checkout-style-container-padding-x="0"
></div>
<div
  data-whop-checkout-plan-id="plan_XXXXXXXXX"
  data-whop-checkout-style-container-padding-left="16"
  data-whop-checkout-style-container-padding-right="16"
  data-whop-checkout-style-container-padding-top="0"
  data-whop-checkout-style-container-padding-bottom="0"
></div>

Full example

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width">
		<script
			async
			defer
  			src="https://js.whop.com/static/checkout/loader.js"
		></script>
		<title>Whop embedded checkout example</title>
		<style>
			div {
				box-sizing: border-box;
			}
			body {
				margin: 0
			}
		</style>
	</head>
	<body>
		<div
			data-whop-checkout-plan-id="plan_XXXXXXXXX"
			data-whop-checkout-session="ch_XXXXXXXXX"
			data-whop-checkout-return-url="https://yoursite.com/checkout/complete"
			data-whop-checkout-theme="light"
			data-whop-checkout-hide-price="false"
			style="height: fit-content; overflow: hidden; max-width: 50%;"
		></div>
	</body>
</html>

Apple Pay

Apple Pay allows customers to pay using their Apple Wallet, providing a seamless checkout experience on Safari and iOS devices. To enable Apple Pay on your embedded checkout, you need to verify ownership of your domain.

Set up Apple Pay

Learn how to verify your domain and enable Apple Pay for embedded checkout
When using the hideSubmitButton option in React, @whop/checkout@0.0.43 or later is required for Apple Pay to appear in the embed.

FAQs

Make sure you’ve correctly replaced plan_XXXXXXXXX or PLAN_ID_HERE in the code snippets with your actual Plan ID from the Whop dashboard. Also verify that the script tag is properly loaded in the <head> section if using HTML/JS.
Go to your Dashboard > Checkout links > Click the three dots (⋮) on your pricing option > Hover over Details > Click the ID (starts with plan_) to copy it.
Yes, you can add multiple checkout embeds with different Plan IDs. Each embed operates independently.
For React: add theme="dark" or theme="light" as a property. For HTML: add data-whop-checkout-theme="dark" to your div element.
Yes, add hidePrice={true} in React or data-whop-checkout-hide-price="true" in HTML to hide the price display.
By default, customers are redirected to your whop. You can customize this by setting a custom redirect URL or skipping the redirect entirely.
Use skipRedirect={true} in React or data-whop-checkout-skip-redirect="true" in HTML to keep users on the same page.
Yes, the checkout automatically adapts to different screen sizes and devices.
You can style the wrapper using the .whop-checkout-wrapper iframe CSS class, but the checkout content itself cannot be modified for security reasons.
Yes, use prefill={{ email: "customer@example.com" }} in React or data-whop-checkout-prefill-email="customer@example.com" in HTML.