# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://staysignal.gitbook.io/staysignal-docs/integration-guides/react-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
