mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-11 22:55:55 +05:45
* Initial setup for paywall control interaction events for v2 paywalls (PWENG-9)
* Use tabs container name for component_name and tab name for component_value (PWENG-9)
* Use tabs container name for tab and toggle control interaction (PWENG-9)
* Introduce paywall control interaction events for legacy paywalls (PWENG-9)
* Align documented code (PWENG-9)
* Fix tvOS 13 build by replacing TapGesture with onTapGesture in FooterView (PWENG-9)
* Fix RevenueCatUITests build by inlining JSON in ToPresentedOverridesTests (PWENG-9)
* Nest paywall control interaction type as PaywallEvent.ControlType (PWENG-9)
* Add componentURL to paywall control interaction events (PWENG-9)
* Add text control type for paywall markdown link analytics (PWENG-9)
* Only track carousel interactions for user drags (PWENG-9)
* Open footer links via OpenURLAction with Link on macOS (PWENG-9)
* Updated documentation for the tab control type (PWENG-9)
* Omit nil name/transition when encoding ButtonComponent (PWENG-9)
* Fix lint errors (PWENG-9)
* Track footer restore tap before restore interceptor (PWENG-9)
* Add CodingKeys for componentUrl in control interaction events (PWENG-9)
* Revert "Add CodingKeys for componentUrl in control interaction events (PWENG-9)"
This reverts commit 57a7525cca.
* Update the control type as a stand-alone enum (PWENG-9)
* Remove trivial unit tests (PWENG-9)
* Update baseline swiftinterface files for `monika/UI-events/paywall-control-interaction` (#6528)
* Remove trivial unit tests (PWENG-9)
* [skip ci] Update baseline swiftinterface files
---------
Co-authored-by: Monika Mateska <monika.mateska@revenuecat.com>
Co-authored-by: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
* Use a fitting parameter name (PWENG-9)
* Track navigation metadata for control interactions
Add navigation metadata (originIndex, destinationIndex, originContextName, destinationContextName, defaultIndex) to paywall control interactions and propagate them through the codebase. Updated PurchaseHandler.trackControlInteraction signature and PaywallEvent.ControlInteractionData to include the new fields and include them in event serialization (FeatureEventsRequest, FeatureEvent map). Updated UI components to populate navigation info: Carousel now reports origin/destination/default page indices and page context names; Tabs now carries tab names/context mapping, initial/default index and reports origin/destination info on selection. Paywall component models now include optional `name` for StackComponent and Tab. Tests and swiftinterface API files were updated accordingly.
* Add PaywallEventTracker and control logger
Introduce PaywallEventTracker to centralize paywall event tracking and provide a lightweight ControlInteractionLogger environment key for views. Refactor PurchaseHandler to delegate event logic to PaywallEventTracker and wire the controlInteractionLogger into paywall views and components (replacing direct PurchaseHandler calls). Update event discriminator from "paywall_control_interaction" to "paywall_component_interacted" and adjust related networking and event mapping. Add unit/UI tests for PaywallEventTracker and ControlInteractionLogger and remove redundant control-interaction tests from PurchaseHandlerTests. Includes background event dispatcher wiring and minor view adjustments to use the new logger.
* Rename control interaction to component interaction
Replace "control"-centric interaction names with "component"-centric ones across the paywall UI and event pipeline. This updates types, methods, environment keys and loggers (e.g. ControlInteraction -> ComponentInteraction), event payload fields and networking mapping, and updates all unit/UITests to match. This standardizes terminology for component interactions (tabs, carousels, buttons, text links) and adjusts the event tracking surface accordingly — note this is a breaking rename for any external API/consumers referencing the old identifiers.
* Rename ControlInteraction to ComponentInteraction
Rename PaywallEvent control interaction API: replace case `controlInteraction` with `componentInteraction`, `ControlInteractionData` with `ComponentInteractionData`, and the `controlInteractionData` property with `componentInteractionData` across platform swiftinterface files (iOS, macOS, tvOS, visionOS, watchOS and their simulators). Updates equality, codable/sendable conformance and encoder/decoder signatures to match the new type name for consistency and clearer naming.
* Use shared PaywallEventTracker instance
Add a private PaywallEventTracker property to PaywallView and PaywallsV2View and pass its componentInteractionLogger into the environment instead of creating a new PaywallEventTracker inline. This ensures a single tracker instance is used for component interaction logging within each view, avoiding ephemeral tracker creation and keeping tracking state consistent.
* Use shared PaywallEventTracker & inject tracker
Add a singleton PaywallEventTracker.shared and wire it into UI and purchasing code. Replace local tracker instances in paywall views with PaywallEventTracker.shared.componentInteractionLogger, and update PurchaseHandler to accept an injectable PaywallEventTracker (defaulting to .shared). Update test helpers and mocks to construct and pass explicit eventTracker instances, adjust LoadingPaywallView test setup to provide a dedicated tracker, and add new source/test files to the Xcode project file. These changes allow deterministic event-tracking in tests and avoid duplicated tracker instances at runtime.
* Remove convenience trackComponentInteraction overload
Remove the parameter-based convenience overload of PaywallEventTracker.trackComponentInteraction and consolidate usage to the single method that accepts PaywallEvent.ComponentInteractionData. Update unit tests to construct ComponentInteractionData via its initializer and call trackComponentInteraction(data) accordingly. This removes duplicated API surface and centralizes event construction.
* Remove EventDispatcher from PurchaseHandler
Remove the EventDispatcher abstraction and related properties from PurchaseHandler: delete the EventDispatcher typealias, backgroundEventDispatcher and testEventDispatcher, and the eventDispatcher stored property and init parameter. Update mapping helpers to stop propagating an eventDispatcher. Update tests and test helpers to pass inline Task { await work() } closures where needed. Files changed: PurchaseHandler.swift, PurchaseHandler+TestData.swift, and related tests in Tests/RevenueCatUITests/Purchasing.
* add name to stack partial
* Update PaywallAPI.swift
* Add testEventDispatcher back to tests
Introduce PaywallEventTracker.testEventDispatcher that uses Task { } (non-detached) so test events inherit caller context and aren't deprioritized by Task.detached(priority: .background) on iOS 26+ CI. Update PurchaseHandler test data and unit tests to pass this test dispatcher when constructing the event tracker to ensure prompt event delivery in tests.
* Add plan-selection metadata to paywall component interaction events
* Add package-selection sheet tracking (PWENG-15)
* [skip ci] Update baseline swiftinterface files (#6564)
* Route paywall control analytics through ComponentInteractionData factories (PWENG-15)
* [skip ci] Update baseline swiftinterface files (#6565)
* Make PaywallEventTracker thread-safe with locked state (PWENG-15)
* Clarify unknown button action telemetry as diagnostics (PWENG-15)
* Isolate paywall analytics state per session in shared tracker (PWENG-15)
* Fix swiftlint issues (PWENG-15)
* Prune PaywallEventTracker session state (PWENG-15)
* Fix ) SPM RevenueCatUl Tests
* Move paywall test event dispatcher out of RevenueCatUI production code (PWENG-15)
* Add purchase button interaction tracking (#6575)
* Add purchase button interaction tracking
Add tracking for purchase button taps: introduce ComponentInteractionType.purchaseButton and a paywallPurchaseButtonAction factory that captures componentName, componentValue, componentURL, currentPackageIdentifier and currentProductIdentifier. Expose componentName and customWebCheckoutUrl on the PurchaseButton view model and log the interaction from PurchaseButtonComponentView before initiating the purchase. Extend PurchaseButtonComponent to include an optional name and make Method conform to CustomStringConvertible to provide stable string values for logging. Update previews to include the new name field where applicable.
Co-Authored-By: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
* Use context-aware web checkout URL
Replace direct use of viewModel.customWebCheckoutUrl with viewModel.urlForWebCheckout(packageContext: packageContext)?.url when logging the purchase button interaction. This ensures the logged componentURL is derived using the current package context (if available) and pulls the URL from the computed web checkout result rather than the raw custom value.
Co-Authored-By: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
* Add tests for purchase button interactions
Add comprehensive tests covering paywall purchase button behavior across components and tracking.
- Tests/RevenueCatUITests/Purchasing/ControlInteractionLoggerTests.swift: add factory tests for PaywallEvent.ComponentInteractionData.paywallPurchaseButtonAction (componentType, name, value, URL, current package/product identifiers, and fully-populated case).
- Tests/RevenueCatUITests/Purchasing/PaywallEventTrackerTests.swift: add tracker tests to ensure component interaction events include purchase button metadata and handle nil name/no-package cases.
- Tests/UnitTests/Paywalls/Components/PurchaseButtonComponentTests.swift: add decoding tests for name present/absent, include name:nil in expected models, add Method.description tests and ComponentInteractionType raw value test.
These tests validate decoding, description strings, raw values, and that tracking records the expected purchase button metadata.
Co-Authored-By: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
* Include name in PurchaseButtonComponent eq/hash
Add `name` to the PurchaseButtonComponent Hashable and Equatable implementations. This ensures instances with different `name` values produce distinct hashes and are not considered equal, preventing incorrect comparisons or collection behavior.
Co-Authored-By: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
* [skip ci] Update baseline swiftinterface files (#6577)
---------
Co-authored-by: Monika Mateska <45938914+MonikaMateska@users.noreply.github.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
* Route paywall component interaction logger through PurchaseHandler (PWENG-15)
* Log V1 purchase button component interactions (PWENG-30)
* Consolidate ComponentInteractionData factory extensions (PWENG-15)
* Defer Paywalls V2 purchase button analytics until checkout is resolved (PWENG-30)
* Fix lint issue (PWENG-15)
* Use NSLock.withLock instead of custom perform (PWENG-15)
* Fix failing test (PWENG-15)
* Fix failing tests (PWENG-15)
* Log Paywalls V2 purchase button interaction before purchase gate (PWENG-15)
* Fallback tier selector interaction value to tier id (PWENG-15)
* Record paywall_close before session reset on UIKit dismiss (PWENG-15)
* Fix lint issues (PWENG-15)
* Expose tier selector interaction value for tests (PWENG-15)
* correct modifers
* Emit paywall close after exit offer dismiss (PWENG-15)
* Consolidate PaywallsV2 impression tracking and eligibility in addPaywallModifiers (PWENG-15)
* Derive tab toggle from selectedTabId to avoid sync race (PWENG-15)
* Fix lint issue (PWENG-15)
* Fix lint issue (PWENG-15)
* Clear tab package selection when user picks a root-only package (PWENG-15)
* Fix Swift 5.8 compile error in purchase button method description (PWENG-15)
---------
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Co-authored-by: Alexander Repty <alexander.repty@mac.com>
Co-authored-by: Jacob Rakidzich <Jacob@JacobZivanDesign.com>
Co-authored-by: Alexander Repty <alex.repty@revenuecat.com>