Skip to content

[Improve App Ratings] Display Hooks + Debug Menu #3331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jul 18, 2025

Conversation

bjtitus
Copy link
Contributor

@bjtitus bjtitus commented Jul 13, 2025

📘 Part of: Improve App Ratings

Closes PCIOS-20 and PCIOS-19

This also adds 4 new analytics events:

  • userSatisfactionSurveyShown
  • userSatisfactionSurveyDismissed
  • userSatisfactionSurveyYesResponse
  • userSatisfactionSurveyNoResponse

I've added a new debug menu to aid in verifying state, manually present the screen, and reset the various history items:
simulator_screenshot_FB6582E4-84C8-4341-A071-11CDF6F465F5

To test

Free User

Star an episode

  • Go to an episode and Star it
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

3rd completed episode

  • Listen to 3 episodes after installing this version
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

After creating a filter

  • Filters > New Filter
  • Complete the modals until you get to the filter's screen
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Rate a podcast

  • Find a podcast you have enough listening history recorded for to rate
  • Rate the Podcast
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Plus users

Create a folder

  • Podcasts > Create folder button in upper left
  • Finish folder creation
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Create or listen to a bookmark

  • Add a bookmark to an episode
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Set a custom theme

  • Profile > Appearance > Theme
  • Set a custom theme
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Share a Plus referral

  • Profile > 🎁 Icon in upper left
  • Share Guest Pass
  • Complete the share by selecting any option
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

2 days after upgrading to Plus

  • Use a free account
  • Use the Debug menu to give the account Plus
  • Kill the app and relaunch so that the upgrade date is logged
  • Move the clock forward 3 days (just to give a buffer)
  • Restart the app
  • ✅ Ensure the rating screen shows up
  • Reset in Developer > Survey Debug Info

Frequency Logic

These are the rules around re-prompting, which can be checked as a part of the events above.

  • Limit: Once per 30 days
  • Suppression:
    • If user already left a review
    • If user clicked “Not Really” within past 60 days

Checklist

  • I have considered if this change warrants user-facing release notes and have added them to CHANGELOG.md if necessary.
  • I have considered adding unit tests for my changes.
  • I have updated (or requested that someone edit) the spreadsheet to reflect any new or changed analytics.

@bjtitus bjtitus added this to the 7.94 milestone Jul 13, 2025
@dangermattic
Copy link
Collaborator

dangermattic commented Jul 13, 2025

1 Warning
⚠️ This PR is larger than 500 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

bjtitus added 17 commits July 14, 2025 23:10
- Add survey presentation tracking methods to Settings
- Create UserSatisfactionSurveyManager with entry point logic
- Add SurveyEventTracker to handle user actions
- Update UserSatisfactionSurveyView to track "Not Really" response
- Add new analytics events for survey tracking
- Add UserDefaults keys for survey data storage

This implements the foundation for context-aware survey prompts
based on user engagement patterns and subscription status.
Add survey tracking calls to all entry points specified in the spec:

Free user entry points:
- Episode completion tracking in PlaybackManager
- Episode starring in EpisodeManager
- Show rating in RatePodcastViewModel
- Filter creation in CreateFilterViewController

Plus user entry points:
- Plus upgrade tracking in IAPHelper
- Folder creation in ColorPreviewFolderView
- Bookmark creation in PlaybackManager
- Custom theme setting in Theme class (Plus themes only)
- Referral sharing in ReferralSendPassVC

All triggers now call the appropriate SurveyEventTracker methods
which will evaluate survey eligibility and present when appropriate.
- Update UserSatisfactionSurveyManager to public visibility
- Update SurveyEventTracker to public visibility
- Make shared instances and tracking methods public
- This enables access from all targets in the project

The survey review prompt logic is now fully implemented according to spec:
- All entry points trigger appropriate survey tracking
- Frequency and suppression logic respects 30-day and 60-day limits
- User subscription status determines which events are eligible
- Existing 2.5h listening time review prompt remains unchanged
@bjtitus bjtitus force-pushed the bjtitus/improve-app-ratings/logic branch from fa6e1c7 to 9cc9dce Compare July 15, 2025 05:14
@bjtitus bjtitus marked this pull request as ready for review July 15, 2025 05:15
@bjtitus bjtitus requested a review from a team as a code owner July 15, 2025 05:15
@bjtitus bjtitus requested review from SergioEstevao and removed request for a team July 15, 2025 05:15
@@ -1054,6 +1054,7 @@ class PlaybackManager: ServerPlaybackDelegate {
episode.playingStatus = PlayingStatus.completed.rawValue
episode.playedUpTo = episode.duration


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove this extra line

@@ -71,6 +71,7 @@ class RatePodcastViewModel: ObservableObject {
Analytics.shared.track(.ratingScreenSubmitTapped,
properties: ["uuid": podcast.uuid,
"stars": stars])

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove this extra line


private func mapAnalyticsEventToSurveyTrigger(name: String) -> SurveyTriggerEvent? {
switch name {
case "episode_starred":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using the event name directly here, what do you think of using the enum rawValue like this:

.episodeStarred.rawValue.toSnakeCaseFromCamelCase()

this way if in the future someone changes the events name or removes it they will warned of this dependency.

@@ -27,6 +27,8 @@ extension AppDelegate {
adapters.append(NotificationsCoordinator.shared)
}

adapters.append(UserSatisfactionSurveyManager.shared)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it better to put this under a FF check?

@@ -159,6 +159,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
PlaybackManager.shared.updateIdleTimer()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line

@@ -52,6 +52,7 @@ struct ColorPreviewFolderView: View {
Button {
let folderUuid = model.createFolder()
Analytics.track(.folderSaved, properties: ["number_of_podcasts": model.selectedPodcastUuids.count, "color": UIColor(model.color).hexString()])

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line

@SergioEstevao SergioEstevao self-requested a review July 16, 2025 13:49
Copy link
Contributor

@SergioEstevao SergioEstevao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for changing the code to use analytics. I left some nit comments but I also detected the following behaviours that I want to check with you:

  • Survey shows when bookmark creation is still visible
  • Survey shows when system share screen is visible, when sharing a referral

@bjtitus bjtitus requested a review from SergioEstevao July 16, 2025 21:20
@bjtitus
Copy link
Contributor Author

bjtitus commented Jul 16, 2025

Survey shows when system share screen is visible, when sharing a referral

Fixed this one by moving the referralPassShared event but this will change the event reporting. I think it's new location is more accurate though.

Survey shows when bookmark creation is still visible

I can't quite pinpoint in the same way as I was with the Analytics event so the survey after bookmark is showing up behind the toast briefly. I don't think this is too bad but what do you think?

Simulator Screenshot - iPhone 16 - 2025-07-16 at 15 42 33

@bjtitus
Copy link
Contributor Author

bjtitus commented Jul 17, 2025

@SergioEstevao Should be ready for review when you get a chance.

Copy link
Contributor

@SergioEstevao SergioEstevao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing all the changes!
:shipit:

@bjtitus bjtitus merged commit f55fd27 into trunk Jul 18, 2025
4 of 6 checks passed
@bjtitus bjtitus deleted the bjtitus/improve-app-ratings/logic branch July 18, 2025 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants