Promoted.ai iOS 客户端库

Promoted.ai 提供一个 iOS 日志记录库,用于收集指标和训练交付系统。该库包含在您的 iOS 应用程序中跟踪事件并将其高效地交付到 Promoted.ai 后端所需的功能。

我们的客户端库适用于 iOS 11+,并可与 Swift 和 Objective-C 应用程序配合使用。我们还通过一个名为 react-native-metrics 的独立软件包支持 React Native 应用程序。

特别感谢 Wendy Lu 的专业审核。

应用隐私

根据 Apple 的应用隐私问题,Promoted 的日志记录库收集以下类型的数据

此数据用于以下目的

[1] 如果用户希望被遗忘,则此链接可以很容易地被断开。

技术

我们的客户端库构建于以下技术之上

  1. Protocol Buffers:一种数据交换格式,比 JSON 在网络传输上效率更高,使我们的数据使用量远低于基于 JSON 的日志记录解决方案。
  2. GTMSessionFetcher(可选):一个用于网络访问的库,被许多 Google iOS 应用程序使用。
  3. Firebase Analytics(可选):在生产流量中提供对客户端库的监控。
  4. Firebase Remote Config(可选):提供客户端库行为的服务器端配置,而无需额外的 App Store 审核/发布周期。

标记为(可选)的依赖项不会安装,除非您选择包含它们。默认情况下,我们包含 GTMSessionFetcher,但您可以提供自己的网络接口并排除此依赖项。

可用性

我们的客户端库通过以下渠道提供。您将收到关于如何通过您选择的渠道进行集成的说明。

  1. 作为 Swift Package (PromotedAIMetricsSDK)
  2. 作为 Cocoapod (PromotedAIMetricsSDK)
  3. 作为 NPM 包(仅限 React Native)( react-native-metrics)

集成

您的应用程序通过以下类控制我们客户端库的初始化和行为

  1. MetricsLoggingService 配置库的行为和初始化。
  2. MetricsLogger 接受要发送到服务器的日志消息。
  3. ImpressionTracker 跟踪集合视图中内容的展示次数。

MetricsLoggerService

在您的应用程序启动时创建并配置服务,然后在配置完成后从服务中检索 MetricsLogger 实例。或者,使用该服务创建 ImpressionTracker 实例。

用法示例(依赖注入)

var config = ClientConfig()
config.metricsLoggingURL = "https://yourdomain.ext.promoted.ai"
config.metricsLoggingAPIKey = "..."
let service = try MetricsLoggerService(initialConfig: config)
try service.startLoggingServices()
// Create and use objects from the service
let logger = service.metricsLogger
let impressionTracker = service.impressionTracker(sourceType: .delivery)
let scrollTracker = service.scrollTracker(collectionView: ...)

用法示例(单例)

var config = ClientConfig()
config.metricsLoggingURL = "https://yourdomain.ext.promoted.ai"
config.metricsLoggingAPIKey = "..."
// Call `startServices` first before accessing the instance.
try MetricsLoggerService.startServices(initialConfig: config)
let service = MetricsLoggerService.shared
// Create and use objects from the service
let logger = service.metricsLogger
let impressionTracker = service.impressionTracker(sourceType: .delivery)
let scrollTracker = service.scrollTracker(collectionView: ...)

Promoted 与代理服务器

当使用 ClientConfig 时,如果您在 metricsLoggingURL 中直接连接到 Promoted 服务器,则需要为 metricsLoggingAPIKey 提供 API 密钥。但是,如果您使用代理服务器,则无需为 metricsLoggingAPIKey 指定值,因为您的代理可能会将真实的 API 密钥转发到 Promoted Metrics 服务。此外,您可以使用 metricsLoggingRequestHeaders 自定义您的请求标头。

// Using a proxy server
var config = ClientConfig()
config.metricsLoggingURL = "https://proxy.yourdomain.com"
config.metricsLoggingRequestHeaders = [
  "x-custom-header-1": "value1",
  "x-custom-header-2": "value2"
]
let service = try MetricsLoggerService(initialConfig: config)

MetricsLogger

Promoted 事件日志记录接口。使用 MetricsLogger 的实例将事件记录到 Promoted 的服务器。事件被累积并在计时器上分批发送。

要启动日志记录会话,请首先调用 startSession(userID:)startSessionSignedOut() 来设置用户 ID 并记录会话的用户 ID。您可以多次调用任一 startSession 方法以使用给定的用户 ID 开始新会话。

使用 log(message:) 将事件排队以进行日志记录。当批处理计时器触发时,所有事件都通过 NetworkConnection 传递到服务器。

示例

let logger = MetricsLogger(...)
// Sets userID and logUserID for subsequent log() calls.
logger.startSession(userID: myUserID)
// Log clicks, purchases, or other relevant events
logger.logAction(type: .navigate, content: clickedContent)
logger.logAction(type: .purchase, content: purchasedContent)
// Resets userID and logUserID.
logger.startSession(userID: secondUserID)

ImpressionTracker

提供跨滚动集合视图(如 UICollectionViewUITableView)的基本展示次数跟踪。最适用于可以提供可见单元格的细粒度更新的视图,但也适用于无法提供细粒度更新的视图(请参阅 ScrollTracker)。

UICollectionView 的用法示例

客户端应创建 ImpressionTracker 的实例并在其视图控制器中引用它,然后在集合视图滚动或更新时向展示次数记录器提供更新。

class MyViewController: UIViewController {
  var collectionView: UICollectionView
  var impressionTracker: ImpressionTracker

  init(...) {
    impressionTracker = metricsLoggerService.impressionTracker()
  }

  private func content(atIndexPath path: IndexPath) -> Content? {
    let item = path.item
    if item >= self.items.count { return nil }
    let myItemProperties = self.items[item]
    return Item(properties: myItemProperties)
  }

  func viewWillDisappear(_ animated: Bool) {
    impressionTracker.collectionViewDidHideAllContent()
  }

  func collectionView(
    _ collectionView: UICollectionView,
    willDisplay cell: UICollectionViewCell,
    forItemAt indexPath: IndexPath
  ) {
    if let content = content(atIndexPath: indexPath) {
      impressionTracker.collectionViewWillDisplay(content: content)
    }
  }
   
  func collectionView(
    _ collectionView: UICollectionView,
    didEndDisplaying cell: UICollectionViewCell,
    forItemAt indexPath: IndexPath
  ) {
    if let content = content(atIndexPath: indexPath) {
      impressionTracker.collectionViewDidHide(content: content)
    }
  }

  func reloadCollectionView() {
    self.collectionView.reloadData()
    let visibleContent = collectionView.indexPathsForVisibleItems.map {
      path in content(atIndexPath: path)
    }
    impressionTracker.collectionViewDidChangeVisibleContent(visibleContent)
  }
}