Skip to content

Commit

Permalink
Merge pull request #1735 from planetary-social/it/track-installation-…
Browse files Browse the repository at this point in the history
…source

Track TestFlight vs AppStore installations in Posthog
  • Loading branch information
pelumy authored Jan 15, 2025
2 parents ce6dca3 + 60b6074 commit 2103c57
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added function for creating a new list and a test verifying list editing. [#112](https://github.com/verse-pbc/issues/issues/112)
- Localized strings on the feed filter drop-down view.
- Disabled automatic tracking in Sentry. [#126](https://github.com/verse-pbc/issues/issues/126)
- Track TestFlight vs AppStore installations in Posthog. [#130](https://github.com/verse-pbc/issues/issues/130)

## [1.1] - 2025-01-03Z

Expand Down
1 change: 1 addition & 0 deletions Nos/AppController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Logger
init() {
currentState = .loading
Log.info("App Version: \(Bundle.current.versionAndBuild)")
analytics.trackInstallationSourceIfNeeded()
}

func configureCurrentState() {
Expand Down
24 changes: 24 additions & 0 deletions Nos/Extensions/Bundle+Current.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import Foundation
private class CurrentBundle {}

extension Bundle {
enum InstallationSource: String {
case testFlight = "TestFlight"
case appStore = "App Store"
case debug = "Debug"
}

static let current = Bundle(for: CurrentBundle.self)

Expand All @@ -21,4 +26,23 @@ extension Bundle {
var versionAndBuild: String {
"\(self.version) (\(self.build))"
}

/// > Warning: This method relies on undocumented implementation details to determine the installation source
/// and may break in future iOS releases.
/// https://gist.github.com/lukaskubanek/cbfcab29c0c93e0e9e0a16ab09586996
/// Checks the app's receipt URL to determine if it contains the TestFlight-specific
/// "sandboxReceipt" identifier.
/// - Returns: `true` if the app was installed through TestFlight, `false` otherwise.
private var isTestFlight: Bool {
Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"
}

/// Returns the app's installation source: debug, TestFlight, or App Store.
var installationSource: InstallationSource {
#if DEBUG
return .debug
#else
return isTestFlight ? .testFlight : .appStore
#endif
}
}
8 changes: 8 additions & 0 deletions Nos/Extensions/UIDevice+Simulator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@ extension UIDevice {
static var isSimulator: Bool {
ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
}

static var platformName: String {
#if os(iOS)
return UIDevice.current.systemName
#elseif os(macOS)
return "macOS"
#endif
}
}
27 changes: 26 additions & 1 deletion Nos/Service/Analytics.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Foundation
import UIKit
import PostHog
import Dependencies
import Logger
Expand Down Expand Up @@ -155,6 +155,31 @@ class Analytics {
postHog?.capture(eventName, properties: properties)
}

/// Tracks the source of the app download when the user launches the app.
func trackInstallationSourceIfNeeded() {
let source = Bundle.main.installationSource
// Make sure we don't track in debug mode.
guard source != .debug else { return }

let installSourceKey = "TrackedAppInstallationSource"

// Check if we've already tracked this installation.
if UserDefaults.standard.bool(forKey: installSourceKey) {
return
}

track(
"Installation Source",
properties: [
"source": source.rawValue,
"platform": UIDevice.platformName,
"app_version": Bundle.current.versionAndBuild
]
)
// Mark as tracked so we don't track again
UserDefaults.standard.set(true, forKey: installSourceKey)
}

/// Tracks when the user submits a search on the Discover screen.
func searchedDiscover() {
track("Discover Search Started")
Expand Down

0 comments on commit 2103c57

Please sign in to comment.