mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-28 04:06:57 +02:00
Add support for UserProperties to analytics and capture FTUE use case selection.
Additionally update taps to interactions following updates in the analytics event repo.
This commit is contained in:
@@ -108,6 +108,7 @@ import AnalyticsEvents
|
||||
!RiotSettings.shared.isIdentifiedForAnalytics
|
||||
else { return }
|
||||
|
||||
let userProperties = makeUserProperties(for: session)
|
||||
let service = AnalyticsService(session: session)
|
||||
self.service = service
|
||||
|
||||
@@ -116,7 +117,7 @@ import AnalyticsEvents
|
||||
|
||||
switch result {
|
||||
case .success(let settings):
|
||||
self.identify(with: settings)
|
||||
self.identify(with: settings, and: userProperties)
|
||||
self.service = nil
|
||||
case .failure:
|
||||
MXLog.error("[Analytics] Failed to use analytics settings. Will continue to run without analytics ID.")
|
||||
@@ -149,17 +150,30 @@ import AnalyticsEvents
|
||||
|
||||
/// Identify (pseudonymously) any future events with the ID from the analytics account data settings.
|
||||
/// - Parameter settings: The settings to use for identification. The ID must be set *before* calling this method.
|
||||
private func identify(with settings: AnalyticsSettings) {
|
||||
/// - Parameter userProperties: Any user properties that should be set for creating cohorts etc.
|
||||
private func identify(with settings: AnalyticsSettings, and userProperties: AnalyticsEvent.UserProperties) {
|
||||
guard let id = settings.id else {
|
||||
MXLog.error("[Analytics] identify(with:) called before an ID has been generated.")
|
||||
return
|
||||
}
|
||||
|
||||
client.identify(id: id)
|
||||
client.identify(id: id, userProperties: userProperties)
|
||||
MXLog.debug("[Analytics] Identified.")
|
||||
RiotSettings.shared.isIdentifiedForAnalytics = true
|
||||
}
|
||||
|
||||
/// Returns the user properties for use when identifying a session.
|
||||
/// - Parameter session: The session to gather any user properties from.
|
||||
/// - Returns: The properties to be set.
|
||||
private func makeUserProperties(for session: MXSession) -> AnalyticsEvent.UserProperties {
|
||||
var useCaseSelection: AnalyticsEvent.UserProperties.FtueUseCaseSelection?
|
||||
if let userId = session.credentials.userId, let userSession = UserSessionsService.shared.userSession(withUserId: userId) {
|
||||
useCaseSelection = userSession.userProperties.useCase?.analyticsName
|
||||
}
|
||||
|
||||
return AnalyticsEvent.UserProperties(ftueUseCaseSelection: useCaseSelection, numSpaces: nil)
|
||||
}
|
||||
|
||||
/// Capture an event in the `client`.
|
||||
/// - Parameter event: The event to capture.
|
||||
private func capture(event: AnalyticsEventProtocol) {
|
||||
@@ -171,6 +185,14 @@ import AnalyticsEvents
|
||||
// The following methods are exposed for compatibility with Objective-C as
|
||||
// the `capture` method and the generated events cannot be bridged from Swift.
|
||||
extension Analytics {
|
||||
/// Updates any user properties to help with creating cohorts.
|
||||
///
|
||||
/// Only non-nil properties will be updated when calling this method.
|
||||
func updateUserProperties(ftueUseCase: UserSessionProperties.UseCase? = nil) {
|
||||
let userProperties = AnalyticsEvent.UserProperties(ftueUseCaseSelection: ftueUseCase?.analyticsName, numSpaces: nil)
|
||||
client.updateUserProperties(userProperties)
|
||||
}
|
||||
|
||||
/// Track the presentation of a screen
|
||||
/// - Parameters:
|
||||
/// - screen: The screen that was shown.
|
||||
@@ -186,20 +208,21 @@ extension Analytics {
|
||||
trackScreen(screen, duration: nil)
|
||||
}
|
||||
|
||||
/// Track an element that has been tapped
|
||||
/// Track an element that has been interacted with
|
||||
/// - Parameters:
|
||||
/// - tap: The element that was tapped
|
||||
/// - uiElement: The element that was interacted with
|
||||
/// - interactionType: The way in with the element was interacted with
|
||||
/// - index: The index of the element, if it's in a list of elements
|
||||
func trackTap(_ tap: AnalyticsUIElement, index: Int?) {
|
||||
let event = AnalyticsEvent.Click(index: index, name: tap.elementName)
|
||||
func trackInteraction(_ uiElement: AnalyticsUIElement, interactionType: AnalyticsEvent.Interaction.InteractionType, index: Int?) {
|
||||
let event = AnalyticsEvent.Interaction(index: index, interactionType: interactionType, name: uiElement.name)
|
||||
client.capture(event)
|
||||
}
|
||||
|
||||
/// Track an element that has been tapped without including an index
|
||||
/// - Parameters:
|
||||
/// - tap: The element that was tapped
|
||||
func trackTap(_ tap: AnalyticsUIElement) {
|
||||
trackTap(tap, index: nil)
|
||||
/// - uiElement: The element that was tapped
|
||||
func trackInteraction(_ uiElement: AnalyticsUIElement) {
|
||||
trackInteraction(uiElement, interactionType: .Touch, index: nil)
|
||||
}
|
||||
|
||||
/// Track an E2EE error that occurred
|
||||
|
||||
@@ -26,7 +26,10 @@ protocol AnalyticsClientProtocol {
|
||||
|
||||
/// Associate the client with an ID. This is persisted until `reset` is called.
|
||||
/// - Parameter id: The ID to associate with the user.
|
||||
func identify(id: String)
|
||||
/// - Parameter userProperties: Any user properties that should be included.
|
||||
///
|
||||
/// Only non-nil user properties will be updated when calling this method.
|
||||
func identify(id: String, userProperties: AnalyticsEvent.UserProperties)
|
||||
|
||||
/// Reset all stored properties and any event queues on the client. Note that
|
||||
/// the client will remain active, but in a fresh unidentified state.
|
||||
@@ -45,4 +48,10 @@ protocol AnalyticsClientProtocol {
|
||||
/// Capture the supplied analytics screen event.
|
||||
/// - Parameter event: The screen event to capture.
|
||||
func screen(_ event: AnalyticsScreenProtocol)
|
||||
|
||||
/// Updates any user properties to help with creating cohorts.
|
||||
/// - Parameter userProperties: The user properties to be updated.
|
||||
///
|
||||
/// Only non-nil properties will be updated when calling this method.
|
||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ import Foundation
|
||||
import AnalyticsEvents
|
||||
|
||||
@objc enum AnalyticsScreen: Int {
|
||||
case welcome
|
||||
case login
|
||||
case register
|
||||
case forgotPassword
|
||||
case sidebar
|
||||
case home
|
||||
case favourites
|
||||
@@ -51,6 +55,14 @@ import AnalyticsEvents
|
||||
/// The screen name reported to the AnalyticsEvent.
|
||||
var screenName: AnalyticsEvent.Screen.ScreenName {
|
||||
switch self {
|
||||
case .welcome:
|
||||
return .Welcome
|
||||
case .login:
|
||||
return .Login
|
||||
case .register:
|
||||
return .Register
|
||||
case .forgotPassword:
|
||||
return .ForgotPassword
|
||||
case .sidebar:
|
||||
return .MobileSidebar
|
||||
case .home:
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
|
||||
import AnalyticsEvents
|
||||
|
||||
/// A tappable UI element that can be track in Analytics.
|
||||
/// A tappable UI element that can be tracked in Analytics.
|
||||
@objc enum AnalyticsUIElement: Int {
|
||||
case sendMessageButton
|
||||
case removeMe
|
||||
|
||||
/// The element name reported to the AnalyticsEvent.
|
||||
var elementName: AnalyticsEvent.Click.Name {
|
||||
var name: AnalyticsEvent.Interaction.Name {
|
||||
switch self {
|
||||
// Note: This is a test element that doesn't need to be captured.
|
||||
// It will likely be removed when the AnalyticsEvent.Click is updated.
|
||||
case .sendMessageButton:
|
||||
return .SendMessageButton
|
||||
// It can be removed when some elements are added that relate to mobile.
|
||||
case .removeMe:
|
||||
return .WebRoomSettingsLeaveButton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AnalyticsEvents
|
||||
|
||||
extension UserSessionProperties.UseCase {
|
||||
var analyticsName: AnalyticsEvent.UserProperties.FtueUseCaseSelection {
|
||||
switch self {
|
||||
case .personalMessaging:
|
||||
return .PersonalMessaging
|
||||
case .workMessaging:
|
||||
return .WorkMessaging
|
||||
case .communityMessaging:
|
||||
return .CommunityMessaging
|
||||
case .skipped:
|
||||
return .Skip
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,9 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
||||
postHog?.enable()
|
||||
}
|
||||
|
||||
func identify(id: String) {
|
||||
postHog?.identify(id)
|
||||
func identify(id: String, userProperties: AnalyticsEvent.UserProperties) {
|
||||
// As user properties overwrite old ones, compactMap the dictionary to avoid resetting any missing properties
|
||||
postHog?.identify(id, properties: userProperties.properties.compactMapValues { $0 })
|
||||
}
|
||||
|
||||
func reset() {
|
||||
@@ -62,4 +63,8 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
||||
postHog?.screen(event.screenName.rawValue, properties: event.properties)
|
||||
}
|
||||
|
||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) {
|
||||
// As user properties overwrite old ones via $set, compactMap the dictionary to avoid resetting any missing properties
|
||||
postHog?.capture("$identify", properties: ["$set": userProperties.properties.compactMapValues { $0 }])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user