Event Forwarding¶
Overview¶
The Rose widget automatically forwards analytics events to your website via the browser's postMessage API. This allows you to capture Rose interactions in your own analytics tools (Google Analytics, PostHog, Mixpanel, Segment, etc.) without any additional configuration.
This feature is enabled by default - no setup required on your end.
How It Works¶
Listening for Events¶
Add this JavaScript to your website to receive Rose events:
window.addEventListener('message', (event) => {
// Filter for Rose analytics events
if (event.data?.type === 'rose-analytics-event') {
const { eventType, category, properties, context } = event.data.payload;
console.log('Rose event:', eventType, properties);
// Forward to your analytics system
// Example: gtag('event', eventType, properties);
}
});
Event Format¶
Each event message has the following structure:
interface RoseEventMessage {
type: 'rose-analytics-event';
payload: {
eventType: string; // e.g., 'message_sent', 'cta_clicked'
category: string; // 'user_action', 'conversion', or 'system'
properties: object; // Event-specific data
context: {
sessionId: string; // Rose conversation session ID
domain: string; // Current domain
timestamp: number; // Unix timestamp (ms)
};
};
}
Event Categories¶
Events are organized into three categories:
| Category | Description | Examples |
|---|---|---|
user_action |
User interactions with the widget | Clicking, typing, hovering |
conversion |
Key conversion events | CTA clicks, form submissions |
system |
Widget lifecycle events | Widget displayed, CTA rendered |
Available Events¶
User Action Events¶
| Event | Description | Key Properties |
|---|---|---|
typed_into_input |
User typed in the input field | inputLength, isFirstInput |
message_sent |
User sent a message | messageNumber, messageLength |
mouse_hover |
User hovered over the widget | widgetState |
click_hidden_zone |
User clicked to reveal widget | clickMethod |
widget_revealed_by_scroll |
Widget revealed by scrolling | viewport_height, scroll_position |
dynamic_question_clicked |
Clicked a suggested question | questionText, language |
follow_up_question_clicked |
Clicked a follow-up question | questionText, questionIndex |
suggested_answer_clicked |
Clicked a suggested answer | answerText, answerIndex |
minimized_dynamic_questions |
Minimized the question list | isMinimized, totalQuestions |
Conversion Events¶
| Event | Description | Key Properties |
|---|---|---|
cta_clicked |
User clicked a CTA button | url, label, ctaId |
form_submitted |
Form submission detected | formId, status, detectionMethod |
cta_page_display |
User arrived at CTA destination | pageUrl, source |
System Events¶
| Event | Description | Key Properties |
|---|---|---|
widget_impression |
Widget loaded and the page was visible for 1 second | siteName |
cta_rendered |
CTA button was rendered | language, url, label |
follow_up_questions_displayed |
Follow-up questions shown | questionCount, questions |
suggested_answers_displayed |
Suggested answers shown | answerCount, answers |
Complete Example: Google Analytics 4¶
// Listen for Rose events and forward to GA4
window.addEventListener('message', (event) => {
if (event.data?.type !== 'rose-analytics-event') return;
const { eventType, category, properties, context } = event.data.payload;
// Map Rose events to GA4
gtag('event', `rose_${eventType}`, {
event_category: category,
rose_session_id: context.sessionId,
...properties
});
// Track specific conversions
if (eventType === 'cta_clicked') {
gtag('event', 'conversion', {
send_to: 'AW-XXXXXXXXXX/XXXXXXXXXXXX',
rose_session_id: context.sessionId
});
}
});
Complete Example: PostHog¶
Add this script to your site, before the Rose script so it also receives the first events:
// The Rose events to send to PostHog. Add others from the lists above if you need them.
const ROSE_EVENTS = new Set(['widget_impression', 'message_sent', 'cta_clicked', 'form_submitted']);
window.addEventListener('message', (event) => {
// Ignore messages sent by other frames on the page
if (event.source !== window || event.data?.type !== 'rose-analytics-event') return;
const { eventType, category, properties, context } = event.data.payload;
if (!ROSE_EVENTS.has(eventType)) return;
window.posthog?.capture(`rose_${eventType}`, {
...properties,
rose_category: category,
rose_session_id: context.sessionId,
rose_person_id: window.InboundXWidget?.getPersonId?.(),
});
});
Events appear in your PostHog project as rose_message_sent, rose_cta_clicked, and so on, attached to the person PostHog already tracks on your site.
- PostHog installed from npm:
window.posthogmay not exist. Callcaptureon the instance you imported instead. - Personal data in URLs: a
urlorpageUrlproperty keeps its full query string, and a CTA URL can include details collected in the chat, such as an email. Remove these properties before callingcaptureif they must not reach PostHog. - Company and person details: these events have no profile fields. The Identified accounts and Identified visitors webhooks send them with a
person_id, which is the value ofrose_person_id. - Consent: the events go to your own PostHog project, so apply the same cookie consent rules as your other PostHog events.
Security Considerations¶
- Events carry no conversation content and no profile fields, but URL properties can contain personal data (see the PostHog example)
- The
context.sessionIdallows you to correlate events with Rose conversations
Debugging¶
To see events in real-time during development:
- Open your browser's Developer Tools (F12)
- Go to the Console tab
- Add the event listener above with
console.log - Interact with the Rose widget to see events