> 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/custom-advanced-integration.md).

# Custom/Advanced Integration

### How to Retrieve the Stripe Subscription ID from Your Backend <a href="#retrieve-subscription-id" id="retrieve-subscription-id"></a>

Most applications store the Stripe subscription ID in their own database after a successful checkout. Here are examples for different backend frameworks:

[Node.js](https://app.staysignal.com/dashboard/widget-setup/integration#nodejs)[PHP](https://app.staysignal.com/dashboard/widget-setup/integration#php)[Ruby](https://app.staysignal.com/dashboard/widget-setup/integration#ruby)[Python](https://app.staysignal.com/dashboard/widget-setup/integration#python)

#### Node.js/Express Example <a href="#nodejs" id="nodejs"></a>

```javascript
// Example: Fetching Stripe subscription ID from your database (Node.js/Express)
app.get('/account', async (req, res) => {
  // Assume you have a User model with a reference to a Subscription
  const user = await User.findById(req.user.id).populate('subscription');
  const subscriptionId = user.subscription?.stripeSubscriptionId;
  res.json({ subscriptionId });
});
```

#### PHP (Laravel) Example <a href="#php" id="php"></a>

```php
// Example: Fetching Stripe subscription ID from your database (Laravel)
public function showAccount() {
    $user = Auth::user();
    $subscription = $user->subscription;
    $subscriptionId = $subscription ? $subscription->stripe_subscription_id : null;
    return response()->json(['subscriptionId' => $subscriptionId]);
}
```

#### Ruby on Rails Example <a href="#ruby" id="ruby"></a>

```ruby
# Example: Fetching Stripe subscription ID from your database (Rails)
class AccountController < ApplicationController
  def show
    @subscription_id = current_user.subscription&.stripe_subscription_id
    render json: { subscriptionId: @subscription_id }
  end
end
```

#### Python (Django) Example <a href="#python" id="python"></a>

```python
# Example: Fetching Stripe subscription ID from your database (Django)
def account_view(request):
    subscription = Subscription.objects.filter(user=request.user).first()
    subscription_id = subscription.stripe_subscription_id if subscription else None
    return JsonResponse({'subscriptionId': subscription_id})
```

#### Fetching from Stripe API (Node.js Example)

```javascript
// Using Stripe Node.js SDK
const stripe = require('stripe')('sk_test_your_stripe_secret_key');

async function getCustomerSubscriptions(customerId) {
  try {
    const subscriptions = await stripe.subscriptions.list({
      customer: customerId,
      status: 'active',
      limit: 1
    });
    if (subscriptions.data.length > 0) {
      return subscriptions.data[0].id; // Returns the subscription ID
    }
    return null;
  } catch (error) {
    console.error('Error fetching from Stripe:', error);
    throw error;
  }
}
```

Note: Never expose your Stripe secret key in client-side code. Always fetch subscription IDs securely from your backend.

#### Opting Out of Automatic Cancellation <a href="#opt-out" id="opt-out"></a>

If you have your own cancellation flow and want to prevent Staysignal from automatically cancelling subscriptions, you can opt out in two ways:

* **Config option:** Pass `cancelOptOut: true` to the widget init config in JavaScript.
* **Button attribute:** Add `data-ss-cancel-optout="true"` to your cancel button element.

**Precedence:** If either method is set, cancellation is skipped and a message is logged to the console.

#### Advanced Flows After Cancellation <a href="#advanced-flows" id="advanced-flows"></a>

After a cancellation, you may want to trigger additional actions (e.g., send a survey, update your CRM, or notify your team). Use the `onComplete` callback in the widget config to run custom logic after a successful cancellation:

```javascript
StaySignal.init({
  siteId: 'YOUR_SITE_ID',
  onComplete: (result) => {
    // Custom logic after cancellation
    fetch('/api/notify-team', {
      method: 'POST',
      body: JSON.stringify({ subscriptionId: result.subscriptionId })
    });
  }
});
```

#### Other Advanced Options <a href="#other-options" id="other-options"></a>

* Use `onError` callback to handle errors in your own UI.
* Integrate with your analytics or logging system in `onComplete` or `onError`.
* Customize the widget appearance or behavior using additional config options (see documentation).
