npm package: @paddle/partner-embeds-react
Description: React bindings for partners to embed Paddle verification flows
Latest version: 1.1.1

# @paddle/partner-embeds-react

React hooks for embedding Paddle flows (verification, etc.) into React applications. Wraps `@paddle/partner-embeds` with idiomatic React APIs that handle mounting, cleanup, and ref management automatically.

## Installation

Both the core SDK and the React bindings are required:

```bash
npm install @paddle/partner-embeds @paddle/partner-embeds-react
```

## Quick start

### Verification flow

```tsx
import { useRef } from 'react'
import { usePaddleVerification } from '@paddle/partner-embeds-react'

function VerificationForm({ token }: { token: string }) {
  const containerRef = useRef<HTMLDivElement>(null)

  usePaddleVerification({
    containerRef,
    token,
    environment: 'sandbox',
    prefill: {
      countryCode: 'US',
      annualRevenue: '100k_500k',
    },
    theme: { mode: 'light' },
    onReady: () => console.log('Loaded'),
    onStepChange: ({ step }) => console.log('Step:', step),
    onComplete: ({ id }) => console.log('Verified:', id),
    onClose: () => console.log('Closed'),
    onError: ({ code, message }) => console.error(code, message),
  })

  return <div ref={containerRef} />
}
```

The hook manages the full embed lifecycle — it mounts the iframe when the component mounts and destroys it on unmount. No manual cleanup is needed.

## API reference

### `usePaddleVerification(options)`

Embeds a Paddle verification flow into a React component.

#### Options

| Option         | Type                             | Required | Description                                                |
| -------------- | -------------------------------- | -------- | ---------------------------------------------------------- |
| `containerRef` | `RefObject<HTMLElement \| null>` | Yes      | React ref to the DOM element that will contain the iframe. |
| `token`        | `string`                         | Yes      | Verification token obtained from the Paddle API.           |
| `environment`  | `'production' \| 'sandbox'`      | No       | Defaults to `'production'`.                                |
| `theme`        | `{ mode: 'light' \| 'dark' }`    | No       | Controls the visual theme of the embedded UI.              |
| `prefill`      | `VerificationPrefillPayload`     | No       | Pre-populate form fields (see below).                      |

#### Prefill options

| Field                | Type                                                                               | Description                             |
| -------------------- | ---------------------------------------------------------------------------------- | --------------------------------------- |
| `countryCode`        | `string`                                                                           | ISO country code (e.g. `'US'`, `'GB'`). |
| `annualRevenue`      | `'not_yet_live' \| '0_100k' \| '100k_500k' \| '500k_3m' \| '3m_10m' \| '10m_plus'` | Annual revenue bracket.                 |
| `businessType`       | `'individual' \| 'private' \| 'public'`                                            | Type of business entity.                |
| `productDescription` | `string`                                                                           | Description of the product being sold.  |
| `pricingPageUrl`     | `string`                                                                           | URL to the pricing page.                |
| `termsOfServiceUrl`  | `string`                                                                           | URL to terms of service.                |
| `privacyPolicyUrl`   | `string`                                                                           | URL to privacy policy.                  |
| `refundPolicyUrl`    | `string`                                                                           | URL to refund policy.                   |

#### Callbacks

##### `onReady`

```ts
onReady?: () => void
```

Fires when the iframe has loaded and is ready for interaction. Use this to hide loading states.

```tsx
function Verification({ token }: { token: string }) {
  const containerRef = useRef<HTMLDivElement>(null)
  const [isLoading, setIsLoading] = useState(true)

  usePaddleVerification({
    containerRef,
    token,
    onReady: () => setIsLoading(false),
  })

  return (
    <>
      {isLoading && <Spinner />}
      <div ref={containerRef} />
    </>
  )
}
```

##### `onStepChange`

```ts
onStepChange?: (payload: { step: string; totalSteps?: number }) => void
```

Fires when the user navigates between steps. Use this for custom progress indicators.

```tsx
function Verification({ token }: { token: string }) {
  const containerRef = useRef<HTMLDivElement>(null)
  const [currentStep, setCurrentStep] = useState<string>()

  usePaddleVerification({
    containerRef,
    token,
    onStepChange: ({ step, totalSteps }) => {
      setCurrentStep(step)
      console.log(`Step ${step}${totalSteps ? ` of ${totalSteps}` : ''}`)
    },
  })

  return (
    <>
      {currentStep && <p>Current step: {currentStep}</p>}
      <div ref={containerRef} />
    </>
  )
}
```

##### `onComplete`

```ts
onComplete?: (payload: { id?: string }) => void
```

Fires when the verification flow has been completed successfully. The `id` is the verification identifier. Use this to redirect the user or update your application state.

```tsx
usePaddleVerification({
  containerRef,
  token,
  onComplete: ({ id }) => {
    navigate(`/dashboard?verified=${id}`)
  },
})
```

##### `onClose`

```ts
onClose?: () => void
```

Fires when the user closes or dismisses the verification flow before completing it.

```tsx
usePaddleVerification({
  containerRef,
  token,
  onClose: () => {
    setShowVerification(false)
    toast('You can resume verification at any time.')
  },
})
```

##### `onError`

```ts
onError?: (payload: { code: string; message: string }) => void
```

Fires when an error occurs within the embed.

```tsx
usePaddleVerification({
  containerRef,
  token,
  onError: ({ code, message }) => {
    console.error(`Paddle error [${code}]: ${message}`)
    setError(`Something went wrong: ${message}`)
  },
})
```

##### `onResize`

```ts
onResize?: (payload: { height: number }) => void
```

Fires when the embedded content changes height. The iframe is automatically resized, but you can use this if you need to adjust surrounding layout.

#### Return value

The hook returns an object with a `send` method for sending messages to the iframe:

```ts
const { send } = usePaddleVerification({ ... })
```

---

### `usePaddleEmbed(options)` (advanced)

A lower-level hook for embedding any Paddle flow. Use this when you need full control over the embed path and messaging.

```tsx
import { useRef } from 'react'
import { usePaddleEmbed } from '@paddle/partner-embeds-react'

function CustomEmbed() {
  const containerRef = useRef<HTMLDivElement>(null)

  const { send } = usePaddleEmbed({
    containerRef,
    embedPath: '/embed/some-flow',
    params: { id: 'abc_123' },
    environment: 'sandbox',
    theme: { mode: 'dark' },
    onReady: () => console.log('Ready'),
    onError: ({ code, message }) => console.error(code, message),
    onResize: ({ height }) => console.log('Height:', height),
    onMessage: (msg) => console.log('Message:', msg),
  })

  return <div ref={containerRef} />
}
```

#### Options

| Option         | Type                             | Required | Description                                 |
| -------------- | -------------------------------- | -------- | ------------------------------------------- |
| `containerRef` | `RefObject<HTMLElement \| null>` | Yes      | React ref to the container element.         |
| `embedPath`    | `string`                         | Yes      | Path to the embed flow.                     |
| `params`       | `Record<string, string>`         | No       | Query parameters appended to the embed URL. |
| `environment`  | `'production' \| 'sandbox'`      | No       | Defaults to `'production'`.                 |
| `theme`        | `{ mode: 'light' \| 'dark' }`    | No       | Controls the visual theme.                  |

#### Callbacks

| Callback    | Payload                                                | Description                                     |
| ----------- | ------------------------------------------------------ | ----------------------------------------------- |
| `onReady`   | —                                                      | Fires when the iframe is loaded and ready.      |
| `onError`   | `{ code: string; message: string }`                    | Fires on errors within the embed.               |
| `onResize`  | `{ height: number }`                                   | Fires when the embedded content changes height. |
| `onMessage` | `{ type: string; version: string; payload?: unknown }` | Catch-all for any message from the iframe.      |

#### Return value

```ts
const { send } = usePaddleEmbed({ ... })

// Send a message to the embedded iframe
send({ type: 'paddle:theme', version: '1.0', payload: { mode: 'dark' } })
```

## Environments

| Environment              | Base URL                             |
| ------------------------ | ------------------------------------ |
| `'production'` (default) | `https://vendors.paddle.com`         |
| `'sandbox'`              | `https://sandbox-vendors.paddle.com` |