Analytics
Listen to Analytics
Analytics page
All analytics events are automatically sent to our servers. You can find various statistics and analysis of your widgets on your Analytics page on Studio.
You can also retrieve them for your own analytics. There are several ways to listen to analytics events depending on the way you integrated your widget.
Default integration
After integrating the widget on your website page, you can listen to JOIN_ANALYTICS
global event like this :
document.addEventListener("JOIN_ANALYTICS", function(event) {
// analytics payload is available in `detail` field of the event.
console.log(event.detail.cpWidgetAlias)
})
See native documentation for more informations about native event listeners.
See Easy integration without npm (recommended) for more informations.
Standalone widget
When instanciating the standalone widget, you can pass a function that will be called each time an event is triggered. Like this:
function analyticsCallback(payload) {
// Do something with the payload...
console.log(payload.cpWidgetAlias)
}
const customPlayer = new JoinModalPlayer('my-widget', { analyticsCallback })
See Standalone Widget for more informations.
NPM Package
When calling renderListBubble
, you can pass a function that will be called each time an event is triggered. Like this:
function analyticsCallback(payload) {
// Do something with the payload...
console.log(payload.cpWidgetAlias)
}
renderBubbleList(
"uniqueDivId",
"teamId",
"aliasWidget",
{ analyticsCallback },
);
See NPM Package for more informations on how to use it.
Analytics events
During its life on a website (or mobile), a widget can trigger various analytics events. There are events related to the widget itself and events related to the stories inside of it. They track how the users interact with the widget and its content.
Analytics v2
A new Analytics stack has been implemented. Old events have been renamed, with more properties. New events have been added. They are split by categories. Each category has its own properties.
Category : Story
Event Name | Trigger Scenario |
---|---|
story-chapter-view | A chapter of the story become active: Opening a player, Change of story (swipe,…), Change of chapter, Coming back to a tab with a story opened ... |
story-first-chapter-view | The first chapter of the story becomes active. |
story-last-chapter-view | The last chapter of the story becomes active. |
story-chapter-exit | The active chapter exits either manually or automatically. |
story-view | A story become active: Opening a player, Change of story (swipe,…), Coming back to a tab with a story opened ... |
story-exit | The active story exits, either manually or automatically. |
story-completed | The last chapter of the story is fully read or ends due to a tap to next. |
story-tap-next | User taps to next on a story. |
story-tap-previous | User taps to previous on a story. |
story-swipe-next | User swipes to the right or clicks on the next story button. |
story-swipe-previous | User swipes to the left or clicks on the previous story button. |
story-pause | Long press on mobile or on click of the pause button on desktop. |
story-unpause | Long press is released on mobile or on click of the play button on desktop. |
story-mute | Click on mute button. |
story-unmute | Click on unmute button. |
Category : Interaction
Event Name | Trigger Scenario |
---|---|
interaction-view | An interaction becomes active (displayed/viewed) in an active story. |
interaction-completed | User completes an interaction. It must be triggered only once. |
interaction-engage | User executes an action on an interaction (e.g., form -> fill fields, tooltip click, CTA click). |
interaction-exit | The interaction becomes inactive (from an active state). |
Category : Widget
Event Name | Trigger Scenario |
---|---|
widget-initialized | The widget has finished initialization before loading data. In case of changing audiences, it is not re-initialized. |
widget-data-loaded | The widget loads data (from internal JSON, API fetch, cache, or fallback). |
widget-displayed | The widget is inserted in the page and displayed or ready to be displayed. |
widget-thumbnail-ready | All thumbnails of visible elements of the widget are loaded. |
widget-view-50 | At least 50% of the widget’s height is visible (in the viewport and not obstructed by another element on top of it). |
widget-view-75 | At least 75% of the widget’s height is visible(in the viewport and not obstructed by another element on top of it). |
widget-view-100 | 100% of the widget’s height is visible (in the viewport and not obstructed by another element on top of it). |
widget-click | User clicks on a widget. |
widget-player-close | The player is closed (e.g., swipe down, tap next when no story, or programmatically). |
widget-scrolled | User scrolls (mobile) or clicks on an arrow (desktop) to see next stories. |
widget-close | The widget is closed in certain cases (e.g., sticky widget). |
Category : Product
Event Name | Trigger Scenario |
---|---|
product-loaded | Product has been loaded in shopping interaction |
product-view | Product has been seen by user |
product-details-view | Product details panel has been seen by user |
product-engage | User has engaged with product (click, add to cart, redirect to product page) |
Category : External
Event Name | Trigger Scenario |
---|---|
page-loaded | Website page is loaded. User arrived on the website but the content is not visible yet. |
page-view | Website page is viewed. Everything is done loading, user can browse the website |
page-exit | User exited the website. It can also be triggered when user changes tab in his browser. |
product-add-to-cart | A product is added to cart either from the website or from a story directly |
cart-sell | Triggered at sell confirmation |
product-sell | Triggered at sell confirmation for each product in the cart |
page-engage | Triggered when a visitor of a webpage engages with the page (click or others actions) |
Properties
All events have at least the common properties. Each category has its own properties.
Common properties
Name | Type | Description |
---|---|---|
event_id | string | Event technical Id |
event_category | string | story, widget, product, … |
event_type | string | Event name. See above for a list of event names |
event_version | string | Event analytics version. (Should be v2) |
event_date_timezone | number | Timezone of the visitor triggering the event. Number in minutes from UTC |
event_date_creation | timestamp | Timestamp (in s) the event was created client side. |
event_owner | string | JOIN owner |
event_user_id | string | Anonymous user id to monitor sessions |
event_device_screen_width | number | |
event_device_screen_height | number | |
event_device_screen_color | number | |
event_device_screen_ratio | number | |
event_device_pixel_ratio | number | |
event_device_network_type | string | Wi-Fi, cellular, bluetooth, ethernet, unknown |
event_device_network_effective_type | string | Wi-Fi, 4G, 5G, Ethernet, unknown |
event_device_orientation | string | portrait, landscape |
event_device_battery_level | number | battery level. Between 0 and 1 |
event_integration_environment | string | app , web , other , unknown |
event_integration_location_name | string | Contains both url or app information |
event_integration_web_protocol | string | |
event_integration_web_title | string | |
event_integration_web_base_url | string | URL that only contains protocol+domain+path |
event_integration_web_url | string | |
event_integration_web_domain | string | |
event_integration_web_path | string | |
event_integration_web_parameters | string | |
event_integration_web_anchor | string | |
event_integration_web_referrer | string | |
event_integration_web_percent_scrolled | number | Ratio of page scrolled when the event was triggered. between 0 and 1. |
event_integration_web_browser_name | string | Browser name |
event_integration_web_browser_version | string | Browser version |
event_integration_web_browser_language | string | Browser preferred language |
event_integration_web_browser_language_locale | string | |
event_integration_web_browser_viewport_width | number | browser's viewport width (in px) |
event_integration_web_browser_viewport_height | number | browser's viewport height (in px) |
event_page_tag | string | Page load ID reset on each new page reload |
Story properties
Name | Type | Description |
---|---|---|
story_id | string | Story technical id |
story_title | string | Story's title |
story_label | string | Story's displayed label (may be different from title) |
story_last_published_date | timestamp | Last published date of the story |
story_has_subtitles | boolean | Wether story has subtitles or not |
story_has_interactions | boolean | Wether story has interactions or not |
story_has_sound | boolean | If at least one chapter has sound on a story, then yes |
story_chapter_count | number | Total count of chapters |
story_interaction_count | number | Total count of interactions on the story |
story_duration | number | Total duration of a story (in ms) |
story_chapter_index | number | The index of the chapter responsible for sending the event. Indexes start at 0 |
story_chapter_duration | number | Total duration of the chapter |
story_previous_chapter_index | number | The index of the previous chapter |
story_index_in_widget | number | Index of the story in the list of stories. Indexes start at 0. |
story_muted | boolean | Is Story muted by the user |
story_displayed_format | string | mobile / desktop - We can have a mobile format for displaying a story even on desktop (ex: sticky) |
story_completion | number | Ratio of completion between 0 and 1 |
story_chapter_completion | number | Ratio of completion between 0 and 1 |
story_viewing_time | number | Duration in ms |
story_chapter_viewing_time | number | Duration in ms |
story_is_active | boolean | Property that should always be true for now, but can be used to dissociate events in the future |
story_chapter_is_active | boolean | Property that should always be true for now, but can be used to dissociate events in the future |
story_exit_reason | string | Enum: swipeDown, swipeNext, swipePrevious, tapNext, tapPrevious, closeButton, ctaClick, autoAdvance |
story_chapter_exit_reason | string | Enum: swipeDown, swipeNext, swipePrevious, tapNext, tapPrevious, closeButton, ctaClick, autoAdvance |
story_pause_duration | number | Duration in ms |
story_version | string | Story's technical version. |
Interaction properties
Name | Type | Description |
---|---|---|
interaction_id | string | Interaction technical Id |
interaction_type | string | Interaction type (CTA, Quiz, Shopping, ...) |
interaction_engage_type | string | redirect | form-input-focus | form-input-change | form-submit | poll-clicked | quiz-click | open-product-config | continue-shopping |
interaction_engage_value_1 | string | First generic value |
interaction_engage_value_2 | string | Second generic value |
interaction_engage_url | string | Only used in case of CTA (replacing value 1-2) |
interaction_engage_label | string | Only used in case of CTA (replacing value 1-2) |
interaction_engaging_time | number | Time between first interactionEngage and interactionEngageComplete or interactionExit |
interaction_viewing_time | number | Time between interactionView and interactionExit |
interaction_has_been_blocking | boolean | In case the interaction has blocked the auto-advance in the chapter/story, waiting for an engagement |
interaction_is_already_completed | boolean | true if it was already completed when the interaction became active |
interaction_is_first_engage | boolean | interaction-engage event is the first engagement of the page. |
interaction_is_story_first_engage | boolean | interaction-engage event is the first engagement of the story. |
interaction_is_completion_engage | boolean | The event is the one that has completed the interaction. |
interaction_exit_state | string | completed |canceled : engaged at least once |ignored : exited interaction without engage |already-completed |
Widget properties
Name | Type | Description |
---|---|---|
widget_id | string | Widget technical id |
widget_alias | string | Widget alias |
widget_type | string | Widget type (list, sdk, qr-code, link) |
widget_shape | string | (Only applies for type list) Widget shape (bubble, card, square) |
widget_layout | string | Widget layout (list, solo-sticky, none) |
widget_integration_type | string | snippet, npm, sdk, generic, shopifyPlugin, … |
widget_integration_relative_position | number | Ratio between the widget position on the page and the page height. Between 0 and 1. |
widget_integration_position | number | Position from the top of the page (in px) |
widget_story_count | number | Number of stories in the widget, after widget-data-loaded (with audience conditions applied) |
widget_duration_displayed | number | Duration (in ms) since widget is displayed, starting at widget_display event |
widget_click_count | number | Number of clicks on the widget since it has been displayed, also to set for all story events |
widget_player_close_reason | string | close-button | background | auto-advance | swipe-down | tap-next |
widget_close_reason | string | close reason (manual or auto ) |
widget_version | string | Widget version |
widget_audience_slots_matched | array | For every widget event except widget initialized, and also for stories when available |
widget_page_scroll_occurred | boolean | Permits to know if the user has scrolled on the page before an event |
widget_visible_duration_threshold | number | Used in the event widgetView100Extended, to know the threshold of visibility |
widget_is_scrollable | boolean | According to integration, if the widget is too large to be displayed fully and is made scrollable |
widget_scroll_type | string | natural/button – to know in case of widgetScroll event, if the scroll is from button or natural gesture |
widget_data_loading_time | number | Duration of the data loading (from API) if instant if coming from JSON = null |
widget_data_loaded_source | string | The source from where the data has been loaded (from API, embedded-data, cache, fallback, ...) |
widget_video_cover_count | number | Count of the number of video covers |
widget_static_cover_count | number | Count of the number of static covers |
widget_element_height | number | Height of the widget (element not full bloc) configured in the studio (or in app) in px |
Product properties
Name | Type | Description |
---|---|---|
product_id | string | ID of the product variation |
product_name | string | Product name |
product_image_url | string | Product image url |
product_thumbnail_url | string | Product thumbnail url |
product_variant | string | Product variant |
product_engage_type | string | |
product_engage_value_1 | string | First generic value |
product_engage_value_2 | string | Second generic value |
product_engage_url | string | URL that the product CTA redirects to |
product_engage_label | string | Label of the CTA used |
product_is_first_engage | boolean | product-engage event is the first engagement. |
product_is_completion_engage | boolean | The event is the one that has completed the product interaction |
product_price | number | Product price |
product_base_price | number | Product base price |
product_final_price | number | Product final price |
product_quantity | number | Product quantity |
External properties
ℹ️ Event product-add-to-cart
has all product properties. See above for the list.
Name | Type | Description |
---|---|---|
page_engage_type | click | scroll | when page-engage is triggered.Type of user engagement. |
page_viewing_time | number | when page-exit is triggered.time (in ms) user spent on the page. |
transaction_id | string | when cart-sell is triggered.unique id to identify product sell |
total_base_amount | number | when cart-sell is triggered.total amount of cart. |
total_final_amount | number | when cart-sell is triggered.total amount of cart after discount or other. |
product_count | number | when cart-sell is triggered.number of products in the cart |
product_ids | string[] | when cart-sell is triggered.List of product ids |
currency | string | when cart-sell is triggered.currency of the cart products |
Analytics v1 (Legacy)
Deprecation notice
v1 events are considered deprecated and will be removed in the future. Don't use them for your new developments.
Check name in V2 column to see how to find old events in new Analytics.
List of event types
Here the list of all available events. There are 2 types of events with different payloads.
EventType | Type of payload | Description | name in V2 |
---|---|---|---|
widgetMounted | widget | Triggers when the widget is mounted. | widget-initialized |
storiesFetched | widget | Triggers when the stories are fetched. | widget-data-loaded |
componentVisible50 | widget | Triggers when the widget is 50% visible. | widget-view-50 |
componentVisible75 | widget | Triggers when the widget is 75% visible. | widget-view-75 |
firstClickOnWidget | widget | Triggers the first time a story is opened (with a click on a widget) during a visit on a page. | widget-click (with property widget_click_count = 1) |
additionalClickOnWidget | widget | Triggers every other times a story is opened during a visit on a page. | widget-click (with property widget_click_count > 1) |
closed | widget | Triggers when a sticky widget is closed. | widget-close |
storyPageVisible | story | Triggers when the current story changes page. | story-view |
storyLastPageVisible | story | Triggers when the last page of a story is viewed. | story-last-chapter-view |
storyClickOnCallToAction | story | Triggers when a cta button is clicked in a story. | interaction-engage (with property engage-type = 'cta') |
storyClickOnLinkInPage | story | Triggers when a link is clicked inside a shopping interaction. | interaction-engage (with property engage-type = 'shopping') |
Widget Event payload
The widget events share the following payload:
Name | Type | Description |
---|---|---|
eventType | string | Event's type. See up for the full list. |
eventOwner | string | JOIN identifier of the customer. |
cpWidgetAlias | string | alias of the widget. |
cpWidgetType | string | widget's type. |
cpWidgetVersion | string | widget's version. |
eventWidgetWorkspaces | string[] | legacy information. For newer client, it should always be ["ws_default"] . |
date | number | event's time. |
eventCategory | widget | event was triggered by the widget itself or by one of its stories. Here it will always be widget . |
cpTitle | string | title of website that triggered the event. |
eventUrl | string | url of website that triggered the event. |
cpBaseUrl | string | domain name of website that triggered the event. |
cpScreenResolution | string | browser's resolution. |
cpScreenColor | number | Colors depth of browser. See native documentation . |
cpBrowserLanguage | string | browser's language. |
cpUserAgent | string | browser's user agent. See native documentation |
hit | boolean | whether analytics were enabled or not. |
Story event payload
The story events share the following payload :
Name | Type | Description |
---|---|---|
eventType | string | Event's type. See above for the full list. |
eventOwner | string | JOIN identifier of the customer. |
storyWorkspace | string | legacy information. For newer client, it should always be ws_default . |
storySlug | string | always web-story-slug . |
storyId | string | Story's id. |
storyPageCount | number | number of pages in the Story. |
storyPageEngagementCount | number | number of pages with a cta button. |
cpIndex | number | story's index inside the widget. |
date | number | event's time. |
eventCategory | story | event was triggered by the widget itself or by one of its stories. Here it will always be story . |
cpTitle | string | always web-story-title . |
eventUrl | string | url of website that triggered the event. |
cpScreenResolution | string | browser's resolution. |
cpScreenColor | number | Colors depth of browser. See native documentation . |
cpBrowserLanguage | string | browser's language. |
cpUserAgent | string | browser's user agent. See native documentation |
cpDocumentReferrer | string | It is either web-list-bubble or web-solo-sticky depending on the widget's type. |
hit | boolean | whether analytics were enabled or not. |
Event example
Here a widget payload:
{
"eventOwner": "join-stories",
"cpWidgetAlias": "inspiration-galerie-audiences",
"cpWidgetType": "list-bubble",
"cpWidgetVersion": "4",
"eventWidgetWorkspaces": [
"ws_default"
],
"date": 1722852202110,
"eventCategory": "widget",
"cpTitle": "My website",
"eventUrl": "https://example.join-stories.com/my-widget",
"cpBaseUrl": "https://example.join-stories.com/my-widget",
"cpScreenResolution": "1512x982",
"cpScreenColor": 30,
"cpBrowserLanguage": "en",
"cpUserAgent": "mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/127.0.0.0 safari/537.36",
"hit": true,
"eventType": "componentVisible50"
}
And a story payload:
{
"storyPageCount": 20,
"storyPageEngagementCount": 0,
"eventOwner": "join-stories",
"storyId": "7ec2ad55-d37c-42e3-ac4b-3b0d000e1042",
"storySlug": "web-story-slug",
"storyWorkspace": "ws_default",
"date": 1722852299269,
"eventCategory": "story",
"cpTitle": "web-story-title",
"eventUrl": "https://example.join-stories.com/my-widget",
"cpDocumentReferrer": "web-list-bubble",
"cpScreenResolution": "1512x982",
"cpScreenColor": 30,
"cpBrowserLanguage": "en",
"cpUserAgent": "mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/127.0.0.0 safari/537.36",
"hit": true,
"cpIndex": 0,
"eventType": "storyPageVisible"
}
Updated 8 days ago