添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
跳到主要内容

使用 SKStoreReviewController 实现应用内评分来提高 AppStore 评分

· 阅读需 11 分钟
GoSwiftUI
goswiftui.com

SKStoreReviewController 允许从应用程序内向您的用户询问 App Store 评分。正面的评价可以帮助您的应用 在 App Store 中脱颖而出并吸引更多用户。当您在正确的时间要求用户评分时,转化率会增加。

虽然实施评级请求很容易,但在正确的时间要求评级可能会变得更加复杂。参与的用户更有可能发布正面评价,而当您在用户流的中间要求评分时,您可能会期望得到负面评价。让我们深入了解如何创建出色的评分请求体验。

使用 SKStoreReviewController 请求评分

SKStoreReviewController 是不可配置的,它只定义了一个方法来要求用户进行评论。使用 API 如下所示:

#if os(macOS)
SKStoreReviewController.requestReview()
#else
guard let scene = UIApplication.shared.foregroundActiveScene else { return }
SKStoreReviewController.requestReview(in: scene)
#endif

您可以直接 requestReview() 在 macOS 上使用该方法。对于 iOS,我们需要获取一个目标场景来呈现。在我们的例子中,我们使用以下扩展来抓取活动的前景场景:

extension UIApplication {
var foregroundActiveScene: UIWindowScene? {
connectedScenes
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
}
}

生成的弹出窗口如下所示:

您可以使用 SKStoreReviewController 在您的应用程序内询问用户评分。

如您所见,用户只需单击一下即可为您的应用提交评分,这是增加应用评分数量的好方法。

询问用户评分的重要性

您之前可能听说过 App Store Optimization (ASO)。App Store Ratings 是优化您的 App Store 排行和增加下载量的重要组成部分。好评是否会让您在搜索结果列表中排名靠前尚不确定,但可以肯定的是,您的应用在获得 5 星评级后看起来会更好。

你可以退后一步,看看你在 App Store 中的行为。如果您不确定要使用哪个应用程序,您可能会查看评分和评论,以确定哪个应用程序可能最适合您。这就是为什么必须使用 SKStoreReviewController 请求评分的原因。

要求评分的正确时机

SKStoreReviewController API 很简单,因此有一些注意事项。例如,我们无法知道用户是否真的提交了评分,或者他是否点击了“Not Now”。我们可以要求用户评分的次数也是有限的,因为 Apple 希望防止我们发送垃圾邮件以获得评分。

总之,这些是需要注意的基本见解:

  • 评分提示在 365 天内最多只会向用户显示 3 次。
  • 没有办法知道评分提示是否出现
  • 您不会收到有关用户是否提交评分或是否点击“现在不”的任何反馈。
  • 换句话说:您应该为您的请求计时,并可能增加用户提交评分的机会。

    我们通过调整评级请求方法开始这个实现:

    func askForRatingIfNeeded() {
    guard shouldAskForRating else { return }
    askForRating()
    }

    func askForRating() {
    Defaults[.lastVersionPromptedForReview] = applicationVersionProvider()

    #if os(macOS)
    SKStoreReviewController.requestReview()
    #else
    guard let scene = UIApplication.shared.foregroundActiveScene else { return }
    SKStoreReviewController.requestReview(in: scene)
    #endif
    }

    请注意,我们正在存储提示审核的最后一个应用程序版本。我们稍后会在设置条件时使用它。这 applicationVersionProvider 只是一个返回捆绑版本的闭包,可用于单元测试和临时覆盖返回的应用程序版本。

    我们定义了一种 askForRatingIfNeeded() 方法,我们可以在我们认为在条件有效的情况下要求用户评分的地方使用该方法。由您决定这一时刻,但尝试找到用户不在其流程中的时刻。例如,在您的应用程序启动时要求评分是有害的,因为用户可能正在寻找某些东西。

    为了更加确定您没有在用户的流程中阻止用户,您可以将要求评分的时间延迟几秒钟。

    let requestWorkItem = DispatchWorkItem {
    askForRatingIfNeeded()
    }

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute: requestWorkItem)

    requestWorkItem 每当用户执行任何用户交互时,我们都应该取消。如果工作项执行,我们知道用户在 2 秒内没有做任何事情,从而增加了他们有时间提交评分的机会。

    在询问之前设置要验证的条件

    requestReview 除了要求正确的时机之外,在执行 SKStoreReviewController方法之前设置条件进行验证也是很好的。我总是喜欢设置以下条件:

  • 只询 问安装应用程序超过 7 天的用户,让他们成为回头客并增加他们喜欢应用程序的机会。
  • 要求对每个应用版本进行一次评级,以防止多次要求查看相同的应用版本。
  • 用户应该有最少数量的会话。
  • 应该触发了重要的用户事件,表明用户理解并使用了该应用程序。
  • 后者可能是在 WeTransfer 应用程序中上传文件或使用 RocketSim 创建录音。这些是这些应用程序中的重要事件,表示活跃用户。

    综合起来,一个可能的实现如下所示:

    var shouldAskForRating: Bool {
    guard !isDebuggingEnabled else { return true }
    guard let firstLaunchDate = Defaults[.firstOpenDate] else { return false }
    let timeSinceFirstLaunch = Date().timeIntervalSince(firstLaunchDate)
    let timeUntilRate: TimeInterval = 60 * 60 * 24 * TimeInterval(configuration.daysUntilPrompt)

    return Defaults[.appSessionsCount] >= configuration.sessionsUntilPrompt
    && Defaults[.ratingEventsCount] >= configuration.eventsUntilPrompt
    && timeSinceFirstLaunch >= timeUntilRate
    && Defaults[.lastVersionPromptedForReview] != applicationVersionProvider()
    }

    我正在使用 这个用户默认便利库 Defaults[] 语法。

    如果启用了调试,则该 shouldAskForRating 方法返回 true,这样您就可以确保弹出窗口在正确的时刻出现。请注意,附加调试器时将始终显示评级提示。

    我将把它作为练习留给你把所有的部分放在一起,但我想分享更多的提示。捕获重要的用户事件是通过这个静态方法完成的:

    static func didPerformSignificantEvent() {
    Defaults[.ratingEventsCount] += 1
    }

    您可以使用以下代码捕获会话计数和首次启动日期:

    @objc private func applicationDidBecomeActive(_ notification: Notification) {
    Defaults[.appSessionsCount] += 1

    if Defaults[.firstOpenDate] == nil {
    Defaults[.firstOpenDate] = Date()
    }
    }

    一个潜在的配置结构如下所示:

    public struct RatingRequesterConfiguration {
    public typealias RatingRequestedHandler = ((String) -> Void)

    /// The minimum amounts of days until the first prompt should be shown.
    let daysUntilPrompt: Int

    /// The number of app sessions required until the first prompt should be shown.
    let sessionsUntilPrompt: Int

    /// The number of events required until the first prompt should be shown.
    let eventsUntilPrompt: Int

    /// Will be called after the user is requested for a review.
    let onRatingRequest: RatingRequestedHandler?

    public init(daysUntilPrompt: Int, sessionsUntilPrompt: Int, eventsUntilPrompt: Int, onRatingRequest: RatingRequesterConfiguration.RatingRequestedHandler?) {
    self.daysUntilPrompt = daysUntilPrompt
    self.sessionsUntilPrompt = sessionsUntilPrompt
    self.eventsUntilPrompt = eventsUntilPrompt
    self.onRatingRequest = onRatingRequest
    }
    }

    验证您的结果

    实施正确的条件后,最好确保您正在验证 SKStoreReviewController 实施的结果。

  • 您获得的评分数量是否在增加?
  • 你得到更多的正面评价,还是你的负面评价在增加?
  • 您甚至可以实施跟踪事件来比较收到的评分数量与您请求评论的次数。

    我们正在使用 AppFigures 来验证我们的评分性能,您可以知道我们何时开始在 WeTransfer 应用程序中使用本文中的技术:

    WeTranfer 在向用户询问应用内的评分后,评分大幅增加。 WeTranfer 的评分在向用户询问应用程序内的评分后有所增加。

    我怎样才能要求评论?

    虽然收视率已经很高,但您可能希望寻求评论。您可以使用以下代码将用户深层链接到 App Store 以提交对您的应用的实际评论:

    @IBAction func requestReviewManually() {
    // Note: Replace the XXXXXXXXXX below with the App Store ID for your app
    // You can find the App Store ID in your app's product URL
    guard let writeReviewURL = URL(string: "https://apps.apple.com/app/idXXXXXXXXXX?action=write-review")
    else { fatalError("Expected a valid URL") }
    UIApplication.shared.open(writeReviewURL, options: [:], completionHandler: nil)
    }

    一个很好的技术可以是从他们的帐户屏幕向用户提供此选项,或者通过创建执行此方法的自定义评级请求弹出窗口。但是,评级提示的侵入性较小,可能会产生更好的结果。

    使用 SKStoreReviewController 请求评分相对容易,但创建正确的时机至关重要。评分可帮助您进行应用商店优化,并可能导致更多用户安装您的应用。设置条件以确保用户不会收到垃圾评分请求,并增加获得正面评价的机会。

  • 原文(英文): https://www.avanderlee.com/swift/skstorereviewcontroller-app-ratings
  • Fucking SwiftUI translate to Fuckingswiftui.com(英文版) Image2WebP