Add the following code to your theme's functions.php file or use a code snippets plugin:
<?php
add_action('wp_footer', 'add_staysignal_widget_script');
function add_staysignal_widget_script() {
$site_id = 'YOUR_SITE_ID_HERE'; // Your Site ID will appear here once subscribed
// Use site_url() for potentially better results than relying on widgetUrl prop
// $widget_base_url = site_url();
$script_src = 'https://app.staysignal.com/api/widget/script/YOUR_SITE_ID_HERE'; // Escape URL just in case
// Only output script tag if site_id is valid
if (!empty($site_id) && $site_id !== 'YOUR_SITE_ID_HERE') {
?>
<script src="<?php echo esc_url('https://app.staysignal.com/api/widget/script/YOUR_SITE_ID_HERE'); ?>" async></script>
<?php
} else {
// Maybe log an error server-side if ID is missing
error_log("StaySignal Error: Site ID not configured for script loading.");
return; // Don't output init script if main script won't load
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var checkStaySignal = setInterval(function() {
if (typeof StaySignal !== 'undefined' && StaySignal.init) {
clearInterval(checkStaySignal);
StaySignal.init({
onComplete: function(payload) { /* Handle completion */ },
onError: function(error) { console.error('StaySignal Error:', error); }
}); // Escape backticks just in case
}
}, 100);
});
</script>
<?php
}
add_shortcode('staysignal_cancel_button', 'staysignal_cancel_button_shortcode');
function staysignal_cancel_button_shortcode($atts) {
$atts = shortcode_atts(array('sub_id' => '', 'text' => 'Cancel Subscription', 'class' => 'staysignal-cancel-button'), $atts, 'staysignal_cancel_button');
if (empty($atts['sub_id'])) { return '<!-- StaySignal Button: Missing subscription ID -->'; }
return '<button class="staysignal-cancel ' . esc_attr($atts['class']) . '" data-subscription_id="' . esc_attr($atts['sub_id']) . '">' . esc_html($atts['text']) . '</button>';
}
?>
Add Cancel Buttons
You can add cancel buttons to your WordPress templates or use shortcodes:
Option 1: Direct HTML in Templates
<!-- In your template file -->
<button class="staysignal-cancel" data-subscription_id="<?php echo esc_attr($subscription_id); ?>">
Cancel Subscription
</button>
Option 2: Create a Shortcode
<?php
// Add this to your functions.php
function staysignal_cancel_button_shortcode($atts) {
$atts = shortcode_atts(array(
'subscription_id' => '',
'text' => 'Cancel Subscription'
), $atts);
return sprintf(
'<button class="staysignal-cancel" data-subscription_id="%s">%s</button>',
esc_attr($atts['subscription_id']),
esc_html($atts['text'])
);
}
add_shortcode('staysignal_cancel', 'staysignal_cancel_button_shortcode');
// Usage in posts/pages:
// [staysignal_cancel subscription_id="sub_123456" text="Cancel Your Subscription"]
Error Handling
It's recommended to implement proper error handling:
<script>
// Global error handler for widget loading issues
window.onerror = function(msg, url, line, col, error) {
console.error('Widget error:', { msg, url, line, col, error });
return false;
};
// Widget-specific error handling
StaySignal.init({
// site_id is no longer needed here, it's included in the script URL
onError: (error) => {
console.error('Widget error:', error);
// Handle the error appropriately
}
});
</script>
Testing
To test your integration:
Ensure the widget script loads successfully
Check browser console for any errors
Test both class-based and JavaScript-based cancel buttons
Verify the onComplete callback is triggered
Test error scenarios by providing invalid subscription IDs
Finding Stripe Subscription IDs
Staysignal requires a subscription_id to identify which subscription a user is trying to cancel. Here are ways to find and use a user's Stripe subscription ID:
From Your Database
Most applications store subscription IDs in their database after a successful Stripe subscription creation. This is the recommended approach for performance and reliability.
<script>
// Example using Node.js with Express and MongoDB
app.get('/account', async (req, res) => {
try {
// Get user ID from session/JWT
const userId = req.user.id;
// Fetch subscription from your database
const user = await User.findById(userId).populate('subscription');
const subscriptionId = user.subscription?.stripeSubscriptionId;
res.render('account', {
user,
subscriptionId // Pass to your view
});
} catch (error) {
console.error('Error fetching subscription:', error);
res.status(500).send('Server error');
}
});
</script>
<?php
// Example using PHP with Laravel
public function showAccount()
{
$user = Auth::user();
$subscription = $user->subscription; // Assuming relationship is set up
$subscriptionId = $subscription ? $subscription->stripe_subscription_id : null;
return view('account', [
'user' => $user,
'subscriptionId' => $subscriptionId
]);
}
# Example using Ruby on Rails
class AccountController < ApplicationController
def show
@user = current_user
@subscription = @user.subscription
@subscription_id = @subscription&.stripe_subscription_id
end
end
# In your view: account.html.erb
<button class="staysignal-cancel" data-subscription_id="<%= @subscription_id %>">
Cancel Subscription
</button>
# Example using Django
def account_view(request):
user = request.user
subscription = Subscription.objects.filter(user=user).first()
subscription_id = subscription.stripe_subscription_id if subscription else None
return render(request, 'account.html', {
'user': user,
'subscription_id': subscription_id
})
Fetching from Stripe API
If you need to fetch the subscription ID directly from Stripe (not recommended for production):
<script>
// 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;
}
}
</script>
# 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
# 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
Integration with Popular Platforms
WooCommerce
<?php
// Getting subscription ID from WooCommerce Subscriptions plugin
function get_subscription_id_for_staysignal($subscription) {
$stripe_sub_id = get_post_meta($subscription->get_id(), '_stripe_subscription_id', true);
return $stripe_sub_id;
}
// Usage in template
$subscription_id = get_subscription_id_for_staysignal($subscription);
?>
WordPress - Paid Memberships Pro
<?php
// For Paid Memberships Pro
function get_pmpro_stripe_subscription_id($user_id = null) {
if (empty($user_id)) {
$user_id = get_current_user_id();
}
global $wpdb;
$subscription_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT subscr_id FROM {$wpdb->pmpro_membership_orders}
WHERE user_id = %d AND gateway = 'stripe'
ORDER BY id DESC LIMIT 1",
$user_id
)
);
return $subscription_id;
}
?>
Security Considerations
Always follow these security best practices:
Never expose your Stripe secret key in client-side code
Implement proper authentication before showing/using subscription IDs
If using the Stripe API directly, cache the results to minimize API calls
Need Help?
If you encounter any issues with the integration, please contact our support team.