Skip to content

Commit 2fcf46c

Browse files
authored
Merge pull request #612 from AppsFlyerSDK/dev/DELIVERY-82509/6.16.2-consent-update
Update to 6.16.2 & AppsFlyerConsent update
2 parents af09dc9 + b13e2e7 commit 2fcf46c

14 files changed

Lines changed: 258 additions & 156 deletions

Docs/RN_CMP.md

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -59,81 +59,123 @@ A CMP compatible with TCF v2.2 collects DMA consent data and stores it in NSUser
5959
}
6060
},[])
6161
```
62-
## Manually collect consent data
63-
If your app does not use a CMP compatible with TCF v2.2, use the SDK API detailed below to provide the consent data directly to the SDK.
64-
65-
### When GDPR applies to the user
66-
If GDPR applies to the user, perform the following:
67-
68-
1. Given that GDPR is applicable to the user, determine whether the consent data is already stored for this session.
69-
1. If there is no consent data stored, show the consent dialog to capture the user consent decision.
70-
2. If there is consent data stored continue to the next step.
71-
2. To transfer the consent data to the SDK create an AppsFlyerConsent object using `forGDPRUser` method that accepts the following parameters:<br>
72-
`hasConsentForDataUsage: boolean` - Indicates whether the user has consented to use their data for advertising purposes.<br>
73-
`hasConsentForAdsPersonalization: boolean` - Indicates whether the user has consented to use their data for personalized advertising.
74-
3. Call `appsFlyer.setConsentData(consentData)` with the AppsFlyerConsent object.
75-
4. Call `appsFlyer.initSdk()`.
62+
63+
### Manually Collecting Consent Data
64+
65+
If your app does not use a TCF v2.2-compatible CMP, you must manually provide the consent data using the SDK API.
66+
67+
How to Set Consent Data: </br>
68+
1. Determine GDPR Applicability:
69+
* If GDPR applies, check whether consent data is already stored.
70+
* If not stored, show a consent dialog to obtain user consent.
71+
2. Create an AppsFlyerConsent object with the relevant parameters.
72+
3. Pass the consent data to the SDK using appsFlyer.setConsentData(consentData).
73+
4. Initialize the SDK with appsFlyer.initSdk().
74+
75+
#### Setting Consent Data for Users
76+
77+
<b>When GDPR Applies</b>
78+
79+
If GDPR applies to the user, create an AppsFlyerConsent object with the user’s preferences.
7680
```javascript
77-
import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer';
81+
import appsFlyer, { AppsFlyerConsent } from 'react-native-appsflyer';
7882

7983
useEffect(() => {
8084
const option = {
81-
isDebug: true,
82-
devKey: 'UxXxXxXxXd',
83-
onInstallConversionDataListener: true,
84-
onDeepLinkListener: true,
85-
timeToWaitForATTUserAuthorization: 10,
85+
isDebug: true,
86+
devKey: 'UxXxXxXxXd',
87+
onInstallConversionDataListener: true,
88+
onDeepLinkListener: true,
89+
timeToWaitForATTUserAuthorization: 10,
8690
};
8791

88-
// user consent data
89-
let consentData = AppsFlyerConsent.forGDPRUser(true, false);
92+
// User has given consent
93+
const consentData = new AppsFlyerConsent(true, true, true, true);
9094

95+
// Send consent data to the SDK
9196
appsFlyer.setConsentData(consentData);
9297

93-
//start appsflyer
98+
// Start AppsFlyer SDK
9499
appsFlyer.initSdk(
95-
option,
96-
res => {
97-
console.log(res);
98-
},
99-
err => {
100-
console.log(err);
101-
},
100+
option,
101+
res => console.log(res),
102+
err => console.log(err)
102103
);
103-
},[])
104+
}, []);
104105
```
105-
### When GDPR does not apply to the user
106106

107-
If GDPR doesn’t apply to the user perform the following:
108-
1. Create an AppsFlyerConsent object using `forNonGDPRUser` method that doesn't accepts any parameters
109-
2. Call `appsFlyer.setConsentData(consentData)` with the AppsFlyerConsent object.
110-
3. Call `appsFlyer.initSdk()`.
107+
<b>When GDPR Does Not Apply</b>
108+
109+
If GDPR does not apply to the user, simply mark it as such in the AppsFlyerConsent object.
111110
```javascript
112-
import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer';
111+
import appsFlyer, { AppsFlyerConsent } from 'react-native-appsflyer';
113112

114113
useEffect(() => {
115114
const option = {
116-
isDebug: true,
117-
devKey: 'UxXxXxXxXd',
118-
onInstallConversionDataListener: true,
119-
onDeepLinkListener: true,
120-
timeToWaitForATTUserAuthorization: 10,
115+
isDebug: true,
116+
devKey: 'UxXxXxXxXd',
117+
onInstallConversionDataListener: true,
118+
onDeepLinkListener: true,
119+
timeToWaitForATTUserAuthorization: 10,
121120
};
122121

123122
// GDPR does not apply to the user
124-
let consentData = AppsFlyerConsent.forNonGDPRUser();
123+
const consentData = new AppsFlyerConsent(false);
125124

126-
appsFlyer.setConsentData(consentData);
125+
// Send consent data to the SDK
126+
appsFlyer.setConsentData(consentData);
127127

128-
//start appsflyer
128+
// Start AppsFlyer SDK
129129
appsFlyer.initSdk(
130-
option,
131-
res => {
132-
console.log(res);
133-
},
134-
err => {
135-
console.log(err);
136-
},
130+
option,
131+
res => console.log(res),
132+
err => console.log(err)
137133
);
138-
},[])
139-
```
134+
}, []);
135+
```
136+
137+
### Consent Object API
138+
139+
```javascript
140+
//AppsFlyerConsent Constructor:
141+
142+
new AppsFlyerConsent(
143+
isUserSubjectToGDPR, // Boolean (optional) - Whether GDPR applies to the user
144+
hasConsentForDataUsage, // Boolean (optional) - Consent for data usage
145+
hasConsentForAdsPersonalization, // Boolean (optional) - Consent for ads personalization
146+
hasConsentForAdStorage // Boolean (optional) - Consent for ad storage
147+
);
148+
149+
//Example Cases:
150+
151+
// Full consent for GDPR user
152+
const consent1 = new AppsFlyerConsent(true, true, true, true);
153+
154+
// No consent for GDPR user
155+
const consent2 = new AppsFlyerConsent(true, false, false, false);
156+
157+
// Non-GDPR user
158+
const consent3 = new AppsFlyerConsent(false);
159+
160+
// AppsFlyerConsent object support the following cases if they are needed.
161+
const consent4 = new AppsFlyerConsent(true);
162+
const consent5 = new AppsFlyerConsent(true, true);
163+
const consent6 = new AppsFlyerConsent(null, true, true, true);
164+
const consent7 = new AppsFlyerConsent(true, null, true, true);
165+
const consent8 = new AppsFlyerConsent(true, true, null, true);
166+
const consent9 = new AppsFlyerConsent(true, true, true, null);
167+
const consent10 = new AppsFlyerConsent(true, true, false, true);
168+
const consent11 = new AppsFlyerConsent(false, true, false, false);
169+
const consent12 = new AppsFlyerConsent(null, null, null, null);
170+
const consent13 = new AppsFlyerConsent();
171+
```
172+
173+
### Deprecation Notice
174+
175+
The following methods have been deprecated since SDK version 6.16.2 and should no longer be used:
176+
```javascript
177+
// Deprecated since 6.16.2
178+
AppsFlyerConsent.forGDPRUser(true, false);
179+
AppsFlyerConsent.forNonGDPRUser();
180+
```
181+
Instead, use the new AppsFlyerConsent constructor.

Docs/RN_Installation.md

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -137,45 +137,6 @@ So `getPackages()` should look like:
137137
}
138138
```
139139

140-
## Android Build Error Due to AGP Version
141-
142-
If you encounter the following error while building your project:
143-
```
144-
Execution failed for task ':app:mergeExtDexDebug'.
145-
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
146-
> Failed to transform af-android-sdk-6.16.0.aar (com.appsflyer:af-android-sdk:6.16.0) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-is-debuggable=true, dexing-min-sdk=21, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}.
147-
> Execution failed for DexingWithClasspathTransform: /Users/amit.levy/.gradle/caches/transforms-3/fb46dcab411d99e4e97f01029413cab1/transformed/jetified-af-android-sdk-6.16.0-runtime.jar.
148-
> Error while dexing.
149-
```
150-
151-
This error occurs if you are using Android Gradle Plugin (AGP) below 8.2.0 due to a known bug in R8.
152-
Google has already resolved this issue
153-
[see Google Issue Tracker](https://issuetracker.google.com/issues/290412574?pli=1).
154-
155-
156-
### Solutions
157-
158-
To fix this issue, you have two options:
159-
1. Upgrade AGP to 8.2.0+ (Recommended):
160-
<br/>Updating AGP to 8.2.0 or later ensures compatibility with the latest R8 version.<br/>Sync and rebuild your project
161-
162-
2. Manually Override the R8 Version
163-
<br/>If upgrading AGP is not an option, you can manually set an external newer R8 version to override the bundled one.
164-
<br/> Open android/build.gradle and add this inside the buildscript {} block then sync and rebuild your project:
165-
```
166-
buildscript {
167-
repositories {
168-
mavenCentral()
169-
maven {
170-
url = uri("https://storage.googleapis.com/r8-releases/raw")
171-
}
172-
}
173-
dependencies {
174-
classpath("com.android.tools:r8:8.2.26")
175-
}
176-
}
177-
```
178-
179140
## Add strict-mode for App-kids
180141
Starting from version **6.1.10** iOS SDK comes in two variants: **Strict** mode and **Regular** mode. Please read more [here](https://dev.appsflyer.com/hc/docs/install-ios-sdk#strict-mode-sdk)
181142

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
- Tested with React-Native **v0.62.0** (older versions might be supported)
1818

1919
## <a id="breaking-changes"> ❗❗ Breaking changes when updating to v6.x.x❗❗
20-
- Starting from version `6.16.0`, Android minimum SDK version is 21.
21-
<br/>Potential Build Issues: If you are using Android Gradle Plugin (AGP) below 8.2.0, you may encounter build errors on Android.
22-
<br/>To resolve this, refer to the [Android Build Error Due to AGP Version](./Docs/RN_Installation.md#android-build-error-due-to-agp-version).
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).
2321

2422
- 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).
2523

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ repositories {
5555
dependencies {
5656
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
5757
implementation "com.android.installreferrer:installreferrer:${safeExtGet('installReferrerVersion', '2.1')}"
58-
api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.16.0')}"
58+
api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.16.2')}"
5959
}

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.16.0";
9+
final static String PLUGIN_VERSION = "6.16.2";
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";

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

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.os.Bundle;
99

1010
import androidx.annotation.NonNull;
11+
import androidx.annotation.Nullable;
1112

1213
import android.util.Log;
1314

@@ -876,17 +877,41 @@ public void enableTCFDataCollection(Boolean enabled) {
876877
}
877878

878879
@ReactMethod
879-
public void setConsentData(ReadableMap consentData) {
880+
public void setConsentData(@Nullable ReadableMap consentData) {
881+
if (consentData == null) {
882+
Log.e("AppsFlyer", "consentData is null");
883+
return;
884+
}
885+
880886
JSONObject JSONConsentData = RNUtil.readableMapToJson(consentData);
881-
boolean isUserSubjectToGDPR = JSONConsentData.optBoolean("isUserSubjectToGDPR");
882-
boolean hasConsentForDataUsage = JSONConsentData.optBoolean("hasConsentForDataUsage");
883-
boolean hasConsentForAdsPersonalization = JSONConsentData.optBoolean("hasConsentForAdsPersonalization");
884-
AppsFlyerConsent consentObject;
885-
if (isUserSubjectToGDPR) {
886-
consentObject = AppsFlyerConsent.forGDPRUser(hasConsentForDataUsage, hasConsentForAdsPersonalization);
887-
} else {
888-
consentObject = AppsFlyerConsent.forNonGDPRUser();
887+
if (JSONConsentData == null) {
888+
Log.e("AppsFlyer", "Failed to convert consentData to JSON");
889+
return;
889890
}
891+
892+
Boolean isUserSubjectToGDPR = JSONConsentData.has("isUserSubjectToGDPR") && !JSONConsentData.isNull("isUserSubjectToGDPR")
893+
? JSONConsentData.optBoolean("isUserSubjectToGDPR")
894+
: null;
895+
896+
Boolean hasConsentForDataUsage = JSONConsentData.has("hasConsentForDataUsage") && !JSONConsentData.isNull("hasConsentForDataUsage")
897+
? JSONConsentData.optBoolean("hasConsentForDataUsage")
898+
: null;
899+
900+
Boolean hasConsentForAdsPersonalization = JSONConsentData.has("hasConsentForAdsPersonalization") && !JSONConsentData.isNull("hasConsentForAdsPersonalization")
901+
? JSONConsentData.optBoolean("hasConsentForAdsPersonalization")
902+
: null;
903+
904+
Boolean hasConsentForAdStorage = JSONConsentData.has("hasConsentForAdStorage") && !JSONConsentData.isNull("hasConsentForAdStorage")
905+
? JSONConsentData.optBoolean("hasConsentForAdStorage")
906+
: null;
907+
908+
AppsFlyerConsent consentObject = new AppsFlyerConsent(
909+
isUserSubjectToGDPR,
910+
hasConsentForDataUsage,
911+
hasConsentForAdsPersonalization,
912+
hasConsentForAdStorage
913+
);
914+
890915
AppsFlyerLib.getInstance().setConsentData(consentObject);
891916
}
892917

babel.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// babel.config.js
2+
module.exports = {
3+
presets: ['module:metro-react-native-babel-preset'],
4+
};

index.d.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,44 @@ declare module "react-native-appsflyer" {
114114
brandDomain?: string;
115115
}
116116

117-
export const AppsFlyerConsent: {
118-
forGDPRUser: (hasConsentForDataUsage: boolean, hasConsentForAdsPersonalization: boolean) => AppsFlyerConsentType;
119-
forNonGDPRUser: () => AppsFlyerConsentType;
117+
export class AppsFlyerConsent {
118+
isUserSubjectToGDPR?: boolean;
119+
hasConsentForDataUsage?: boolean;
120+
hasConsentForAdsPersonalization?: boolean;
121+
hasConsentForAdStorage?: boolean;
122+
123+
/**
124+
* Creates an instance of AppsFlyerConsent.
125+
* @param isUserSubjectToGDPR - Indicates whether GDPR applies to the user.
126+
* @param hasConsentForDataUsage - Indicates whether the user has consented to data usage.
127+
* @param hasConsentForAdsPersonalization - Indicates whether the user has consented to ads personalization.
128+
* @param hasConsentForAdStorage - Indicates whether the user has consented to ad storage.
129+
*/
130+
constructor(
131+
isUserSubjectToGDPR?: boolean,
132+
hasConsentForDataUsage?: boolean,
133+
hasConsentForAdsPersonalization?: boolean,
134+
hasConsentForAdStorage?: boolean
135+
) {}
136+
137+
/**
138+
* @deprecated since version 6.16.2. Use the AppsFlyerConsent constructor instead for more flexibility with optional booleans.
139+
*/
140+
static forGDPRUser(hasConsentForDataUsage: boolean, hasConsentForAdsPersonalization: boolean): AppsFlyerConsent {
141+
return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization);
142+
}
143+
144+
/**
145+
* @deprecated since version 6.16.2. Use the AppsFlyerConsent constructor instead for more flexibility with optional booleans.
146+
*/
147+
static forNonGDPRUser(): AppsFlyerConsent {
148+
return new AppsFlyerConsent(false);
149+
}
120150
}
121151

152+
/**
153+
* @deprecated since version 6.16.2. Use the AppsFlyerConsent class instead for a more integrated approach to consent management.
154+
*/
122155
export interface AppsFlyerConsentType {
123156
isUserSubjectToGDPR: boolean;
124157
hasConsentForDataUsage?: boolean;
@@ -190,7 +223,7 @@ declare module "react-native-appsflyer" {
190223
appendParametersToDeepLinkingURL(contains: string, parameters: object): void
191224
startSdk(): void
192225
enableTCFDataCollection(enabled: boolean): void
193-
setConsentData(consentData: AppsFlyerConsentType): void
226+
setConsentData(consentData: AppsFlyerConsent): void;
194227
logAdRevenue(adRevenueData: AFAdRevenueData) : void
195228
/**
196229
* For iOS Only

0 commit comments

Comments
 (0)