TelemetryDeck / SwiftSDK

Swift SDK for TelemetryDeck, a privacy-conscious analytics service for apps and websites.
https://telemetrydeck.com/
Other
155 stars 32 forks source link

Force-sending signals from cache when app enters background / terminated #130

Closed Jeehut closed 8 months ago

Jeehut commented 10 months ago

I'm using TelemetryDeck in a new crossword app where I want to track if people leave my app to research an answer for a crossword clue and come back, or if they leave the app and don't come back. I'm also concerned about the last actions a user makes before potentially deleting my app or never opening it again or opening it only weeks later (which is too late).

From what I understand from the "[TelemetryDeck: INFO]" console outputs, TelemetryDeck caches the signals and sends them after a certain time. To be sure that events are sent before leaving or terminating the app, it would be great if there was an API for manually triggering the sending of signals. Then I could just write something like this in my @UIApplicationDelegateAdaptor implementation (note the .forceSyncEvents() calls):

#if os(macOS)
final class AppDelegate: NSObject, NSApplicationDelegate {
   func applicationDidFinishLaunching(_ notification: Notification) {
      Analytics.setup()
      Analytics.record(eventName: "App.didFinishLaunching")
   }

   func applicationWillTerminate(_ notification: Notification) {
      Analytics.record(eventName: "App.willTerminate")
      Analytics.forceSyncEvents()
   }
}
#else
final class AppDelegate: NSObject, UIApplicationDelegate {
   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
      Analytics.setup()
      Analytics.record(eventName: "App.didFinishLaunching")
      return true
   }

   func applicationWillEnterForeground(_ application: UIApplication) {
      Analytics.record(eventName: "App.willEnterForeground")
   }

   func applicationDidEnterBackground(_ application: UIApplication) {
      Analytics.record(eventName: "App.didEnterBackground")
      Analytics.forceSyncEvents()
   }

   func applicationWillTerminate(_ application: UIApplication) {
      Analytics.record(eventName: "App.willTerminate")
      Analytics.forceSyncEvents()
   }
}
#endif

@main
struct MyApp: App {
   #if os(macOS)
   @NSApplicationDelegateAdaptor(AppDelegate.self)
   var appDelegate
   #else
   @UIApplicationDelegateAdaptor(AppDelegate.self)
   var appDelegate
   #endif

   var body: some Scene { ... }
}
Implementation of my Analytics type enum Analytics { static var userID: String { let key = "userID" guard let existingUserID = UserDefaults.standard.string(forKey: key) else { let newUserID = UUID().uuidString UserDefaults.standard.setValue(newUserID, forKey: key) return newUserID } return existingUserID } static func setup() { let configuration = TelemetryManagerConfiguration(appID: "...") configuration.defaultUser = Self.userID TelemetryManager.initialize(with: configuration) } static func record(eventName: String, floatValue: Double? = nil, attributes: [String: String] = [:]) { TelemetryManager.send(eventName, floatValue: floatValue, with: attributes) } static func forceSyncEvents() { TelemetryManager.forceSyncEvents() } }