Skip to content

Commit c0ebcb0

Browse files
committed
Plugin update to 6.17.1
Podspec hotfix, readme update, plugin update
1 parent efebda7 commit c0ebcb0

7 files changed

Lines changed: 98 additions & 70 deletions

File tree

Docs/RN_PurchaseConnector.md

Lines changed: 86 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ For more information please check the following pages:
3838
- [Subscription Purchase Data Source](#subscription-purchase-data-source)
3939
- [In-App Purchase Data Source](#in-app-purchase-data-source)
4040
- [Platform-Specific Implementation](#platform-specific-implementation)
41+
- [Logging Consumable Transactions](#logging-consumable-transactions)
4142
- [Important Notes](#important-notes)
4243

4344
## <a id="important-note"></a>Important Note ⚠️ ⚠️
4445

4546
The Purchase Connector feature of the AppsFlyer SDK depends on specific libraries provided by Google and Apple for managing in-app purchases:
4647

47-
- For Android, it depends on the [Google Play Billing Library](https://developer.android.com/google/play/billing/integrate) (Supported versions: 5.x.x - 6.x.x).
48-
- For iOS, it depends on [StoreKit](https://developer.apple.com/documentation/storekit).
48+
- For Android, it depends on the [Google Play Billing Library](https://developer.android.com/google/play/billing/integrate) (Supported versions: 5.x.x - 7.x.x).
49+
- For iOS, it depends on [StoreKit](https://developer.apple.com/documentation/storekit) (Supported versions: StoreKit1 and StoreKit2 (beta)).
4950

5051
However, these dependencies aren't actively included with the SDK. This means that the responsibility of managing these dependencies and including the necessary libraries in your project falls on you as the consumer of the SDK.
5152

@@ -125,6 +126,7 @@ For example:
125126
logSubscriptions: true,
126127
logInApps: true,
127128
sandbox: true,
129+
storeKitVersion: StoreKitVersion.SK2
128130
});
129131

130132
// purchaseConnector1 and purchaseConnector2 point to the same instance
@@ -149,9 +151,10 @@ Start the SDK instance to observe transactions. </br>
149151

150152
appsFlyer.startSdk();
151153
const purchaseConnectorConfig: PurchaseConnectorConfig = AppsFlyerPurchaseConnectorConfig.setConfig({
152-
logSubscriptions: true,
153-
logInApps: true,
154-
sandbox: true,
154+
logSubscriptions: true,
155+
logInApps: true,
156+
sandbox: true,
157+
storeKitVersion: StoreKitVersion.SK2
155158
});
156159

157160
//Create the object
@@ -318,15 +321,20 @@ Add following keep rules to your `proguard-rules.pro` file:
318321

319322
## <a id="full-code-example"></a>Full Code Example
320323
```javascript
321-
const purchaseConnectorConfig: PurchaseConnectorConfig = AppsFlyerPurchaseConnectorConfig.setConfig({
324+
import appsFlyer, {
325+
StoreKitVersion,
326+
AppsFlyerPurchaseConnector,
327+
AppsFlyerPurchaseConnectorConfig,
328+
} from 'react-native-appsflyer';
329+
330+
const purchaseConnectorConfig = AppsFlyerPurchaseConnectorConfig.setConfig({
322331
logSubscriptions: true,
323332
logInApps: true,
324333
sandbox: true,
334+
storeKitVersion: StoreKitVersion.SK2
325335
});
326336

327-
AppsFlyerPurchaseConnector.create(
328-
purchaseConnectorConfig,
329-
);
337+
AppsFlyerPurchaseConnector.create(purchaseConnectorConfig);
330338

331339
const handleValidationSuccess = (validationResult) => {
332340
console.log('>> ValidationSuccess: ', validationResult);
@@ -417,14 +425,13 @@ AppsFlyerPurchaseConnector.setPurchaseRevenueDataSource({
417425
```javascript
418426
// Set additional parameters for StoreKit2 purchases
419427
AppsFlyerPurchaseConnector.setPurchaseRevenueDataSourceStoreKit2({
420-
products: [
421-
{ product_id: 'com.app.subscription.monthly' },
422-
{ product_id: 'com.app.subscription.yearly' }
423-
],
424-
transactions: [
425-
{ transaction_id: 'transaction123' },
426-
{ transaction_id: 'transaction456' }
427-
]
428+
additionalParameters: {
429+
user_id: '12345',
430+
user_type: 'premium',
431+
purchase_source: 'app_store',
432+
custom_param1: 'value1',
433+
custom_param2: 'value2'
434+
}
428435
});
429436
```
430437

@@ -469,7 +476,7 @@ When implementing these data sources in your app, you should consider the platfo
469476

470477
```javascript
471478
import { Platform } from 'react-native';
472-
import AppsFlyerPurchaseConnector from 'react-native-appsflyer-plugin';
479+
import { AppsFlyerPurchaseConnector } from 'react-native-appsflyer';
473480

474481
const setupPurchaseDataSources = () => {
475482
if (Platform.OS === 'ios') {
@@ -484,12 +491,11 @@ const setupPurchaseDataSources = () => {
484491

485492
// iOS StoreKit2 data source (iOS 15.0+)
486493
AppsFlyerPurchaseConnector.setPurchaseRevenueDataSourceStoreKit2({
487-
products: [
488-
{ product_id: 'com.app.subscription.monthly' }
489-
],
490-
transactions: [
491-
{ transaction_id: 'transaction123' }
492-
]
494+
additionalParameters: {
495+
user_id: '12345',
496+
user_type: 'premium',
497+
purchase_source: 'app_store'
498+
}
493499
});
494500
} else if (Platform.OS === 'android') {
495501
// Android subscription data source
@@ -513,6 +519,59 @@ const setupPurchaseDataSources = () => {
513519
};
514520
```
515521

522+
523+
### <a id="logging-consumable-transactions"></a>Logging Consumable Transactions
524+
525+
On iOS 15 and above, consumable in-app purchases are handled via StoreKit 2. The behavior depends on your iOS version:
526+
527+
- **On iOS 18 and later:**
528+
Apple introduced a new Info.plist flag: `SKIncludeConsumableInAppPurchaseHistory`.
529+
- If you set `SKIncludeConsumableInAppPurchaseHistory` to `YES` in your Info.plist, automatic collection will happen.
530+
- If the flag is not present or is set to `NO`, you must manually log consumable transactions as shown below.
531+
532+
- **On iOS 15–17:**
533+
Consumable purchases must always be logged manually.
534+
535+
To manually log consumable transactions, use the `logConsumableTransaction` method after finishing the transaction:
536+
537+
```javascript
538+
import { Platform } from 'react-native';
539+
import { AppsFlyerPurchaseConnector } from 'react-native-appsflyer';
540+
541+
// Purchase update listener
542+
purchaseUpdatedListener((purchase) => {
543+
console.log("🛒 Purchase updated:", purchase.productId, "Transaction ID:", purchase.transactionId);
544+
const isConsumable = consumablesItems.includes(purchase.productId);
545+
546+
finishTransaction({ purchase, isConsumable })
547+
.then((res) => {
548+
console.log("✅ finishTransaction success:", res);
549+
console.log("🔍 Expecting AppsFlyer validation callback for:", purchase.productId);
550+
551+
// Log consumable transaction for iOS
552+
if (Platform.OS === 'ios' && isConsumable && purchase.transactionId) {
553+
AppsFlyerPurchaseConnector.logConsumableTransaction(purchase.transactionId);
554+
console.log("📝 Consumable transaction logged:", purchase.transactionId);
555+
}
556+
})
557+
.catch((error) => {
558+
console.warn("❌ Error finishing transaction:", error);
559+
});
560+
});
561+
```
562+
563+
### Method Signature
564+
565+
```javascript
566+
AppsFlyerPurchaseConnector.logConsumableTransaction(transactionId: string): void
567+
```
568+
569+
**Parameters:**
570+
- `transactionId` (string): The unique transaction identifier from the App Store transaction
571+
572+
**Note:** This method is iOS-specific and should only be called on iOS devices. On Android, consumable transactions are automatically handled by the Purchase Connector.
573+
574+
516575
### <a id="important-notes"></a>Important Notes
517576

518577
1. **iOS StoreKit2**: The StoreKit2 data source is only available on iOS 15.0 and later. Make sure to check the iOS version before using it.
@@ -525,10 +584,11 @@ const setupPurchaseDataSources = () => {
525584

526585
```javascript
527586
// 1. Create the connector
528-
await AppsFlyerPurchaseConnector.create({
587+
AppsFlyerPurchaseConnector.create({
529588
logSubscriptions: true,
530589
logInApps: true,
531-
sandbox: __DEV__
590+
sandbox: __DEV__,
591+
storeKitVersion: StoreKitVersion.SK2
532592
});
533593

534594
// 2. Set up data sources
@@ -537,5 +597,3 @@ setupPurchaseDataSources();
537597
// 3. Start observing transactions
538598
await AppsFlyerPurchaseConnector.startObservingTransactions();
539599
```
540-
541-
4. **Validation**: The parameters you set will be included in the purchase events sent to AppsFlyer. You can verify this in the AppsFlyer dashboard under the purchase events section.

README.md

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,18 @@
1313
### <a id="plugin-build-for"> This plugin is built for
1414

1515
- Android AppsFlyer SDK **v6.17.0**
16-
- iOS AppsFlyer SDK **v6.17.0**
16+
- iOS AppsFlyer SDK **v6.17.1**
1717
- Tested with React-Native **v0.62.0** (older versions might be supported)
1818

19-
## <a id="breaking-changes"> ❗❗ Breaking changes when updating to v6.x.x❗❗
20-
- From version `6.16.2`, `AppsFlyerConsent.forGDPRUser` and `AppsFlyerConsent.forNonGDPRUser` have been **deprecated**. Use the new `AppsFlyerConsent` constructor instead. See [Deprecation Notice](/Docs/RN_CMP.md#deprecation-notice).
19+
## <a id="release-updates"> Release Updates
2120

22-
- From version `6.15.1`, upgraded to targetSDKVersion 34, Java 17, and Gradle 8.7 in [AppsFlyer Android SDK v6.15.1](https://support.appsflyer.com/hc/en-us/articles/115001256006-AppsFlyer-Android-SDK-release-notes).
21+
- Starting with version 6.17.1 the plugin supports the Purchase Connector for validating and measuring Subscription and In-app purchase events. Integration guide can be found [here](https://github.com/AppsFlyerSDK/appsflyer-react-native-plugin/blob/master/Docs/RN_PurchaseConnector.md).
2322

24-
- From version `6.15.1`, iOS Minimum deployment target is set to 12.0.
23+
- Starting with version `6.16.2`, `AppsFlyerConsent.forGDPRUser` and `AppsFlyerConsent.forNonGDPRUser` have been **deprecated**. Use the new `AppsFlyerConsent` constructor instead. See [Deprecation Notice](/Docs/RN_CMP.md#deprecation-notice).
2524

26-
- From version `6.3.0`, we use `xcframework` for iOS platform. Then you need to use cocoapods version >= 1.10
25+
- Starting with version `6.15.1`, upgraded to targetSDKVersion 34, Java 17, and Gradle 8.7 in [AppsFlyer Android SDK v6.15.1](https://support.appsflyer.com/hc/en-us/articles/115001256006-AppsFlyer-Android-SDK-release-notes).
2726

28-
- From version `6.2.30`, `logCrossPromotionAndOpenStore` api will register as `af_cross_promotion` instead of `af_app_invites` in your dashboard.<br>
29-
Click on a link that was generated using `generateInviteLink` api will be register as `af_app_invites`.
30-
31-
- From version `6.0.0` we have renamed the following APIs:
32-
33-
| Old API | New API |
34-
| ----------------------------- | ----------------------------- |
35-
| trackEvent | logEvent |
36-
| trackLocation | logLocation |
37-
| stopTracking | stop |
38-
| trackCrossPromotionImpression | logCrossPromotionImpression |
39-
| trackAndOpenStore | logCrossPromotionAndOpenStore |
40-
| setDeviceTrackingDisabled | anonymizeUser |
41-
| AppsFlyerTracker | AppsFlyerLib |
42-
43-
And removed the following ones:
44-
45-
- trackAppLaunch -> no longer needed. See new init guide
46-
- sendDeepLinkData -> no longer needed. See new init guide
47-
- enableUninstallTracking -> no longer needed. See new uninstall measurement guide
48-
49-
If you have used 1 of the removed APIs, please check the integration guide for the updated instructions.
27+
- Starting with version `6.15.1`, iOS Minimum deployment target is set to 12.0.
5028

5129
---
5230

android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
public class RNAppsFlyerConstants {
88

9-
final static String PLUGIN_VERSION = "6.17.01";
9+
final static String PLUGIN_VERSION = "6.17.1";
1010
final static String NO_DEVKEY_FOUND = "No 'devKey' found or its empty";
1111
final static String UNKNOWN_ERROR = "AF Unknown Error";
1212
final static String SUCCESS = "Success";

index.d.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,12 @@ declare module "react-native-appsflyer" {
216216

217217
//PurchaseRevenueDataSourceSK1
218218
export interface PurchaseRevenueDataSource {
219-
purchaseRevenueAdditionalParametersForProducts?: (
220-
products: any[], // SKProduct array
221-
transactions: any[] // SKPaymentTransaction array
222-
) => { [key: string]: any } | null;
219+
additionalParameters?: { [key: string]: any };
223220
}
224221

225222
// PurchaseRevenueDataSourceStoreKit2
226223
export interface PurchaseRevenueDataSourceStoreKit2 {
227-
purchaseRevenueAdditionalParametersStoreKit2ForProducts: (
228-
products: any[], // AFSDKProductSK2 array
229-
transactions: any[] // AFSDKTransactionSK2 array
230-
) => { [key: string]: any } | null;
224+
additionalParameters?: { [key: string]: any };
231225
}
232226

233227
// Android interfaces

ios/PCAppsFlyer.m

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,12 @@ @implementation PCAppsFlyer
148148
// Delegate method for StoreKit1
149149
- (NSDictionary *)purchaseRevenueAdditionalParametersForProducts:(NSSet<SKProduct *> *)products
150150
transactions:(NSSet<SKPaymentTransaction *> *)transactions {
151-
// Simply return the parameters that were set from React Native
152151
return self.purchaseRevenueParams;
153152
}
154153

155154
// Delegate method for StoreKit2
156155
- (NSDictionary<NSString *, id> *)purchaseRevenueAdditionalParametersStoreKit2ForProducts:(NSSet<AFSDKProductSK2 *> *)products
157156
transactions:(NSSet<AFSDKTransactionSK2 *> *)transactions {
158-
// Simply return the parameters that were set from React Native
159157
return self.purchaseRevenueStoreKit2Params;
160158
}
161159

ios/RNAppsFlyer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
@end
2323

2424

25-
static NSString *const kAppsFlyerPluginVersion = @"6.17.01";
25+
static NSString *const kAppsFlyerPluginVersion = @"6.17.1";
2626
static NSString *const NO_DEVKEY_FOUND = @"No 'devKey' found or its empty";
2727
static NSString *const NO_APPID_FOUND = @"No 'appId' found or its empty";
2828
static NSString *const NO_EVENT_NAME_FOUND = @"No 'eventName' found or its empty";

react-native-appsflyer.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ Pod::Spec.new do |s|
3636
# AppsFlyerFramework
3737
if defined?($RNAppsFlyerStrictMode) && ($RNAppsFlyerStrictMode == true)
3838
Pod::UI.puts "#{s.name}: Using AppsFlyerFramework/Strict mode"
39-
s.dependency 'AppsFlyerFramework/Strict', '6.17.0'
39+
s.dependency 'AppsFlyerFramework/Strict', '6.17.1'
4040
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) AFSDK_NO_IDFA=1' }
4141
else
4242
if !defined?($RNAppsFlyerStrictMode)
4343
Pod::UI.puts "#{s.name}: Using default AppsFlyerFramework. You may require App Tracking Transparency. Not allowed for Kids apps."
4444
Pod::UI.puts "#{s.name}: You may set variable `$RNAppsFlyerStrictMode=true` in Podfile to use strict mode for kids apps."
4545
end
46-
s.dependency 'AppsFlyerFramework', '6.17.0'
46+
s.dependency 'AppsFlyerFramework', '6.17.1'
4747
end
4848
end

0 commit comments

Comments
 (0)