Skip to content

Commit 8a79b44

Browse files
committed
Detect free trials and report as a separate signal
1 parent c1880a4 commit 8a79b44

File tree

1 file changed

+74
-25
lines changed

1 file changed

+74
-25
lines changed

Sources/TelemetryDeck/Presets/TelemetryDeck+Purchases.swift

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,57 @@ extension TelemetryDeck {
1919
parameters: [String: String] = [:],
2020
customUserID: String? = nil
2121
) {
22-
let priceValueInNativeCurrency = NSDecimalNumber(decimal: transaction.price ?? Decimal()).doubleValue
23-
24-
let priceValueInUSD: Double
25-
26-
if #available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) {
27-
if transaction.currency?.identifier == "USD" {
28-
priceValueInUSD = priceValueInNativeCurrency
29-
} else if
30-
let currencyCode = transaction.currency?.identifier,
31-
let oneUSDExchangeRate = self.currencyCodeToOneUSDExchangeRate[currencyCode]
22+
if #available(iOS 17.2, macOS 14.2, tvOS 17.2, visionOS 1.1, watchOS 10.2, *) {
23+
// detect if the purchase is a free trial (using modern APIs)
24+
if
25+
transaction.productType == .autoRenewable,
26+
transaction.offer?.type == .introductory,
27+
transaction.price == nil || transaction.price!.isZero
3228
{
33-
priceValueInUSD = priceValueInNativeCurrency / oneUSDExchangeRate
29+
self.reportFreeTrial(transaction: transaction, parameters: parameters, customUserID: customUserID)
3430
} else {
35-
priceValueInUSD = 0
31+
self.reportPaidPurchase(transaction: transaction, parameters: parameters, customUserID: customUserID)
3632
}
3733
} else {
38-
if transaction.currencyCode == "USD" {
39-
priceValueInUSD = priceValueInNativeCurrency
40-
} else if
41-
let currencyCode = transaction.currencyCode,
42-
let oneUSDExchangeRate = self.currencyCodeToOneUSDExchangeRate[currencyCode]
34+
// detect if the purchase is a free trial (using legacy APIs on older systems)
35+
if
36+
transaction.productType == .autoRenewable,
37+
transaction.offerType == .introductory,
38+
transaction.price == nil || transaction.price!.isZero
4339
{
44-
priceValueInUSD = priceValueInNativeCurrency / oneUSDExchangeRate
40+
self.reportFreeTrial(transaction: transaction, parameters: parameters, customUserID: customUserID)
4541
} else {
46-
priceValueInUSD = 0
42+
self.reportPaidPurchase(transaction: transaction, parameters: parameters, customUserID: customUserID)
4743
}
4844
}
45+
}
46+
47+
private static func reportFreeTrial(
48+
transaction: StoreKit.Transaction,
49+
parameters: [String: String],
50+
customUserID: String?
51+
) {
52+
self.internalSignal(
53+
"TelemetryDeck.Purchase.freeTrialStarted",
54+
parameters: self.purchaseParameters(transaction: transaction).merging(parameters) { $1 },
55+
customUserID: customUserID
56+
)
57+
}
58+
59+
private static func reportPaidPurchase(
60+
transaction: StoreKit.Transaction,
61+
parameters: [String: String],
62+
customUserID: String?
63+
) {
64+
self.internalSignal(
65+
"TelemetryDeck.Purchase.completed",
66+
parameters: self.purchaseParameters(transaction: transaction).merging(parameters) { $1 },
67+
floatValue: self.calculatePriceInUSD(transaction: transaction),
68+
customUserID: customUserID
69+
)
70+
}
4971

72+
private static func purchaseParameters(transaction: StoreKit.Transaction) -> [String: String] {
5073
let countryCode: String
5174
if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) {
5275
countryCode = transaction.storefront.countryCode
@@ -73,12 +96,38 @@ extension TelemetryDeck {
7396
}
7497
}
7598

76-
self.internalSignal(
77-
"TelemetryDeck.Purchase.completed",
78-
parameters: purchaseParameters.merging(parameters) { $1 },
79-
floatValue: priceValueInUSD,
80-
customUserID: customUserID
81-
)
99+
return purchaseParameters
100+
}
101+
102+
private static func calculatePriceInUSD(transaction: StoreKit.Transaction) -> Double {
103+
let priceValueInNativeCurrency = NSDecimalNumber(decimal: transaction.price ?? Decimal()).doubleValue
104+
let priceValueInUSD: Double
105+
106+
if #available(iOS 16, macOS 13, tvOS 16, watchOS 9, *) {
107+
if transaction.currency?.identifier == "USD" {
108+
priceValueInUSD = priceValueInNativeCurrency
109+
} else if
110+
let currencyCode = transaction.currency?.identifier,
111+
let oneUSDExchangeRate = self.currencyCodeToOneUSDExchangeRate[currencyCode]
112+
{
113+
priceValueInUSD = priceValueInNativeCurrency / oneUSDExchangeRate
114+
} else {
115+
priceValueInUSD = 0
116+
}
117+
} else {
118+
if transaction.currencyCode == "USD" {
119+
priceValueInUSD = priceValueInNativeCurrency
120+
} else if
121+
let currencyCode = transaction.currencyCode,
122+
let oneUSDExchangeRate = self.currencyCodeToOneUSDExchangeRate[currencyCode]
123+
{
124+
priceValueInUSD = priceValueInNativeCurrency / oneUSDExchangeRate
125+
} else {
126+
priceValueInUSD = 0
127+
}
128+
}
129+
130+
return priceValueInUSD
82131
}
83132

84133
private static let currencyCodeToOneUSDExchangeRate: [String: Double] = [

0 commit comments

Comments
 (0)