The Molin AI widget notifies your website at key moments in its lifecycle. You can use these hooks to trigger custom logic such as initializing integrations, adjusting page layout, or tracking analytics.
Settings hooks (recommended)
The simplest and most reliable approach is to define callback functions directly in window.molinSettings. Because this object is defined before the widget script loads, the onReady hook is guaranteed to fire.
<script>
window.molinSettings = {
onReady: (e) => {
console.log('Widget ready:', e.widgetId);
window.Molin.openChat();
},
onChatOpen: (e) => {
console.log('Chat opened:', e.widgetId);
},
onChatClose: (e) => {
console.log('Chat closed:', e.widgetId);
},
onMessageSent: (e) => {
console.log('Message sent:', e.widgetId);
},
onLinkClick: (e) => {
console.log('Link clicked:', e.widgetId, e.url);
},
};
</script>
Available hooks
| Hook | Argument | Description |
|---|
onReady | { widgetId: string } | Called once when the widget has loaded and rendered |
onChatOpen | { widgetId: string } | Called whenever the chat window opens |
onChatClose | { widgetId: string } | Called whenever the chat window closes |
onMessageSent | { widgetId: string } | Called when the user sends a message |
onLinkClick | { widgetId: string, url: string } | Called when the user clicks a link in the chat |
Settings hooks can be combined with other molinSettings properties like hidden or userData in the same object.
Window events (alternative)
The widget also dispatches standard CustomEvent events on the window object. Use this approach if you need multiple independent listeners for the same event, or if you prefer the DOM event API.
Available events
molin:ready
Fired once when the widget has fully loaded its configuration and rendered for the first time.
window.addEventListener('molin:ready', (e) => {
console.log('Molin widget is ready:', e.detail.widgetId);
// safe to call widget methods now
window.Molin.openChat({ message: 'Welcome!' });
});
| Property | Type | Description |
|---|
e.detail.widgetId | string | The unique ID of the widget that fired |
If your script loads after the widget, the molin:ready event may have already fired. In that case, check if window.Molin already exists as a fallback:if (window.Molin) {
// widget is already ready
onMolinReady();
} else {
window.addEventListener('molin:ready', onMolinReady);
}
This race condition does not exist with the settings hooks approach above, which is why it is recommended.
molin:chat-open
Fired whenever the chat window is opened, whether by the user clicking the bubble, a popup click, the floating input, a programmatic call to openChat(), or a restored session on mobile.
window.addEventListener('molin:chat-open', (e) => {
console.log('Chat opened for widget:', e.detail.widgetId);
});
| Property | Type | Description |
|---|
e.detail.widgetId | string | The unique ID of the widget that fired |
molin:chat-close
Fired whenever the chat window is closed, whether by the user clicking the close button, toggling the bubble, or a programmatic call to closeChat().
window.addEventListener('molin:chat-close', (e) => {
console.log('Chat closed for widget:', e.detail.widgetId);
});
| Property | Type | Description |
|---|
e.detail.widgetId | string | The unique ID of the widget that fired |
molin:message-sent
Fired when the user sends a message in the chat.
window.addEventListener('molin:message-sent', (e) => {
console.log('Message sent in widget:', e.detail.widgetId);
});
| Property | Type | Description |
|---|
e.detail.widgetId | string | The unique ID of the widget that fired |
molin:link-click
Fired when the user clicks a link inside the chat conversation.
window.addEventListener('molin:link-click', (e) => {
console.log('Link clicked:', e.detail.url);
});
| Property | Type | Description |
|---|
e.detail.widgetId | string | The unique ID of the widget that fired |
e.detail.url | string | The URL of the clicked link |
Full example
<script>
function onMolinReady(e) {
console.log('Widget ready:', e.detail.widgetId);
}
if (window.Molin) {
onMolinReady({ detail: { widgetId: 'already-loaded' } });
} else {
window.addEventListener('molin:ready', onMolinReady);
}
window.addEventListener('molin:chat-open', () => {
document.body.classList.add('molin-chat-open');
});
window.addEventListener('molin:chat-close', () => {
document.body.classList.remove('molin-chat-open');
});
</script>