From 426f1da0559e20988bb1be18a3b63884c2604da8 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Mon, 10 Nov 2025 15:29:00 +0000 Subject: [PATCH 1/4] feat(firebase_analytics): add `logInAppPurchase` support for iOS and Android --- .../lib/src/firebase_analytics.dart | 55 +++++++++++++++++++ .../lib/firebase_analytics_web.dart | 3 + 2 files changed, 58 insertions(+) diff --git a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart index 0676996ca2ad..3bdd6e042f22 100755 --- a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart @@ -1205,6 +1205,40 @@ class FirebaseAnalytics extends FirebasePluginPlatform { ); } + /// Logs the standard `in_app_purchase` event. + /// + /// This event signifies that an item(s) was purchased by a user. + /// + /// This API supports manually logging in-app purchase events on iOS and Android. + /// This is especially useful in cases where purchases happen outside the native + /// billing systems (e.g. custom payment flows). + Future logInAppPurchase({ + String? currency, + bool? freeTrial, + double? price, + bool? priceIsDiscounted, + String? productID, + String? productName, + int? quantity, + bool? subscription, + num? value, + }) { + return _delegate.logEvent( + name: 'in_app_purchase', + parameters: filterOutNulls({ + _CURRENCY: currency, + _FREE_TRIAL: freeTrial, + _PRICE: price, + _PRICE_IS_DISCOUNTED: priceIsDiscounted, + _PRODUCT_ID: productID, + _PRODUCT_NAME: productName, + _QUANTITY: quantity, + _SUBSCRIPTION: subscription, + _VALUE: value, + }), + ); + } + /// Sets the duration of inactivity that terminates the current session. /// /// The default value is 1800000 milliseconds (30 minutes). @@ -1547,3 +1581,24 @@ const String _PROMOTION_ID = 'promotion_id'; /// The name of a product promotion const String _PROMOTION_NAME = 'promotion_name'; + +/// Whether the purchase is a free trial +const String _FREE_TRIAL = 'free_trial'; + +/// The price of the item +const String _PRICE = 'price'; + +/// Whether the price is discounted +const String _PRICE_IS_DISCOUNTED = 'price_is_discounted'; + +/// The ID of the product +const String _PRODUCT_ID = 'product_id'; + +/// The name of the product +const String _PRODUCT_NAME = 'product_name'; + +/// The quantity of the product +const String _QUANTITY = 'quantity'; + +/// Whether the purchase is a subscription +const String _SUBSCRIPTION = 'subscription'; diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart b/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart index b16554ec508e..8899f60bcbf8 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart @@ -70,6 +70,9 @@ class FirebaseAnalyticsWeb extends FirebaseAnalyticsPlatform { Map? parameters, AnalyticsCallOptions? callOptions, }) async { + if (name == 'in_app_purchase') { + throw UnimplementedError('in_app_purchase() is not supported on Web.'); + } return convertWebExceptions(() { return _delegate.logEvent( name: name, From e6c3e6df96753e309621457d3a7b671c43bbbcd0 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Mon, 17 Nov 2025 14:11:48 +0000 Subject: [PATCH 2/4] feat(firebase_analytics): restrict `logInAppPurchase` to iOS --- .../firebase_analytics/lib/firebase_analytics.dart | 2 ++ .../firebase_analytics/lib/src/firebase_analytics.dart | 3 +++ .../firebase_analytics_web/lib/firebase_analytics_web.dart | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart index 0b526dcc6eb4..3ce699bfaa9f 100644 --- a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + import 'package:firebase_analytics_platform_interface/firebase_analytics_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' diff --git a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart index 3bdd6e042f22..8d8697e36dba 100755 --- a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart @@ -1223,6 +1223,9 @@ class FirebaseAnalytics extends FirebasePluginPlatform { bool? subscription, num? value, }) { + if (!Platform.isIOS) { + throw UnimplementedError('logInAppPurchase() is only supported on iOS.'); + } return _delegate.logEvent( name: 'in_app_purchase', parameters: filterOutNulls({ diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart b/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart index 8899f60bcbf8..b16554ec508e 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/firebase_analytics_web.dart @@ -70,9 +70,6 @@ class FirebaseAnalyticsWeb extends FirebaseAnalyticsPlatform { Map? parameters, AnalyticsCallOptions? callOptions, }) async { - if (name == 'in_app_purchase') { - throw UnimplementedError('in_app_purchase() is not supported on Web.'); - } return convertWebExceptions(() { return _delegate.logEvent( name: name, From 2a8d6c803bdf172b500883a2f9a9d394753d7073 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Tue, 18 Nov 2025 11:16:08 +0000 Subject: [PATCH 3/4] chore: update `logInAppPurchase` to use `defaultTargetPlatform` for iOS check --- .../firebase_analytics/lib/firebase_analytics.dart | 2 -- .../firebase_analytics/lib/src/firebase_analytics.dart | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart index 3ce699bfaa9f..0b526dcc6eb4 100644 --- a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:io'; - import 'package:firebase_analytics_platform_interface/firebase_analytics_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' diff --git a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart index 8d8697e36dba..de6f0d57f630 100755 --- a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart @@ -1223,7 +1223,7 @@ class FirebaseAnalytics extends FirebasePluginPlatform { bool? subscription, num? value, }) { - if (!Platform.isIOS) { + if (defaultTargetPlatform != TargetPlatform.iOS) { throw UnimplementedError('logInAppPurchase() is only supported on iOS.'); } return _delegate.logEvent( From 26d775f31130f08ff92f25f8ff594278d4c27077 Mon Sep 17 00:00:00 2001 From: Jude Kwashie Date: Wed, 19 Nov 2025 11:19:50 +0000 Subject: [PATCH 4/4] test: add test for `logInAppPurchase` --- .../firebase_analytics_e2e_test.dart | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/integration_test/firebase_analytics/firebase_analytics_e2e_test.dart b/tests/integration_test/firebase_analytics/firebase_analytics_e2e_test.dart index 9b302593cbf6..f7d309a3b306 100644 --- a/tests/integration_test/firebase_analytics/firebase_analytics_e2e_test.dart +++ b/tests/integration_test/firebase_analytics/firebase_analytics_e2e_test.dart @@ -170,6 +170,27 @@ void main() { ); }); + test( + 'logInAppPurchase', + () async { + await expectLater( + FirebaseAnalytics.instance.logInAppPurchase( + currency: 'USD', + freeTrial: false, + price: 4.99, + priceIsDiscounted: false, + productID: 'com.example.product', + productName: 'Example Product', + quantity: 1, + subscription: true, + value: 4.99, + ), + completes, + ); + }, + skip: defaultTargetPlatform != TargetPlatform.iOS, + ); + test('setUserId', () async { await expectLater( FirebaseAnalytics.instance.setUserId(id: 'foo'),