The Paid-to-Freemium Transition Problem
Switching a paid app to freemium is a common business decision, but it comes with a fairness challenge: users who already paid for the app should not suddenly lose features or be asked to pay again. StoreKit’s AppTransaction API solves this cleanly.
Using AppTransaction to Check Purchase History
The key is AppTransaction.shared, which provides information about the original transaction for your app. Specifically, originalAppVersion tells you which version of the app the user originally downloaded. If that version was a paid version, you know the user already paid.
import StoreKit
func shouldGrantFullAccess() async -> Bool {
do {
let result = try await AppTransaction.shared
if case .verified(let transaction) = result {
let originalVersion = transaction.originalAppVersion
// Version "2.0" was when the app went freemium
if originalVersion.compare("2.0", options: .numeric) == .orderedAscending {
return true // User purchased before freemium transition
}
}
} catch {
// Handle verification failure
}
return false
}The logic is straightforward: compare the user’s originalAppVersion against the version where you made the freemium switch. If their original version predates the change, grant them full access automatically.
Important Details
The originalAppVersion corresponds to the CFBundleShortVersionString value at the time of the original purchase (or download for free apps). Make sure you know exactly which version number marks your transition point.
This approach requires no server infrastructure and no migration code. StoreKit handles verification through the App Store receipt chain, so the check is tamper-resistant. Apple documents this pattern in their original API for business model migration.
For TestFlight and simulator testing, originalAppVersion returns the CFBundleVersion (build number) instead, so plan your test cases accordingly.
