Cleeng Hosted Widgets: Global Communication Methods
This guide explains how Cleeng Hosted Widgets communicate with your website to share authentication state and UI events, such as checkout and payment updates.
The Cleeng script exposes a global window.cleeng object to provide communication with your website. These methods are available regardless of the widget used.
1. Example of usage
Important
- Remember that the Cleeng script should be added once to your application, in the head section.
- Methods should be called only once in the entire application, typically in a general component such as App.js.
All window.cleeng methods are available as soon as the Cleeng script is loaded. You can call them directly, as in the example below:
window.cleeng.onAuthTokensUpdate(({ jwt, refreshToken }) => {
// Called whenever tokens change (login, logout, refresh)
// jwt and refreshToken are null on logout
myApp.updateSession({ jwt, refreshToken });
});
// SSO: pass your own tokens to Cleeng widgets
// If a widget is already mounted and you need confirmation
// it processed the tokens, await the returned Promise
if (userIsLoggedIn) {
await window.cleeng.setAuthTokens({ jwt, refreshToken });
}
// Subscribe to widget events (e.g. for analytics)
window.cleeng.onWidgetEvent(({ name, data }) => {
if (name === 'payment-succeeded') {
analytics.track('Purchase', data);
}
});2. Supported Methods
onAuthTokensUpdate(callback)
onAuthTokensUpdate(callback)Use this method to keep your application's authentication state synchronized with the Cleeng widgets. This is useful when you need to:
- Know when a user logs in or out,
- Get updated tokens for making API calls,
- Check if a user is currently authenticated.
Usage:
window.cleeng.onAuthTokensUpdate(({ jwt, refreshToken }) => {
// Update your app's authentication state
if (jwt && refreshToken) {
// User is logged in - store tokens in your app
console.log('User authenticated');
} else {
// User is logged out
console.log('User logged out');
}
});Key Features:
- Automatic updates: Triggers whenever tokens change (login, logout, refresh).
- Logout detection: Both tokens become
nullwhen the user logs out or when the widget ends the session due to invalid or expired tokens.
Best Practice: Call this method once at the top level of your application (e.g., in your main app component) - calling it multiple times registers duplicate listeners, causing the callback to fire multiple times per token update.
Note: Both tokens will have their value set to null when the end user has been logged out.
logout()
logout()To ensure a consistent and secure user experience, when a user logs out from your main application, you should also programmatically log them out from the Cleeng widgets.
How it works: Call the window.cleeng.logout method. This function instructs the widgets to clear any session-related data they store. Then, if you have registered a listener via window.cleeng.onAuthTokensUpdate, your callback will be called with null as both token values.
window.cleeng.logout();setAuthTokens()
setAuthTokens()If your application uses an external identity provider, you can integrate Single Sign-On (SSO) with Cleeng’s widgets by programmatically passing authentication tokens.
After a user successfully logs in or registers through your external system, and you've generated the necessary jwt and refreshToken using Cleeng's SSO Login API endpoint, use the window.cleeng.setAuthTokens() method to authenticate the user in the widget.
This function sends the tokens to the widget and ensures that:
- The user's session is recognized across Cleeng widgets.
- The authenticated state remains synchronized when tokens are refreshed or reissued.
Call this method whenever the user's authentication state changes – the user logs in, or their tokens change (to log a user out of Cleeng widgets, use window.cleeng.logout() instead). This keeps the frontend session in sync across your application and the Cleeng widgets.
Example:
// Set authentication tokens for all widgets
window.cleeng.setAuthTokens({
jwt: 'your-jwt-token',
refreshToken: 'your-refresh-token'
});If you are updating tokens while a widget is already mounted and need to guarantee the iframe has processed them before taking the next action, make sure to await the returned Promise from setAuthTokens.
In all other cases - such as calling setAuthTokens before mounting a widget - the tokens are stored synchronously and await can be omitted.
onWidgetEvent(callback)
onWidgetEvent(callback)It is sent in various parts of the application (see the table of available UI events below).
You can subscribe to it via window.cleeng.onWidgetEvent() to respond to specific events - for example, to integrate with an analytics tool. Your callback receives two properties: name (the event type) and data (event-specific payload).
name | data | Description |
|---|---|---|
checkout-loaded | { order } | Sent when the Checkout component is loaded. The order object sent in this event represents the initial order used to open the checkout. Its data may change later, when the user applies a coupon or selects a payment method that adds additional fees. |
payment-succeeded | { payment, paymentMethod?: ’paypal’, externalPaymentId?: string } | Sent when a payment request was successful.
|
payment-failed | { error: string, code?: string, paymentMethod?: 'paypal'} | Sent when a payment request failed.
|
Examples
How to use onWidgetEvent(callback)?
window.cleeng.onWidgetEvent(({ name, data }) => {
console.log("Widget event arrived: ", {
name,
data,
});
});checkout-loaded example
{
"name": "checkout-loaded",
"data": {
"order": {
"id": 434946589,
"customerId": 996028494,
"customer": {
"locale": "pl_PL",
"email": "[email protected]"
},
"publisherId": 120355559,
"offerId": "S567921766_NL",
"offer": {
"title": "Monthly subscription (recurring) to customerName",
"description": null,
"price": 18.3636,
"currency": "EUR"
},
"totalPrice": 22.58,
"priceBreakdown": {
"offerPrice": 18.36,
"discountAmount": 0,
"discountedPrice": 18.36,
"taxValue": 4.22,
"customerServiceFee": 0,
"paymentMethodFee": 0
},
"taxRate": 0.23,
"taxBreakdown": null,
"currency": "EUR",
"country": "PL",
"paymentMethodId": 0,
"expirationDate": 1580307560,
"billingAddress": null,
"couponId": null,
"discount": {
"applied": false,
"type": "",
"periods": ""
},
"requiredPaymentDetails": true
}
}
}payment-succeeded example for Card (Adyen) payment
{
"name": "payment-succeeded",
"data": {
"payment": {
"id": 1538290265,
"orderId": 359630536,
"status": "authorized",
"totalAmount": 20.9963,
"currency": "EUR",
"customerId": 686909867,
"paymentGateway": "adyen",
"paymentMethod": "card",
"externalPaymentId": "N3MMRD2SDV5X8N82",
"couponId": null,
"amount": 16.26,
"country": "PL",
"offerType": "subscription",
"offerId": "S123456789_PL",
"taxValue": 3.74,
"paymentMethodFee": 0.81,
"customerServiceFee": 0,
"rejectedReason": null,
"refundedReason": null,
"paymentDetailsId": 208583452,
"paymentOperation": "initial-payment",
"gatewaySpecificParams": {
"merchantAccount": "CleengEUR"
}
}
}
}
payment-succeeded example for PayPal payment
{
"name": "payment-succeeded",
"data": {
"paymentMethod": "paypal",
"externalPaymentId": "N3MMRD2SDV5X8N82"
}
}payment-failed example for Card payment
{
"name": "payment-failed",
"data": {
"error": "Refused",
}
}payment-failed example for PayPal payment
{
"name": "payment-failed",
"data": {
"error": "Refusal reason", // any error message from PayPal
"paymentMethod": "paypal"
}
}FAQs
Can I use hosted customer flows solution on Smart TVs or native mobile apps?
No, it’s a solution for the web only.
Do I need to register onAuthTokensUpdate and onWidgetEvent listeners separately for each widget on the page?
No. These methods are global and apply to all widgets. They should be called once at the top level of your application - for example, in your main app component. Registering them multiple times creates duplicate listeners, causing the callback to fire multiple times per event.
How can I tell when a user has logged out via the widget?
Listen for onAuthTokensUpdate. When the user logs out, or when the widget ends the session due to invalid or expired tokens, both jwt and refreshToken are passed as null to your callback.

