> For the complete documentation index, see [llms.txt](https://staysignal.gitbook.io/staysignal-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://staysignal.gitbook.io/staysignal-docs/integration-guides/react-integration.md).

# React integration

### React Integration

Follow these steps to integrate the Staysignal widget into your React application:

#### 1. Create a Widget Component

This component loads the widget script using your Site ID (from the URL) and handles initialization.

```typescript

import { useEffect } from 'react';

interface StaySignalWidgetProps {
  onComplete?: (payload: any) => void;
  onError?: (error: any) => void;
}

declare global {
  interface Window { StaySignal: any; }
}

export function StaySignalWidget({ onComplete, onError }: StaySignalWidgetProps) {

  useEffect(() => {
    const scriptId = 'staysignal-widget-script';
    if (document.getElementById(scriptId)) return;

    const script = document.createElement('script');
    script.id = scriptId;
    script.src = '/api/widget/script/YOUR_SITE_ID_HERE'; // Use the new script URL
    script.async = true;

    script.onload = () => {
      if (!window.StaySignal) {
        console.error("StaySignal object not found after script load.");
        onError?.(new Error("StaySignal failed to initialize."));
        return;
      }
      window.StaySignal.init({
        // site_id is included in the script URL
        onComplete: (payload: any) => { onComplete?.(payload); },
        onError: (error: any) => { onError?.(error); }
      });
      window.StaySignal.onReady(() => { /* Widget Core Ready */ });
    };

    script.onerror = () => { onError?.(new Error("Failed to load StaySignal script.")); };

    document.body.appendChild(script);

    return () => {
      const existingScript = document.getElementById(scriptId);
      if (existingScript) {
        document.body.removeChild(existingScript);
      }
    };
  }, [onComplete, onError]); // Adjust dependencies

  return null; // Component doesn't render anything itself
}
```

#### 2. Create a Cancel Button Component

```typescript
// components/CancelButton.tsx
import { useEffect, useRef } from 'react';

interface CancelButtonProps {
  subscriptionId: string;
  className?: string;
  children?: React.ReactNode;
}

export function CancelButton({ subscriptionId, className = '', children }: CancelButtonProps) {
  const buttonRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    const button = buttonRef.current;
    if (!button) return;

    // Add required attributes
    button.classList.add('staysignal-cancel');
    button.setAttribute('data-subscription_id', subscriptionId);

    return () => {
      button.classList.remove('staysignal-cancel');
      button.removeAttribute('data-subscription_id');
    };
  }, [subscriptionId]);

  return (
    <button ref={buttonRef} className={className}>
      {children || 'Cancel Subscription'}
    </button>
  );
}
```

#### 3. Use the Components

[Learn how to retrieve the correct subscription ID](https://app.gitbook.com/o/L1J4IXndMOL7SI7HjRkS/s/vYa98TfDh2GiMvr5EyYo/~/changes/10/basics/integrations/finding-stripe-subscription-ids)

###

{% tabs %}
{% tab title="PHP" %}

```php
<?php
// Using Stripe PHP SDK
require_once 'vendor/autoload.php';
StripeStripe::setApiKey('sk_test_your_stripe_secret_key');

function getCustomerSubscriptions($customerId) {
    try {
        $subscriptions = StripeSubscription::all([
            'customer' => $customerId,
            'status' => 'active',
            'limit' => 1
        ]);
        
        if (count($subscriptions->data) > 0) {
            return $subscriptions->data[0]->id;
        }
        return null;
    } catch (Exception $e) {
        error_log('Stripe API Error: ' . $e->getMessage());
        return null;
    }
}
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
# Using Stripe Ruby SDK
require 'stripe'
Stripe.api_key = 'sk_test_your_stripe_secret_key'

def get_customer_subscriptions(customer_id)
  begin
    subscriptions = Stripe::Subscription.list(
      customer: customer_id,
      status: 'active',
      limit: 1
    )
    
    return subscriptions.data.first&.id
  rescue Stripe::StripeError => e
    Rails.logger.error("Stripe API Error: #{e.message}")
    return nil
  end
end
```

{% endtab %}

{% tab title="Python" %}

```python
# Using Stripe Python SDK
import stripe
stripe.api_key = "sk_test_your_stripe_secret_key"

def get_customer_subscriptions(customer_id):
    try:
        subscriptions = stripe.Subscription.list(
            customer=customer_id,
            status='active',
            limit=1
        )
        
        if subscriptions.data:
            return subscriptions.data[0].id
        return None
    except stripe.error.StripeError as e:
        print(f"Stripe API Error: {e}")
        return None
```

{% endtab %}
{% endtabs %}

### Need Help?

If you encounter any issues with the integration, please contact our support team.
