Page and screen engagement
Activity or engagement tracking enables you to measure the time a user spent engaged on a page or screen, and the extent of the page or screen they viewed.
Snowplow provides implementations for web and mobile platforms:
- Page ping events on web
- Screen summary entity on mobile
Both page and screen activity tracking are included in the Snowplow Unified Digital package to calculate engagement metrics. The legacy Web package handles page pings as well.
Page engagement
Page ping events record users engaging with content on a web page after it has initially loaded. This includes scroll position.
Where activity autotracking is available, you can configure your tracker to send page ping events at regular intervals. They're considered a type of "heartbeat" event that indicates the user is still present and engaging with the page.
Page ping events are baked-in events that have no schema. They populate the page offset atomic event parameters.
This table shows the support for page ping tracking across the main client-side Snowplow tracker SDKs. Python is the only server-side tracker that provides page ping events.
| Tracker | Supported | Since version | Auto-tracking | Notes |
|---|---|---|---|---|
| Web | ✅ | 0.10.0 | ✅ | |
| iOS | ❌ | |||
| Android | ❌ | |||
| React Native | ❌ | |||
| Flutter | ✅ | 0.1.0 | ✅ | Only on web |
| Roku | ❌ | |||
| Python | ✅ | 0.8.0 | ❌ | Detect activity and track manually |
| Google Tag Manager | ✅ | v3 | ✅ |
We recommend using the Base web tracking plan template for web tracking. It includes page pings.
Screen engagement
Use screen engagement tracking to track a screen_end event when a user navigates away from a screen.
The trackers can also track a screen_summary entity that contains screen engagement data. This entity is sent along with lifecycle and screen_end events.
This table shows the support for screen engagement tracking across the main client-side Snowplow tracker SDKs. The server-side trackers don't include screen engagement tracking.
| Tracker | Supported | Since version | Auto-tracking | Notes |
|---|---|---|---|---|
| Web | ✅ | 4.2.0 | ✅/❌ | Requires screen tracking plugin |
| iOS | ✅ | 6.0.0 | ✅ | |
| Android | ✅ | 6.0.0 | ✅ | |
| React Native | ✅ | 2.1.0 | ✅ | Only on mobile |
| Flutter | ✅ | 0.1.0 | ✅ | Only on mobile |
| Roku | ❌ | |||
| Google Tag Manager | ❌ |
We recommend using the Base mobile tracking plan template for mobile tracking. It includes screen end events.
Screen end event
This event can be tracked automatically just before the transition to the next screen, based on the firing of the next screen view event. It has no properties.
screen_end
EventProperties and schema
- Table
- JSON schema
This schema has no properties.
{
"description": "Schema for an event tracked before transitioning to a new screen",
"properties": {},
"additionalProperties": false,
"type": "object",
"self": {
"vendor": "com.snowplowanalytics.mobile",
"name": "screen_end",
"format": "jsonschema",
"version": "1-0-0"
},
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#"
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_mobile_screen_end_1 screen_end_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'screen_end'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_screen_end_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'screen_end'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_screen_end_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'screen_end'
and events.event_vendor = 'com.snowplowanalytics.mobile'
and unstruct_event_com_snowplowanalytics_mobile_screen_end_1 is not null
select
"screen_end_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_mobile_screen_end_1 "screen_end_1"
on "screen_end_1".root_id = events.event_id and "screen_end_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "screen_end_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'screen_end'
and events.event_vendor = 'com.snowplowanalytics.mobile'
List item view event
Track this event to mark which items are visible in a list. When screen engagement tracking is enabled, this event won't be sent to the Collector but used to update the tracker state for the screen summary entity.
If you're using the iOS tracker with SwiftUI, you can configure it to automatically track this event.
list_item_view
EventExample
{
"index": 3,
"items_count": 10
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
indexinteger | Required. Index of the item in a list on the screen |
items_countinteger | Optional. Total number of items in a list on the screen |
{
"description": "Schema for an event tracked when an item is displayed in a list",
"properties": {
"index": {
"type": "integer",
"description": "Index of the item in a list on the screen",
"minimum": 0,
"maximum": 65535
},
"items_count": {
"type": [
"integer",
"null"
],
"description": "Total number of items in a list on the screen",
"minimum": 0,
"maximum": 65535
}
},
"additionalProperties": false,
"type": "object",
"required": [
"index"
],
"self": {
"vendor": "com.snowplowanalytics.mobile",
"name": "list_item_view",
"format": "jsonschema",
"version": "1-0-0"
},
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#"
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_mobile_list_item_view_1 list_item_view_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'list_item_view'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_list_item_view_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'list_item_view'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_list_item_view_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'list_item_view'
and events.event_vendor = 'com.snowplowanalytics.mobile'
and unstruct_event_com_snowplowanalytics_mobile_list_item_view_1 is not null
select
"list_item_view_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_mobile_list_item_view_1 "list_item_view_1"
on "list_item_view_1".root_id = events.event_id and "list_item_view_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "list_item_view_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'list_item_view'
and events.event_vendor = 'com.snowplowanalytics.mobile'
Scroll changed event
Track this event to mark changes in scroll position on a screen. When screen engagement tracking is enabled, this event won't be sent to the Collector but used to update the tracker state for the screen summary entity.
scroll_changed
EventExample
{
"x_offset": 0,
"y_offset": 250,
"view_width": 375,
"view_height": 667,
"content_width": 375,
"content_height": 1500
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
x_offsetinteger | Optional. Horizontal scroll offset in pixels |
y_offsetinteger | Optional. Vertical scroll offset in pixels |
view_widthinteger | Optional. The width of the scroll view in pixels |
view_heightinteger | Optional. The height of the scroll view in pixels |
content_widthinteger | Optional. The width of the content in the scroll view in pixels |
content_heightinteger | Optional. The height of the content in the scroll view in pixels |
{
"description": "Schema for an event tracked when a scroll view's scroll position changes",
"properties": {
"x_offset": {
"type": [
"integer",
"null"
],
"description": "Horizontal scroll offset in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"y_offset": {
"type": [
"integer",
"null"
],
"description": "Vertical scroll offset in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"view_width": {
"type": [
"integer",
"null"
],
"description": "The width of the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
},
"view_height": {
"type": [
"integer",
"null"
],
"description": "The height of the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
},
"content_width": {
"type": [
"integer",
"null"
],
"description": "The width of the content in the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
},
"content_height": {
"type": [
"integer",
"null"
],
"description": "The height of the content in the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
}
},
"additionalProperties": false,
"type": "object",
"self": {
"vendor": "com.snowplowanalytics.mobile",
"name": "scroll_changed",
"format": "jsonschema",
"version": "1-0-0"
},
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#"
}
Warehouse query
- Snowflake
- BigQuery
- Databricks
- Redshift & Postgres
select
unstruct_event_com_snowplowanalytics_mobile_scroll_changed_1 scroll_changed_1
from
atomic.events
where
events.collector_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'scroll_changed'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_scroll_changed_1_0_0
from
PIPELINE_NAME.events events
where
events.collector_tstamp > timestamp_sub(current_timestamp(), interval 1 hour)
and events.event = 'unstruct'
and events.event_name = 'scroll_changed'
and events.event_vendor = 'com.snowplowanalytics.mobile'
select
unstruct_event_com_snowplowanalytics_mobile_scroll_changed_1
from
atomic.events events
where
events.collector_tstamp > timestampadd(HOUR, -1, current_timestamp())
and events.event = 'unstruct'
and events.event_name = 'scroll_changed'
and events.event_vendor = 'com.snowplowanalytics.mobile'
and unstruct_event_com_snowplowanalytics_mobile_scroll_changed_1 is not null
select
"scroll_changed_1".*
from
atomic.events events
join atomic.com_snowplowanalytics_mobile_scroll_changed_1 "scroll_changed_1"
on "scroll_changed_1".root_id = events.event_id and "scroll_changed_1".root_tstamp = events.collector_tstamp
where
events.collector_tstamp > getdate() - interval '1 hour'
and "scroll_changed_1".root_tstamp > getdate() - interval '1 hour'
and events.event = 'unstruct'
and events.event_name = 'scroll_changed'
and events.event_vendor = 'com.snowplowanalytics.mobile'
Screen summary entity
Entity that contains screen engagement information, including how long a user spends on a screen in the foreground and background, as well as information about scroll depth and list items.
The entity data is based on tracker state captured from lifecycle, list item view, and scroll changed events.
screen_summary
EntityExample
{
"foreground_sec": 10.2,
"background_sec": 3.1,
"last_item_index": 11,
"items_count": 50,
"min_x_offset": 0,
"max_x_offset": 400,
"min_y_offset": 0,
"max_y_offset": 1000,
"content_width": 400,
"content_height": 5000
}
Properties and schema
- Table
- JSON schema
| Property | Description |
|---|---|
foreground_secnumber | Required. Time in seconds spent on the current screen while the app was in foreground |
background_secnumber | Optional. Time in seconds spent on the current screen while the app was in background |
last_item_indexinteger | Optional. Index of the last viewed item in the list on the screen |
items_countinteger | Optional. Total number of items in the list on the screen |
min_x_offsetinteger | Optional. Minimum horizontal scroll offset on the scroll view in pixels |
max_x_offsetinteger | Optional. Maximum horizontal scroll offset on the scroll view in pixels |
min_y_offsetinteger | Optional. Minimum vertical scroll offset on the scroll view in pixels |
max_y_offsetinteger | Optional. Maximum vertical scroll offset on the scroll view in pixels |
content_widthinteger | Optional. Width of the scroll view in pixels |
content_heightinteger | Optional. Height of the scroll view in pixels |
{
"description": "Schema for an entity tracked with foreground/background/screen_end events with summary statistics about the screen view",
"properties": {
"foreground_sec": {
"type": "number",
"description": "Time in seconds spent on the current screen while the app was in foreground",
"minimum": 0,
"maximum": 2147483647
},
"background_sec": {
"type": [
"number",
"null"
],
"description": "Time in seconds spent on the current screen while the app was in background",
"minimum": 0,
"maximum": 2147483647
},
"last_item_index": {
"type": [
"integer",
"null"
],
"description": "Index of the last viewed item in the list on the screen",
"minimum": 0,
"maximum": 65535
},
"items_count": {
"type": [
"integer",
"null"
],
"description": "Total number of items in the list on the screen",
"minimum": 0,
"maximum": 65535
},
"min_x_offset": {
"type": [
"integer",
"null"
],
"description": "Minimum horizontal scroll offset on the scroll view in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"max_x_offset": {
"type": [
"integer",
"null"
],
"description": "Maximum horizontal scroll offset on the scroll view in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"min_y_offset": {
"type": [
"integer",
"null"
],
"description": "Minimum vertical scroll offset on the scroll view in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"max_y_offset": {
"type": [
"integer",
"null"
],
"description": "Maximum vertical scroll offset on the scroll view in pixels",
"minimum": -2147483647,
"maximum": 2147483647
},
"content_width": {
"type": [
"integer",
"null"
],
"description": "Width of the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
},
"content_height": {
"type": [
"integer",
"null"
],
"description": "Height of the scroll view in pixels",
"minimum": 0,
"maximum": 2147483647
}
},
"additionalProperties": false,
"type": "object",
"required": [
"foreground_sec"
],
"self": {
"vendor": "com.snowplowanalytics.mobile",
"name": "screen_summary",
"format": "jsonschema",
"version": "1-0-0"
},
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#"
}