Skip to content

Commit e29cae3

Browse files
committed
Track paywall started loading + load error via EventsListener
1 parent 491a1ec commit e29cae3

File tree

9 files changed

+78
-1
lines changed

9 files changed

+78
-1
lines changed

RevenueCatUI/Data/PaywallViewConfiguration.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ extension PaywallViewConfiguration {
5454
case offering(Offering)
5555
case offeringIdentifier(String, presentedOfferingContext: PresentedOfferingContext?)
5656

57+
/// Empty for the default offering.
58+
var offeringIdentifier: String {
59+
switch self {
60+
case .defaultOffering:
61+
return ""
62+
case .offering(let offering):
63+
return offering.identifier
64+
case .offeringIdentifier(let identifier, _):
65+
return identifier
66+
}
67+
}
5768
}
5869

5970
}

RevenueCatUI/PaywallView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ public struct PaywallView: View {
241241
.transition(Self.transition)
242242
.task {
243243
do {
244+
self.purchaseHandler.trackPaywallStartedLoading(
245+
offeringIdentifier: self.contentToDisplay.offeringIdentifier
246+
)
244247
guard Purchases.isConfigured else {
245248
throw PaywallError.purchasesNotConfigured
246249
}
@@ -253,6 +256,10 @@ public struct PaywallView: View {
253256
self.customerInfo = try await Purchases.shared.customerInfo()
254257
}
255258
} catch let error as NSError {
259+
self.purchaseHandler.trackPaywallFailedToLoad(
260+
offeringIdentifier: self.contentToDisplay.offeringIdentifier,
261+
error: error
262+
)
256263
self.error = error
257264
}
258265
}

RevenueCatUI/Purchasing/MockPurchases.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ final class MockPurchases: PaywallPurchasesType {
7777
await self.trackEventBlock(paywallEvent)
7878
}
7979

80+
func trackPaywallStartedLoading(offeringIdentifier: String) async {}
81+
82+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async {}
83+
8084
#if !ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION
8185
func invalidateCustomerInfoCache() {
8286
// No-op, this is a mock implementation.

RevenueCatUI/Purchasing/PaywallPurchasesType.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ protocol PaywallPurchasesType: Sendable {
4444
@Sendable
4545
func track(paywallEvent: PaywallEvent) async
4646

47+
@Sendable
48+
func trackPaywallStartedLoading(offeringIdentifier: String) async
49+
50+
@Sendable
51+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async
52+
4753
#if !ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION
4854
func invalidateCustomerInfoCache()
4955
#endif

RevenueCatUI/Purchasing/PurchaseHandler.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,18 @@ extension PurchaseHandler {
400400
self.track(.impression(.init(), eventData))
401401
}
402402

403+
func trackPaywallStartedLoading(offeringIdentifier: String) {
404+
Task {
405+
await purchases.trackPaywallStartedLoading(offeringIdentifier: offeringIdentifier)
406+
}
407+
}
408+
409+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) {
410+
Task {
411+
await purchases.trackPaywallFailedToLoad(offeringIdentifier: offeringIdentifier, error: error)
412+
}
413+
}
414+
403415
/// - Returns: whether the event was tracked
404416
@discardableResult
405417
func trackPaywallClose() -> Bool {
@@ -523,6 +535,10 @@ private final class NotConfiguredPurchases: PaywallPurchasesType {
523535

524536
func track(paywallEvent: PaywallEvent) async {}
525537

538+
func trackPaywallStartedLoading(offeringIdentifier: String) async {}
539+
540+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async {}
541+
526542
#if !ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION
527543
func invalidateCustomerInfoCache() {}
528544
#endif

RevenueCatUI/Views/LoadingPaywallView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ private final class LoadingPaywallPurchases: PaywallPurchasesType {
191191
// Ignoring font loading errors from paywall view
192192
}
193193

194+
func trackPaywallStartedLoading(offeringIdentifier: String) async {}
195+
196+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async {}
197+
194198
}
195199

196200
// MARK: - Shimmer

Sources/Events/EventsManager.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,24 @@ import UIKit
3434
/// - error: The JSON encoding error that occurred when encoding `featureEvent`, `nil` if the failure was when
3535
/// trying to initialize a `String` with the JSON encoded data using UTF-8.
3636
func failedToTrackFeatureEvent(_ featureEvent: FeatureEvent, error: Error?)
37+
38+
/// Called whenever the EventsManager failed to be created.
39+
func failedToCreateEventsManager(error: Error)
40+
41+
func trackPaywallStartedLoading(offeringIdentifier: String)
42+
43+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error)
3744
}
3845

3946
protocol EventsManagerType {
4047

4148
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *)
4249
func track(featureEvent: FeatureEvent) async
4350

51+
func trackPaywallStartedLoading(offeringIdentifier: String) async
52+
53+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async
54+
4455
#if ENABLE_AD_EVENTS_TRACKING
4556
@available(iOS 15.0, tvOS 15.0, macOS 12.0, watchOS 8.0, *)
4657
func track(adEvent: AdEvent) async
@@ -136,6 +147,14 @@ actor EventsManager: EventsManagerType {
136147
}
137148
}
138149

150+
func trackPaywallStartedLoading(offeringIdentifier: String) {
151+
self.eventsListener?.trackPaywallStartedLoading(offeringIdentifier: offeringIdentifier)
152+
}
153+
154+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) {
155+
self.eventsListener?.trackPaywallFailedToLoad(offeringIdentifier: offeringIdentifier, error: error)
156+
}
157+
139158
#if ENABLE_AD_EVENTS_TRACKING
140159
func track(adEvent: AdEvent) async {
141160
guard let store = self.adEventStore else {

Sources/Paywalls/Events/Networking/EventsRequest+Paywall.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ extension FeatureEventsRequest {
3636
extension FeatureEventsRequest.PaywallEvent {
3737

3838
enum EventType: String {
39-
39+
case startLoading = "start_loading"
40+
case failedToLoad = "failed_to_load"
4041
case impression = "paywall_impression"
4142
case cancel = "paywall_cancel"
4243
case close = "paywall_close"

Sources/Purchasing/Purchases/Purchases.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ public typealias StartPurchaseBlock = (@escaping PurchaseCompletedBlock) -> Void
508508
}
509509
} catch {
510510
Logger.verbose(Strings.paywalls.event_manager_failed_to_initialize(error))
511+
eventsListener?.failedToCreateEventsManager(error: error)
511512
eventsManager = nil
512513
}
513514

@@ -1443,6 +1444,14 @@ public extension Purchases {
14431444
await self.eventsManager?.track(featureEvent: paywallEvent)
14441445
}
14451446

1447+
func trackPaywallStartedLoading(offeringIdentifier: String) async {
1448+
await self.eventsManager?.trackPaywallStartedLoading(offeringIdentifier: offeringIdentifier)
1449+
}
1450+
1451+
func trackPaywallFailedToLoad(offeringIdentifier: String, error: Error) async {
1452+
await self.eventsManager?.trackPaywallFailedToLoad(offeringIdentifier: offeringIdentifier, error: error)
1453+
}
1454+
14461455
/// Used by `RevenueCatUI` to keep track of ``CustomerCenterEvent``s.
14471456
@_spi(Internal) func track(customerCenterEvent: any CustomerCenterEventType) {
14481457
operationDispatcher.dispatchOnWorkerThread {

0 commit comments

Comments
 (0)