diff --git a/kmp/shared-core/spm/Sources/SharedCoreKit/AnalyticsEvents.swift b/kmp/shared-core/spm/Sources/SharedCoreKit/AnalyticsEvents.swift index b406d34184..cf3c54da3a 100644 --- a/kmp/shared-core/spm/Sources/SharedCoreKit/AnalyticsEvents.swift +++ b/kmp/shared-core/spm/Sources/SharedCoreKit/AnalyticsEvents.swift @@ -26,6 +26,9 @@ public typealias GroupInviteMethod = SharedCore.GroupInviteMethod public typealias GroupInviteSource = SharedCore.GroupInviteSource public typealias GroupAccess = SharedCore.GroupAccess public typealias GroupGateFunding = SharedCore.GroupGateFunding +public typealias ProfileField = SharedCore.ProfileField +public typealias ProfileMenuAction = SharedCore.ProfileMenuAction +public typealias ProfilePinnedAction = SharedCore.ProfilePinnedAction public typealias AnalyticsButton = SharedCore.Button public typealias AnalyticsAmount = SharedCore.Amount public typealias PeopleCounter = SharedCore.PeopleCounter @@ -45,6 +48,7 @@ public typealias ErrorModalEvents = SharedCore.ErrorModalEvents public typealias AccountEvents = SharedCore.AccountEvents public typealias ButtonEvents = SharedCore.ButtonEvents public typealias GroupEvents = SharedCore.GroupEvents +public typealias ProfileEvents = SharedCore.ProfileEvents /// A property value as the iOS sender needs it. Mixpanel is not a dependency of this /// package, so the app maps these to `MixpanelType` itself. diff --git a/libs/analytics-events/EVENTS.md b/libs/analytics-events/EVENTS.md index 3a31fc9d72..ef6246508b 100644 --- a/libs/analytics-events/EVENTS.md +++ b/libs/analytics-events/EVENTS.md @@ -506,6 +506,56 @@ No properties. No properties. +## Profile + +### Profile: Settings Viewed + +The Settings screen opened. + +No properties. + +### Profile: Edit Profile Viewed + +The Edit Profile screen opened. + +No properties. + +### Profile: Field Saved + +A profile field was saved. + +| Property | Type | Optional | Values | +|---|---|---|---| +| Field | list | no | [ProfileField](#profilefield) | + +### Profile: Bio Moderation Failed + +A bio was rejected by moderation. + +No properties. + +### Profile: Menu Action + +An action was picked from another user's profile menu. + +| Property | Type | Optional | Values | +|---|---|---|---| +| Action | list | no | [ProfileMenuAction](#profilemenuaction) | + +### Profile: Pinned Button Tapped + +The pinned button on another user's profile was tapped. + +| Property | Type | Optional | Values | +|---|---|---|---| +| Action | list | no | [ProfilePinnedAction](#profilepinnedaction) | + +### Profile: Card Shown + +A profile card was shown. + +No properties. + ## Button ### Button: {button} @@ -574,6 +624,7 @@ The `Source` property on Add Money: Opened: where the user opened Add Money from | Chat | `CHAT` | | | Scanner | `SCANNER` | | | Balance | `BALANCE` | | +| Profile | `PROFILE` | | ### AddMoneyMethod @@ -704,6 +755,40 @@ The `Source` property on the Display Name events: the screen the name was set on | My Account | `MY_ACCOUNT` | | | Tip Card Setup | `TIP_CARD_SETUP` | | +### ProfileField + +The `Field` property on Profile: Field Saved: the profile field that was saved. + +| Value sent | Name in code | Drift | +|---|---|---| +| Name | `NAME` | | +| Username | `USERNAME` | | +| Photo | `PHOTO` | | +| Cover | `COVER` | | +| Bio | `BIO` | | +| Minimum | `MINIMUM` | | + +### ProfileMenuAction + +The `Action` property on Profile: Menu Action: the action picked from another user's profile menu. + +| Value sent | Name in code | Drift | +|---|---|---| +| Mute | `MUTE` | | +| Report | `REPORT` | | +| Block | `BLOCK` | | +| Unblock | `UNBLOCK` | | + +### ProfilePinnedAction + +The `Action` property on Profile: Pinned Button Tapped: what the profile's pinned button does. + +| Value sent | Name in code | Drift | +|---|---|---| +| Start Chatting | `START_CHATTING` | | +| Open Chat | `OPEN_CHAT` | | +| Unblock | `UNBLOCK` | | + ### Button The button tapped, sent in the event name `Button: {button}`. diff --git a/libs/analytics-events/events.toml b/libs/analytics-events/events.toml index 7eeca8bc8d..ca66e47d48 100644 --- a/libs/analytics-events/events.toml +++ b/libs/analytics-events/events.toml @@ -90,6 +90,7 @@ USERNAME_SHORTFALL = "Username Shortfall" CHAT = "Chat" SCANNER = "Scanner" BALANCE = "Balance" +PROFILE = "Profile" [lists.AddMoneyMethod] description = "The `Method` property on the Add Money events: how the user adds money." @@ -181,6 +182,31 @@ ONBOARDING = "Onboarding" MY_ACCOUNT = "My Account" TIP_CARD_SETUP = "Tip Card Setup" +[lists.ProfileField] +description = "The `Field` property on Profile: Field Saved: the profile field that was saved." +[lists.ProfileField.values] +NAME = "Name" +USERNAME = "Username" +PHOTO = "Photo" +COVER = "Cover" +BIO = "Bio" +MINIMUM = "Minimum" + +[lists.ProfileMenuAction] +description = "The `Action` property on Profile: Menu Action: the action picked from another user's profile menu." +[lists.ProfileMenuAction.values] +MUTE = "Mute" +REPORT = "Report" +BLOCK = "Block" +UNBLOCK = "Unblock" + +[lists.ProfilePinnedAction] +description = "The `Action` property on Profile: Pinned Button Tapped: what the profile's pinned button does." +[lists.ProfilePinnedAction.values] +START_CHATTING = "Start Chatting" +OPEN_CHAT = "Open Chat" +UNBLOCK = "Unblock" + [lists.Button] description = "The button tapped, sent in the event name `Button: {button}`." [lists.Button.values] @@ -684,6 +710,53 @@ name = "Linked Phone Number" domain = "Account" name = "Complete Onboarding" +# Profile + +[[event]] +domain = "Profile" +name = "Profile: Settings Viewed" +builder = "settingsViewed" +description = "The Settings screen opened." + +[[event]] +domain = "Profile" +name = "Profile: Edit Profile Viewed" +builder = "editProfileViewed" +description = "The Edit Profile screen opened." + +[[event]] +domain = "Profile" +name = "Profile: Field Saved" +builder = "fieldSaved" +properties = [{ name = "Field", type = "ProfileField" }] +description = "A profile field was saved." + +[[event]] +domain = "Profile" +name = "Profile: Bio Moderation Failed" +builder = "bioModerationFailed" +description = "A bio was rejected by moderation." + +[[event]] +domain = "Profile" +name = "Profile: Menu Action" +builder = "menuAction" +properties = [{ name = "Action", type = "ProfileMenuAction" }] +description = "An action was picked from another user's profile menu." + +[[event]] +domain = "Profile" +name = "Profile: Pinned Button Tapped" +builder = "pinnedButtonTapped" +properties = [{ name = "Action", type = "ProfilePinnedAction" }] +description = "The pinned button on another user's profile was tapped." + +[[event]] +domain = "Profile" +name = "Profile: Card Shown" +builder = "cardShown" +description = "A profile card was shown." + # Buttons [[event]] diff --git a/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/AddMoneyEventsTest.kt b/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/AddMoneyEventsTest.kt index b4f7bae783..6a54b8080a 100644 --- a/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/AddMoneyEventsTest.kt +++ b/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/AddMoneyEventsTest.kt @@ -17,7 +17,7 @@ class AddMoneyEventsTest { @Test fun openedCarriesEverySourceByItsWireString() { assertEquals( - listOf("Menu", "Give Shortfall", "Buy Shortfall", "Username Shortfall", "Chat", "Scanner", "Balance"), + listOf("Menu", "Give Shortfall", "Buy Shortfall", "Username Shortfall", "Chat", "Scanner", "Balance", "Profile"), AddMoneySource.entries.map { val event = AddMoneyEvents.opened(it) assertEquals("Add Money: Opened", event.name) diff --git a/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/ProfileEventsTest.kt b/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/ProfileEventsTest.kt new file mode 100644 index 0000000000..5f256fee16 --- /dev/null +++ b/libs/analytics-events/src/commonTest/kotlin/com/flipcash/analytics/ProfileEventsTest.kt @@ -0,0 +1,52 @@ +package com.flipcash.analytics + +import com.flipcash.analytics.events.ProfileEvents +import kotlin.test.Test +import kotlin.test.assertEquals + +class ProfileEventsTest { + + @Test + fun screenEventsHaveNoProperties() { + assertEquals(AnalyticsEvent("Profile: Settings Viewed", emptyMap()), ProfileEvents.settingsViewed()) + assertEquals(AnalyticsEvent("Profile: Edit Profile Viewed", emptyMap()), ProfileEvents.editProfileViewed()) + assertEquals(AnalyticsEvent("Profile: Bio Moderation Failed", emptyMap()), ProfileEvents.bioModerationFailed()) + assertEquals(AnalyticsEvent("Profile: Card Shown", emptyMap()), ProfileEvents.cardShown()) + } + + @Test + fun fieldSavedCarriesEveryFieldByItsWireString() { + assertEquals( + listOf("Name", "Username", "Photo", "Cover", "Bio", "Minimum"), + ProfileField.entries.map { + val event = ProfileEvents.fieldSaved(it) + assertEquals("Profile: Field Saved", event.name) + (event.properties.getValue("Field") as PropertyValue.Text).value + }, + ) + } + + @Test + fun menuActionCarriesEveryActionByItsWireString() { + assertEquals( + listOf("Mute", "Report", "Block", "Unblock"), + ProfileMenuAction.entries.map { + val event = ProfileEvents.menuAction(it) + assertEquals("Profile: Menu Action", event.name) + (event.properties.getValue("Action") as PropertyValue.Text).value + }, + ) + } + + @Test + fun pinnedButtonTappedCarriesEveryActionByItsWireString() { + assertEquals( + listOf("Start Chatting", "Open Chat", "Unblock"), + ProfilePinnedAction.entries.map { + val event = ProfileEvents.pinnedButtonTapped(it) + assertEquals("Profile: Pinned Button Tapped", event.name) + (event.properties.getValue("Action") as PropertyValue.Text).value + }, + ) + } +}