npm package: @retainme/widget
Description: Official React SDK for Retain.io - Collect feedback, bug reports, testimonials, and prevent churn
Author: RetainMe.io
Latest version: 3.0.1

# @retainme/widget

Official React SDK for [Retain.io](https://retainme.io) - Collect feedback, bug reports, testimonials, and prevent customer churn.

## Installation

```bash
npm install @retainme/widget
# or
yarn add @retainme/widget
# or
pnpm add @retainme/widget
```

## Quick Start

### 1. Wrap your app with RetainProvider

```tsx
import { RetainProvider } from '@retainme/widget'

function App() {
  return (
    <RetainProvider
      config={{
        apiKey: 'pk_live_YOUR_API_KEY_HERE',
      }}
    >
      <YourApp />
    </RetainProvider>
  )
}
```

## Features


### 🎨 Display Testimonials on Your Site

Show your collected testimonials beautifully on your website using the same design as the Retain.io embed widget:

#### Basic Usage

```tsx
import { Testimonials } from '@retainme/widget'

function TestimonialsPage() {
  return (
    <Testimonials
      apiKey="pk_live_YOUR_API_KEY"
    />
  )
}
```

### 💰 Churn Prevention

Prevent customer churn with intelligent retention flows using your configured churn flows:

```tsx
import { useChurnFlow } from '@retainme/widget'

function CancelSubscriptionPage() {
  // Uses VITE_API_URL env var by default, or pass apiUrl to override
  const { startFlow, isLoaded } = useChurnFlow()

  const handleCancel = async () => {
    const result = await startFlow({
      stripeSubscriptionId: 'sub_123',
      projectId: 'your_api_key_here',
      email: 'user_churning_email'
      onComplete: (result) => {
        if (result === 'kept') {
          console.log('User kept subscription!')
        } else {
          console.log('User cancelled subscription')
        }
      },
    })
  }

  return (
    <button onClick={handleCancel} disabled={!isLoaded}>
      Cancel Subscription
    </button>
  )
}
```

This loads your existing `/retainme-churn.js` script with your configured flows.

## Advanced Usage

### Access Widget Instance Directly

```tsx
import { useRetain } from '@retainme/widget'

function MyComponent() {
  const { widget, isLoaded, error } = useRetain()

  if (error) {
    return <div>Failed to load Retain.io widget</div>
  }

  if (!isLoaded) {
    return <div>Loading...</div>
  }

  // Access widget methods directly
  const handleClick = () => {
    widget?.open()
  }

  return <button onClick={handleClick}>Feedback</button>
}
```

## Examples

### Next.js App Router

```tsx
// app/layout.tsx
import { RetainProvider } from '@retainme/widget'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <RetainProvider
          config={{
            apiKey: "your_key_here",
          }}
        >
          {children}
        </RetainProvider>
      </body>
    </html>
  )
}
```

### Next.js Pages Router

```tsx
// pages/_app.tsx
import { RetainProvider } from '@retainme/widget'

export default function App({ Component, pageProps }) {
  return (
    <RetainProvider
      config={{
        apiKey: "your_key_here",
      }}
    >
      <Component {...pageProps} />
    </RetainProvider>
  )
}
```

### Vite/Create React App

```tsx
// src/main.tsx or src/index.tsx
import { RetainProvider } from '@retainme/widget'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <RetainProvider
      config={{
        apiKey: "your_key_here",
      }}
    >
      <App />
    </RetainProvider>
  </React.StrictMode>
)
```



## License

MIT