Widget Public API¶
If you add custom code to your website, Rose exposes a small browser API on window.InboundXWidget.
You can use it to:
- check whether the widget is ready
- read Rose identity context from your own scripts
- add Rose session and visitor IDs to your own links, redirects, forms, or booking flows
- send Rose visitor IDs into tools such as HubSpot so contacts can be matched back to Rose
When to use it¶
The widget loads in the background after your page starts rendering.
If you want to read data from the widget as soon as the page loads, wait until Rose is ready:
<script>
function waitForRoseReady(callback) {
const tryAgain = () => {
if (!window.InboundXWidget) {
window.setTimeout(tryAgain, 100);
return;
}
if (window.InboundXWidget.isReady?.()) {
callback();
return;
}
if (window.InboundXWidget.onReady) {
window.InboundXWidget.onReady(callback);
return;
}
window.setTimeout(tryAgain, 100);
};
tryAgain();
}
waitForRoseReady(() => {
console.log('Rose is ready');
});
</script>
You can also check readiness manually:
This returns:
truewhen the widget is fully loadedfalsewhen it is still loading
Available methods¶
| Method | What it does | Typical use |
|---|---|---|
isReady() |
Returns true when the widget is ready |
Check whether you can safely call the API |
onReady(callback) |
Runs your callback once the widget is ready | Best option when adding custom scripts |
getIdentityContext() |
Returns all available Rose identifiers in one object | Recommended for forms, HubSpot, booking links, and redirects |
getLastActiveSessionId() |
Returns the most recent Rose session where the visitor actively engaged | Best session ID for CRM and post-chat conversion attribution |
getSessionId() |
Returns the current Rose session ID | Use only when you specifically need the current page's widget session |
getVisitorId() |
Returns Rose's visitor ID for this browser when available | Send this to HubSpot or your CRM to match contacts back to Rose visitors |
getPersonId() |
Returns the visitor's Rose person ID when available | Useful for advanced tracking |
trackFormSubmitted(data?) |
Reports a form submission to Rose (fires the conversion event) | Use when Rose cannot auto-detect your form (custom JS or single-page app) |
startPostConversionQualification(options?) |
Opens Rose's post-conversion qualification flow | Use after your own conversion success signal when Rose cannot detect it reliably |
What getIdentityContext() returns¶
{
sessionId: "sess_123",
lastActiveSessionId: "sess_123",
personId: "person_456",
visitorId: "visitor_789"
}
Some values can be null.
For example:
lastActiveSessionIdis the session ID to forward to HubSpot, booking tools, or your own CRM because it points to the last conversation where the visitor actively engagedsessionIdis the current widget session on the page. Do not use it as a fallback for CRM attribution.visitorIdidentifies the Rose visitor and is the value to ingest into HubSpot when you want to match a contact back to RosepersonIdmay still benullif Rose has not identified the visitor yet
If you are forwarding multiple values, call getIdentityContext() once. If you only need one value, use the dedicated getter.
Most common use case¶
For most integrations, collect the identity context and forward both:
rose_session_id:lastActiveSessionIdrose_visitor_id:visitorId
const identity = window.InboundXWidget?.getIdentityContext?.();
const roseSessionId = identity?.lastActiveSessionId;
const roseVisitorId = identity?.visitorId;
if (!roseSessionId) {
console.log('No active Rose conversation yet');
} else {
const rosePayload = {
rose_session_id: roseSessionId,
rose_visitor_id: roseVisitorId
};
// Add rosePayload to your CRM form, redirect, or booking link.
}
The same logic with dedicated getters looks like this:
const roseSessionId = window.InboundXWidget?.getLastActiveSessionId?.();
const roseVisitorId = window.InboundXWidget?.getVisitorId?.();
if (!roseSessionId) {
console.log('No active Rose conversation yet');
} else {
const rosePayload = {
rose_session_id: roseSessionId,
rose_visitor_id: roseVisitorId
};
// Add rosePayload to your CRM form, redirect, or booking link.
}
Use this after the widget is ready, or inside a click handler.
Example: add Rose IDs to your redirect URL¶
Here is the basic idea:
const url = new URL('https://example.com/book-demo');
const identity = window.InboundXWidget?.getIdentityContext?.();
const lastActiveSessionId = identity?.lastActiveSessionId;
const visitorId = identity?.visitorId;
if (lastActiveSessionId) {
url.searchParams.set('rose_session_id', lastActiveSessionId);
}
if (visitorId) {
url.searchParams.set('rose_visitor_id', visitorId);
}
window.location.href = url.toString();
If both IDs are available, the final URL becomes:
If the visitor has not had an active Rose conversation yet, lastActiveSessionId can be null. In that case, the redirect still works and opens without rose_session_id.
Example: add Rose IDs to hidden form fields¶
Use this pattern when your form or HubSpot form includes hidden properties for Rose data.
<input type="hidden" name="rose_session_id" id="rose-session-id" />
<input type="hidden" name="rose_visitor_id" id="rose-visitor-id" />
<script>
window.InboundXWidget?.onReady?.(() => {
const identity = window.InboundXWidget.getIdentityContext();
const lastActiveSessionId = identity.lastActiveSessionId;
const sessionInput = document.getElementById('rose-session-id');
const visitorInput = document.getElementById('rose-visitor-id');
if (lastActiveSessionId && sessionInput) {
sessionInput.value = lastActiveSessionId;
}
if (identity.visitorId && visitorInput) {
visitorInput.value = identity.visitorId;
}
});
</script>
In HubSpot, create matching contact properties such as rose_session_id and rose_visitor_id, then map your hidden fields to those properties.
Examples by platform¶
<button id="book-demo-button">Book a demo</button>
<script>
document.addEventListener('DOMContentLoaded', () => {
const button = document.getElementById('book-demo-button');
if (!button) return;
button.addEventListener('click', () => {
const url = new URL('https://example.com/book-demo');
const identity = window.InboundXWidget?.getIdentityContext?.();
const lastActiveSessionId = identity?.lastActiveSessionId;
const visitorId = identity?.visitorId;
if (lastActiveSessionId) {
url.searchParams.set('rose_session_id', lastActiveSessionId);
}
if (visitorId) {
url.searchParams.set('rose_visitor_id', visitorId);
}
window.location.href = url.toString();
});
});
</script>
import React from 'react';
export default function BookDemoButton() {
const handleClick = () => {
const url = new URL('https://example.com/book-demo');
const identity = window.InboundXWidget?.getIdentityContext?.();
const lastActiveSessionId = identity?.lastActiveSessionId;
const visitorId = identity?.visitorId;
if (lastActiveSessionId) {
url.searchParams.set('rose_session_id', lastActiveSessionId);
}
if (visitorId) {
url.searchParams.set('rose_visitor_id', visitorId);
}
window.location.href = url.toString();
};
return <button onClick={handleClick}>Book a demo</button>;
}
import * as React from 'react';
export default function BookDemoButton() {
const handleClick = () => {
const url = new URL('https://example.com/book-demo');
const identity = window.InboundXWidget?.getIdentityContext?.();
const lastActiveSessionId = identity?.lastActiveSessionId;
const visitorId = identity?.visitorId;
if (lastActiveSessionId) {
url.searchParams.set('rose_session_id', lastActiveSessionId);
}
if (visitorId) {
url.searchParams.set('rose_visitor_id', visitorId);
}
window.location.href = url.toString();
};
return (
<button
onClick={handleClick}
style={{ padding: '12px 20px', cursor: 'pointer' }}
>
Book a demo
</button>
);
}
In Framer, you can use this inside a Code Component or a custom code block.
Give your button an ID such as book-demo-button, then add this in Project Settings → Custom Code or on the page:
<script>
document.addEventListener('DOMContentLoaded', () => {
const button = document.getElementById('book-demo-button');
if (!button) return;
button.addEventListener('click', function (event) {
event.preventDefault();
const url = new URL('https://example.com/book-demo');
const identity = window.InboundXWidget?.getIdentityContext?.();
const lastActiveSessionId = identity?.lastActiveSessionId;
const visitorId = identity?.visitorId;
if (lastActiveSessionId) {
url.searchParams.set('rose_session_id', lastActiveSessionId);
}
if (visitorId) {
url.searchParams.set('rose_visitor_id', visitorId);
}
window.location.href = url.toString();
});
});
</script>
If you want to read identity context immediately on page load¶
For example, if you want to store Rose IDs in your own script before any button click, use waitForRoseReady:
<script>
function waitForRoseReady(callback) {
const tryAgain = () => {
if (!window.InboundXWidget) {
window.setTimeout(tryAgain, 100);
return;
}
if (window.InboundXWidget.isReady?.()) {
callback();
return;
}
if (window.InboundXWidget.onReady) {
window.InboundXWidget.onReady(callback);
return;
}
window.setTimeout(tryAgain, 100);
};
tryAgain();
}
waitForRoseReady(() => {
const identity = window.InboundXWidget.getIdentityContext();
const lastActiveSessionId = identity.lastActiveSessionId;
if (!lastActiveSessionId) {
console.log('No active Rose conversation yet');
return;
}
console.log('Rose last active session:', lastActiveSessionId);
console.log('Rose visitor:', identity.visitorId);
});
</script>
Report a form submission¶
Rose automatically detects most form submissions. If your form uses custom
JavaScript or a single-page app flow that Rose cannot observe, call
trackFormSubmitted() yourself when the submission succeeds. This fires the same
conversion event Rose records for auto-detected forms.
This method only reports the conversion event. To open Rose's qualification flow,
use startPostConversionQualification().
Call it from your own success handler — for example, after your form's API call returns OK:
// In your form's "submitted successfully" handler:
window.InboundXWidget?.trackFormSubmitted?.({ formId: 'demo-request' });
- All fields are optional.
trackFormSubmitted()with no arguments works. formIdis optional — pass it only if you want to tell several forms apart in analytics.- The widget loads in the background, so guard the call with
?.(oronReady). It returnsfalseand records nothing if Rose is not ready yet.
window.InboundXWidget?.onReady?.(() => {
// ... later, when the form is submitted:
window.InboundXWidget.trackFormSubmitted({ formId: 'demo-request' });
});
Prefer no-code? Use Google Tag Manager
If you manage your tags through GTM, you can fire this same conversion from a GTM tag on form submit — without editing your site code. See GTM Conversion Tracking.
Start post-conversion qualification¶
If your site already knows when a visitor has converted, call
startPostConversionQualification() from your own success handler. Rose opens
the widget and starts the configured post-conversion qualification questions.
// In your form's "submitted successfully" handler:
window.InboundXWidget?.startPostConversionQualification?.({
formId: 'demo-request',
context: {
email: 'lead@example.com',
utm_source: 'google'
}
});
formIdis optional when your Rose config has one post-conversion form. Pass it when several forms exist.contextis optional. Values are included in Rose's post-conversion completion payload asvisitor_contact.trackConversiondefaults tofalse. SettrackConversion: trueonly if you also want this call to record Rose's conversion event.- The widget loads in the background, so guard the call with
?.or run it insideonReady.
window.InboundXWidget?.onReady?.(() => {
// ... later, when your form submission succeeds:
window.InboundXWidget.startPostConversionQualification({
formId: 'demo-request',
trackConversion: true
});
});
Which method should I use?¶
| Goal | Recommended method |
|---|---|
| Wait until Rose is ready | onReady(callback) |
| Check readiness manually | isReady() |
| Add Rose IDs to HubSpot, a form, a booking link, or a redirect | getIdentityContext() |
| Get the best session ID for CRM attribution | getLastActiveSessionId() |
| Get the current page's widget session ID | getSessionId() |
| Get the Rose visitor ID for CRM matching | getVisitorId() |
| Report a form submission Rose cannot auto-detect | trackFormSubmitted(data?) |
| Start Rose qualification after a known conversion | startPostConversionQualification(options?) |
Good to know¶
- The public API is available on the top-level page where the Rose widget is installed.
- If you test inside a preview iframe, some values may be missing.
- For CRM and HubSpot ingestion, prefer
getIdentityContext()so you can sendlastActiveSessionIdandvisitorIdtogether.