Skip to main content

Auto events

For additional information, please also refer to documentation of configSet(autoEventsConfig:) method, pa_autoEventDataSource instance property, which conforms to the AutoTrackableEventDataSource protocol. For container views such as UITableViewController and UICollectionView, there is a pa_itemsViewDataSource instance property, which conforms to the ItemsViewDataSource protocol.

Overview

Pulse SDK provides a way to automatically generate events when certain predefined actions occur. Auto events use swizzling under the hood and need to be explicitly enabled first. They only work with UIKit, and SwiftUI is not supported. Similar functionality in SwiftUI can be achieved using custom view modifiers, which must be explicitly applied to the views you want to track.

By default, most auto-events that describe the user's journey across the application are disabled to support the best app performance and network traffic consumption. To configure auto-event tracking granularly, call the configSet(autoEventsConfig:) method and pass a list of the auto-event types you'd like to enable. Each of this types is related to specific UIKit controls and user interactions. Below is an overview of the supported events and their corresponding types used to enable them.

auto-eventtriggercorresponding type of PAAutoEventType
clickUIButton is clicked.buttonClick
clickUISlider is clicked.sliderControlClick
clickUISwitch is clicked.switchControlClick
clickUIStepper is clicked.stepperControlClick
clickUISegmentedControl is clicked.segmentedControlClick
clickUIBarButtonItem is clicked.barButtonClick
clickUITableViewCell is clicked.tableViewClick
clickUICollectionViewCell is clicked.collectionViewClick
page_loadUIViewController is loaded ("viewDidLoad()" is called).viewController
page_viewUIViewController appeared ("viewWillAppear(:)" is called).viewController
items_impressionUITableViewCell was visible for given amount of time.tableViewImpression
items_impressionUICollectionViewCell was visible for given amount of time.collectionViewImpression
scrollUIScrollView was scrolled.scroll
gestureUIGestureRecognizer was fired.gesture
revenue_xxxSpecific StoreKit revenue-related transaction is occurring.revenueTracking
Keep in mind

To maintain a clean auto-events sequence and avoid irrelevant events, the Pulse SDK excludes the following classes from page_load and page_view events:

  • UINavigationController
  • UITabBarController
  • UIPageViewController
  • UISplitViewController

This exclusion also applies to their subclasses.

Code sample for enabling auto-events:

let config = PAAutoEventsConfig()
config.addType(.viewController)
config.addType(.buttonClick)
PAAnalytics.configSet(autoEventsConfig: config)

or

let config = PAAutoEventsConfig(autoEventTypes:
[
.viewController,
.buttonClick,
.barButtonClick,
.collectionViewClick
]
)
PAAnalytics.configSet(autoEventsConfig: config)
Danger Zone

Note: Once auto-events are enabled via the configSet(autoEventsConfig:) method, they cannot be disabled during the current session. This limitation ensures the integrity of the swizzled call chain and helps prevent potential runtime issues.

Keep in mind

If you configure auto-events at app startup, it allows the SDK to begin recording the user journey as early as possible, providing better insights into user behavior.

General auto event contents

Auto events contain a number of predefined and automatically populated fields in the data section of the event. Here's an overview:

field nametypeoptionalcorresponding UIKit property
element.valueStringyestitle/image
element.idStringyespa_autoEventDataSource
element.typeStringno-
element.sequence 1)Intyes-
element.accessibility_idStringyesaccessibilityIdentifier
sources_info[[String: String]]no-
parent_info 2)[String: String]yes- 3)
previous_events[String]no-
additional_properties[String: Any]yespa_autoEventDataSource
additional_ids[String: Any]yespa_autoEventDataSource
groupStringyespa_autoEventDataSource
sectionStringyespa_autoEventDataSource

1) only in page_view
2) not included in page_load or page_view events
3) you can influence parent_info content indirectly by changing parent's of elementName property if AutoTrackableEventData object that is retrieved by pa_autoEventDataSource

Keep in mind

The Pulse Analytics SDK includes the public optional delegate property pa_autoEventDataSource for the following classes::

  • UIView
  • UIViewController
  • UIBarButtonItem
  • UIGestureRecognizer

The pa_autoEventDataSource property references a class that conforms to the AutoTrackableEventDataSource protocol. It is assigned to supply real-time data for any trackable UIKit element, provided that this delegate has been set for the specific instance of the UIKit element. When the SDK determines that the conditions for tracking a specific auto-event are met, it requests the delegate to provide a populated AutoTrackableEventData object that contains contextual information about the particular element.

element

element field contains information about the element that generates the event: a button, a collection view cell, a view controller, etc. It contains multiple subfields that describe the properties of the element.

field nameoptionaldescription
valueyesContains the value of the element, such as its title or image name in the case of a button, title in the case of the view controller, first found label in the case of UITableView/UICollectionViewCell, etc.
idyesContains custom name (identifier) of the element via the AutoTrackableEventData.elementName property
typenoDescribes the type of the element that generated the event. Can be one of these values: button, toggle, slider, stepper, segment, bar_button, collection_view_cell, table_view_cell, scroll_view.
sequenceyesThe number of times this view controller appeared.
accessibility_idyesContains the value of the element's accessibilityIdentifier property.

sources_info

sources_info field contains an array of dictionaries, each of which contains information about previously visited view controllers. It can be used to trace the user's journey leading to the current screen. Each item in the array contains the following subfields:

field nameoptionaldescription
classnoContains class name of the view controller
idyesContains custom name (identifier) of the view controller
accessibility_idyesContains accessibility ID of the view controller

sources_info contains up to three past screens. Screens are added to the array in order of appearance, meaning the last item in the array is the one that was shown most recently.

parent_info

parent_info contains information about the element's parent view controller.

field nameoptionaldescription
classnoContains class name of the view controller
idyesContains custom name (identifier) of the view controller
accessibility_idyesContains accessibility ID of the view controller

previous_events

previous_events contains IDs of up to 10 previous events.

additional_properties

additional_properties contains key-value pairs provided to the element via the AutoTrackableEventData.additionalProperties property.

additional_ids

additional_ids contains key-value pairs provided to the element via the AutoTrackableEventData.additionalIDs property.

group and section

Groups and sections are means of grouping elements together. Set AutoTrackableEventData.trackingGroup or AutoTrackableEventData.trackingSection in autoTrackEventData(for:) delegate method for a given view, and all of its containing elements that can generate auto events will contain the assigned values in their respective group and section fields.

sub_sids

Optional sub_sids parameter contains a dictionary where keys are custom IDs and values are view controller class names that exist in the hierarchy. This dictionary allows inspection of the view controller navigation path, describing the user's journey to the touchpoint where the event occurred.

Specialized contents

items_impression

items_count

items_count field contains the number of items counted as seen and contained in the params field.

params

params field contains information about each individual seen item.

gesture

The JSON schema of gesture event contains unique gesture_params parameter that may have different members depending of gesture recogniser type

gesture_params

gesture_params field contains information about the performed gesture. The internal mandatory type field indicates the type of gesture recognizer and the corresponding JSON schema structure.

gesture_params for UITapGestureRecognizer
field nametypeoptionaldescription
tap_xIntyesHorizontal coordinate of tap
tap_yIntyesVertical coordinate of tap
taps_countIntyesNumber of fingers required to match
typeStringno"tap"
gesture_params for UILongPressGestureRecognizer
field nametypeoptionaldescription
tap_xIntyesHorizontal coordinate of tap
tap_yIntyesVertical coordinate of tap
taps_countIntyesNumber of fingers required to match
typeStringno"long_press"
gesture_params for UIPinchGestureRecognizer
field nametypeoptionaldescription
scale_startIntyesStart value of pinch gesture recognizer in percentage
scale_endIntyesFinal value of pinch gesture recognizer in percentage
scale_valueIntyesAccumulated scale change in percentage
typeStringno"scale"
gesture_params for UIRotationGestureRecognizer
field nametypeoptionaldescription
rotate_startIntyesStart value of rotation gesture recognizer in degrees
rotate_endIntyesFinal value of rotation gesture recognizer in degrees
rotate_valueIntyesAccumulated rotation change in degrees
typeStringno"rotate"
gesture_params for UIPanGestureRecognizer
field nametypeoptionaldescription
move_start_xIntyesHorizontal coordinate before finger moving
move_start_yIntyesVertical coordinate before finger moving
move_end_xIntyesHorizontal coordinate after finger moving
move_end_yIntyesVertical coordinate after finger moving
move_distance_xIntyesDistance between move_end_x and move_start_x in pixels
move_distance_yIntyesDistance between move_end_y and move_start_y in pixels
typeStringno"move"

scroll

The JSON schema of the scroll event contains a unique scroll_info parameter that is included regardless of the scroll direction, whether horizontal or vertical.

scroll_info

scroll_info field contains information about the performed scroll.

field nametypeoptionaldescription
distanceIntnoScrolling distance in pixels
speedIntnoScrolling speed (pixels per second)
directionStringnoScrolling direction ("up", "down", "left", "right")
scroll_depthIntnoVisible percentage of scrolling
start_positionIntnoStart position before scrolling (content offset)
end_positionIntnoFinal position after scrolling (content offset)
durationIntnoScrolling duration in milliseconds

General customization

Auto events will contain as much useful info as our SDK can gather by itself, but if you'd like to have some control over the data, auto events can be customized in a few ways. This section discusses customization options available for all of the auto events.

Opt behavior

After enabling certain types of auto events, all objects of that class will generate those events when the trigger is met. All instances of classes that have their auto events enabled are opted in by default. If you'd like to change that, use the pa_optBehavior property on the appropriate class:

UIButton.pa_optBehavior = .autoOptOut
UIScrollView.pa_optBehavior = .autoOptOut
Keep in mind

The pa_autoEventDataSource optional delegate can be assigned to any view controller, view, or UI element. This delegate refers to an instance conforming to the AutoTrackableEventDataSource protocol, and it is used to provide additional information about the element generating the event. Additional details can be supplied by implementing the optional delegate method:

func autoTrackEventData(for element: AutoTrackableElement) -> AutoTrackableEventData?

This method, defined in the AutoTrackableEventDataSource protocol, enables you to pass relevant event data for enhanced tracking capabilities.

You can enable or disable event generation on a per-instance basis by implementing of func shouldAutoTrack(for element: AutoTrackableElement) -> Bool optional delegate method by pa_autoEventDataSource instance.

@MainActor
extension ABCDController: AutoTrackableEventDataSource {
func shouldAutoTrack(for element: AutoTrackableElement) -> Bool {
false
}
}

Identifying the element

Use AutoTrackableEventData.elementName to give elements a unique identifier that helps you identify events from specific objects. The element name will be included in the element.name field of the event.

@MainActor
extension ABCDController: AutoTrackableEventDataSource {
func autoTrackEventData(for element: AutoTrackableElement) -> AutoTrackableEventData? {
if let cell = element as? UICollectionViewCell {
if let indexPath = collectionView.indexPath(for: cell) {
let item = items[indexPath.row]
let data = AutoTrackableEventData(elementName: item.name)
print("Ask data for collection view cell with indexPath: \(indexPath)")
return data
} else {
print("Can't resolve indexPath of `AutoTrackableElement` collection view cell")
}
} else {
print("Ask data for other view: \(NSStringFromClass(type(of: element))) ")
}
return nil
}
}

Adding custom fields to the event

To add more data to the auto event, use the AutoTrackableEventData.additionalProperties and AutoTrackableEventData.additionalIDs properties that might be set by func autoTrackEventData(for element: AutoTrackableElement) -> AutoTrackableEventData? method.

@MainActor
extension ABCDController: AutoTrackableEventDataSource {
func autoTrackEventData(for element: AutoTrackableElement) -> AutoTrackableEventData? {
if let button = element as? MyLoginButton {
let params = ["username": "john-doe"]
let ids = ["sid": "e0182f1b-41e4-41aa-a30a-f19cfce0bd39"]
let data = AutoTrackableEventData(elementName: "login_button_signup", additionalProperties: params, additionalIDs: ids)
return data
}
return nil
}
}

Key-value pairs passed in the dictionaries will be added to the data.additional_properties and data.additional_ids fields of the auto event, respectively.

Detailed customization

Certain auto events have additional customization options due to their specific nature. This section discusses these additional options.

click localized string reverse lookup

click auto events include the button's title or asset name (if the button contains an image instead of text). This can be problematic for apps supporting multiple languages, as the same button could be "Si", "Ja", or "Yes" depending on the language. To mitigate this, you can set a custom AutoTrackableEventData.elementName or accessibilityIdentifier, or enable reverse string lookup to automate unique button identification.

Our SDK can track resolved localized strings and their keys in a reverse lookup table. This ensures that regardless of the resolved, localized string, the event includes the localized key used for resolving that string.

To enable this feature, call Bundle.enableLocalizedStringSwizzling(). As a result, the element field will contain an additional localized_key field:

"element": {
"localized_key": "universal.save",
"value": "Speichern",
"type": "button"
}

items_impression

The items_impression event is generated by any UITableView and UICollectionView instance. It contains data about items visible for more than 3 seconds and with over 50% visible area. Items are collected while the collection view or table view is visible and the event is closed when the collection view disappears (e.g., navigating to another screen or the app entering the background).

Our analytics SDK can only capture the index path of visible items, which is not very useful by itself. To properly populate the event with data, we introduced the ItemsViewDataProvider protocol. The collection view (table view) requests data about items at specific index paths (similar to UICollectionViewDataSource and collectionView(_:cellForItemAt:)). To provide items_impression data, assign the pa_itemsViewDataSource property of the collection view and implement ItemsViewDataSource methods, for example:

extension MyCollectionViewController: ItemsViewDataSource {
// global event data contained in root of `data` field
func eventData() -> [String: Any]? {
["sid": self.sessionID]
}

// per item data
func itemData(for indexPath: IndexPath) -> [String: Any]? {
guard let item = items[indexPath.row] else {
return nil
}

var data: [String: Any] = [:]
data["id"] = item.id
data["name"] = item.name

return data
}
}

Examples of events

page_load

{
"event_type": "page_load",
"event_id": "307CBBE7-8A92-4856-97AB-8F7CC10E4B22",
"timestamp": 1722336443065,
"sub_sids": {
"PAHomeViewController": "C2446833-4351-405B-A02F-CA463D648BA0"
},
"is_background": false,
"data": {
"metadata": {
"auto_generated": true,
"event_id_source": "sdk"
},
"connection_type": "WIFI",
"element": {
"class": "PADetailViewController",
"id": "Detail",
"type": "controller"
},
"previous_events": [
"EB66B7A8-8F25-450E-9A56-996C58779BBD",
"42012EEE-28F9-481F-8646-CCA5FB5CBC13",
"B3613147-D129-40A0-A407-9F1EEE910436",
"C0EE4335-C250-418B-963B-5030411DCB26"
],
"sources_info": [
{
"class": "PAHomeViewController",
"id": "Home"
}
]
}
}

page_view

{
"event_type": "page_view",
"event_id": "29FA66EC-D92E-4ED6-9CCA-BE93100FAEAD",
"timestamp": 1722336443122,
"is_background": false,
"sub_sids": {
"PAHomeViewController": "C2446833-4351-405B-A02F-CA463D648BA0",
"PADetailViewController": "70952851-2932-4BFF-A1DE-98A2345F1F3A"
},
"data": {
"metadata": {
"event_id_source": "sdk",
"auto_generated": true
},
"connection_type": "WIFI",
"element": {
"class": "PAProfileViewController",
"id": "Profile",
"type": "controller",
"sequence": 2
},
"previous_events": [
"42012EEE-28F9-481F-8646-CCA5FB5CBC13",
"B3613147-D129-40A0-A407-9F1EEE910436",
"C0EE4335-C250-418B-963B-5030411DCB26",
"51ED3F3D-20BD-4056-86EA-6E7466A5E998",
"22C85D49-CCB1-444B-B8B2-61458C74C2C7",
"B48AD8B9-1096-4F82-A808-AC390705A7B6",
"307CBBE7-8A92-4856-97AB-8F7CC10E4B22"
],
"sources_info": [
{
"class": "PAHomeViewController",
"id": "Home"
},
{
"class": "PADetailViewController",
"id": "Detail"
}
]
}
}

click

{
"event_type": "click",
"event_id": "FD8AF18C-B0EA-430A-A701-A7E7243FACA4",
"timestamp": 1722330200930,
"is_background": false,
"sub_sids": {
"PAHomeViewController": "3DD731ED-0F72-4847-BA08-1D4343E76D15"
},
"data": {
"metadata": {
"event_id_source": "sdk",
"auto_generated": true
},
"connection_type": "WIFI",
"element": {
"type": "button",
"value": "Speichern",
"localized_key": "universal.save"
},
"parent_info": {
"class": "PAHomeViewController"
},
"previous_events": [
"4EE35B59-078A-4B70-B3B6-EDF468561C1A",
"AA3EFA00-1FFA-4804-9DB9-E6C891BD7399",
"FE8830FD-E720-4E09-9C01-6440092C66F9"
],
"sources_info": [],
}
}

items_impression

{
"event_type": "items_impression",
"event_id": "F3D7D292-0180-4A1F-8BDE-047CD5C52542",
"timestamp": 1722351318853,
"is_background": false,
"sub_sids": {
"PAHomeViewController": "013CEE0A-7F71-43F0-ACFE-1E4CE8B7620E",
"PASimpleCollectionViewController": "49703FFD-C43A-4695-9EE1-E7C671211C5E"
},
"data": {
"metadata": {
"auto_generated": true,
"event_id_source": "sdk"
},
"connection_type": "WIFI",
"element": {
"type": "collection_view_cell"
},
"items_count": 8,
"params": [
{
"id": "83204de9",
"view_time": 4,
"name": "item 3",
"timestamp": 1722351315226
},
{
"id": "7ecd1b15",
"name": "item 6",
"timestamp": 1722351315226,
"view_time": 4
},
{
"id": "1b050eac",
"timestamp": 1722351315226,
"view_time": 4,
"name": "item 5"
},
{
"timestamp": 1722351315226,
"name": "item 4",
"view_time": 4,
"id": "6cc0d7ff"
},
{
"view_time": 4,
"name": "item 1",
"id": "a531edcc",
"timestamp": 1722351315226
},
{
"id": "b546f395",
"view_time": 4,
"timestamp": 1722351315226,
"name": "item 2"
},
{
"view_time": 4,
"id": "077fd072",
"name": "item 0",
"timestamp": 1722351315226
},
{
"view_time": 4,
"timestamp": 1722351315226,
"name": "item 7",
"id": "fd6426c3"
}
],
"parent_info": {
"class": "PASimpleCollectionViewController"
},
"previous_events": [
"44509F2A-1D13-435A-943F-8F6798116FEF",
"41E5961F-97A0-4B2C-AB65-4C450799DC6C",
"DE04BC5B-F750-4A46-8B68-A790C26D6712",
"12CF5246-97FD-40C2-B831-092BD4EADDF6"
],
"sources_info": [
{
"class": "PAHomeViewController",
"id": "Home"
},
{
"class": "PASimpleCollectionViewController"
}
]
}
}

scroll

{
"event_type": "scroll",
"event_id": "AD9DD603-0CD0-4E58-9831-19F609DA6DF6",
"timestamp": 1722348525771,
"is_background": false,
"sub_sids": {
"PAHomeViewController": "4A29E66E-12EB-42DB-BCD2-E708ED19BE4E"
},
"data": {
"metadata": {
"event_id_source": "sdk",
"auto_generated": true
},
"connection_type": "WIFI",
"element": {
"type": "scroll_view"
},
"parent_info": {
"class": "PAHomeViewController",
"id": "Home"
},
"previous_events": [
"FB155738-B97A-4E95-A95B-5CE044D37FE3",
"2BF72AAF-906B-4207-9581-11C4641AEA1D",
"D0880F56-514E-4DBE-A460-AA8D6C3E0EF7"
],
"sources_info": [],
"scroll_info": {
"distance": 36,
"speed": 73,
"direction": "up",
"scroll_depth": 27,
"end_position": 36,
"start_position": 0,
"duration": 487
}
}
}

gesture

{
"event_type": "gesture",
"event_id": "7749CD2D-8309-47D2-9448-2FD9089A099F",
"timestamp": 1722350412882,
"is_background": false,
"sub_sids": {
"settings": "A0095D03-5DD6-4FBA-8925-42B2C893F9D4",
"PAHomeViewController": "802D7F69-E2EB-4F76-98BF-7696EB18D913"
},
"data": {
"metadata": {
"event_id_source": "sdk",
"auto_generated": true
},
"connection_type": "WIFI",
"previous_events": [
"AEB4421F-3627-4D6B-AC7E-44090CF4DD9D",
"8335E620-3ABE-4238-ACD2-132DA59E94BB",
"6206B02C-87AF-424C-BF76-FB4270DF8FCE",
"A0E3B9F1-11B1-4313-97D6-F3C74BA54A2A"
],
"sources_info": [
{
"id": "Home",
"class": "PAHomeViewController"
},
{
"class": "PAProfileViewController",
"id": "Profile"
}
],
"parent_info": {
"id": "Settings",
"class": "PASettingsViewController"
},
"gesture_params": {
"tap_x": 185,
"type": "tap",
"tap_y": 376,
"taps_count": 1
},
"target_info": {
"class": "UIView"
},
}
}