Skip to content

Commit 3806778

Browse files
authoredFeb 19, 2024
Merge pull request #527 from AppsFlyerSDK/releases/6.x.x/6.13.x/6.13.0-rc2
Releases/6.x.x/6.13.x/6.13.0 rc2
2 parents fe3b80d + 2635e1d commit 3806778

20 files changed

+365
-28
lines changed
 

‎CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 6.13.0
2+
Release date: *2024-02-19*
3+
4+
- Add DMA support
5+
- Fix incompatible config for RN >= 0.69.x
6+
- Update Plugin to v6.13.0
7+
18
## 6.12.2
29
Release date: *2023-08-29*
310

‎Docs/RN_API.md

+47
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ The list of available methods for this plugin is described below.
3535
- [addPushNotificationDeepLinkPath](#addpushnotificationdeeplinkpath)
3636
- [appendParametersToDeepLinkingURL](#appendparameterstodeeplinkingurl)
3737
- [disableAdvertisingIdentifier](#disableAdvertisingIdentifier)
38+
- [enableTCFDataCollection](#enableTCFDataCollection)
39+
- [setConsentData](#setConsentData)
3840
- [Android Only APIs](#android-only-apis)
3941
- [setCollectAndroidID](#setcollectandroidid)
4042
- [setCollectIMEI](#setcollectimei)
@@ -750,6 +752,51 @@ Disables collection of various Advertising IDs by the SDK.<br>
750752
appsFlyer.disableAdvertisingIdentifier(true);
751753
```
752754

755+
---
756+
### enableTCFDataCollection
757+
`enableTCFDataCollection(enabled): void`
758+
759+
instruct the SDK to collect the TCF data from the device.
760+
761+
762+
| parameter | type | description |
763+
| ---------- |----------|------------------ |
764+
| enabled | boolean | enable/disable TCF data collection |
765+
766+
*Example:*
767+
768+
```javascript
769+
appsFlyer.enableTCFDataCollection(true);
770+
```
771+
772+
---
773+
### setConsentData
774+
`setConsentData(consentObject): void`
775+
776+
When GDPR applies to the user and your app does not use a CMP compatible with TCF v2.2, use this API to provide the consent data directly to the SDK.<br>
777+
The AppsFlyerConsent object has 2 methods:
778+
779+
1. `AppsFlyerConsent.forNonGDPRUser`: Indicates that GDPR doesn’t apply to the user and generates nonGDPR consent object. This method doesn’t accept any parameters.
780+
2. `AppsFlyerConsent.forGDPRUser`: create an AppsFlyerConsent object with 2 parameters:
781+
782+
783+
| parameter | type | description |
784+
| ---------- |----------|------------------ |
785+
| hasConsentForDataUsage | boolean | Indicates whether the user has consented to use their data for advertising purposes |
786+
| hasConsentForAdsPersonalization | boolean | Indicates whether the user has consented to use their data for personalized advertising |
787+
788+
*Example:*
789+
790+
```javascript
791+
import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer';
792+
793+
let nonGDPRUser = AppsFlyerConsent.forNonGDPRUser();
794+
// OR
795+
let GDPRUser = AppsFlyerConsent.forGDPRUser(true, false);
796+
797+
appsFlyer.setConsentData(nonGDPRUser /**or**/ GDPRUser);
798+
```
799+
753800
## Android Only APIs
754801

755802
### setCollectAndroidID

‎Docs/RN_CMP.md

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
title: Send consent for DMA compliance
3+
category: 5f9705393c689a065c409b23
4+
parentDoc: 645213236f53a00d4daa9230
5+
order: 12
6+
hidden: false
7+
---
8+
9+
## Send consent for DMA compliance
10+
The SDK offers two alternative methods for gathering consent data:
11+
12+
Through a Consent Management Platform (CMP): If the app uses a CMP that complies with the Transparency and Consent Framework (TCF) v2.2 protocol, the SDK can automatically retrieve the consent details.
13+
14+
OR
15+
16+
Through a dedicated SDK API: Developers can pass Google's required consent data directly to the SDK using a specific API designed for this purpose.
17+
18+
### Use CMP to collect consent data
19+
A CMP compatible with TCF v2.2 collects DMA consent data and stores it in NSUserDefaults (iOS) and SharedPreferences (Android). To enable the SDK to access this data and include it with every event, follow these steps:
20+
21+
1. Call `appsFlyer.enableTCFDataCollection(true)`
22+
2. Initialize the SDK in [manual start mode](/Docs/RN_API.md#initsdk)
23+
3. Use the CMP to decide if you need the consent dialog in the current session to acquire the consent data. If you need the consent dialog move to step 4; otherwise move to step 5
24+
4. Get confirmation from the CMP that the user has made their consent decision and the data is available in NSUserDefaults/SharedPreferences
25+
5. Call `appsFlyer.startSdk()`
26+
```javascript
27+
useEffect(() => {
28+
const option = {
29+
isDebug: true,
30+
devKey: 'UxXxXxXxXd',
31+
onInstallConversionDataListener: true,
32+
onDeepLinkListener: true,
33+
timeToWaitForATTUserAuthorization: 10,
34+
manualStart: true, // <-- Manual start
35+
};
36+
// TCF data collection
37+
appsFlyer.enableTCFDataCollection(true);
38+
39+
//init appsflyer
40+
appsFlyer.initSdk(
41+
option,
42+
res => {
43+
console.log(res);
44+
},
45+
err => {
46+
console.log(err);
47+
},
48+
);
49+
50+
...
51+
52+
// CMP Pseudocode
53+
if (cmpManager.hasConsent()) {
54+
appsFlyer.startSdk();
55+
} else {
56+
cmpManager.presentConsentDialog(res => {
57+
appsFlyer.startSdk();
58+
});
59+
}
60+
},[])
61+
```
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()`.
76+
```javascript
77+
import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer';
78+
79+
useEffect(() => {
80+
const option = {
81+
isDebug: true,
82+
devKey: 'UxXxXxXxXd',
83+
onInstallConversionDataListener: true,
84+
onDeepLinkListener: true,
85+
timeToWaitForATTUserAuthorization: 10,
86+
};
87+
88+
// user consent data
89+
let consentData = AppsFlyerConsent.forGDPRUser(true, false);
90+
91+
appsFlyer.setConsentData(consentData);
92+
93+
//start appsflyer
94+
appsFlyer.initSdk(
95+
option,
96+
res => {
97+
console.log(res);
98+
},
99+
err => {
100+
console.log(err);
101+
},
102+
);
103+
},[])
104+
```
105+
### When GDPR does not apply to the user
106+
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()`.
111+
```javascript
112+
import appsFlyer, {AppsFlyerConsent} from 'react-native-appsflyer';
113+
114+
useEffect(() => {
115+
const option = {
116+
isDebug: true,
117+
devKey: 'UxXxXxXxXd',
118+
onInstallConversionDataListener: true,
119+
onDeepLinkListener: true,
120+
timeToWaitForATTUserAuthorization: 10,
121+
};
122+
123+
// GDPR does not apply to the user
124+
let consentData = AppsFlyerConsent.forNonGDPRUser();
125+
126+
appsFlyer.setConsentData(consentData);
127+
128+
//start appsflyer
129+
appsFlyer.initSdk(
130+
option,
131+
res => {
132+
console.log(res);
133+
},
134+
err => {
135+
console.log(err);
136+
},
137+
);
138+
},[])
139+
```

‎Docs/RN_UserInvite.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The link that is generated for the user invite will use this OneLink ID as the b
3636

3737
```javascript
3838

39-
// set the tamplate ID before you generate a link. Without it UserInvite won't work.
39+
// set the template ID before you generate a link. Without it UserInvite won't work.
4040
appsFlyer.setAppInviteOneLinkID('scVs', null);
4141

4242
// set the user invite params

‎README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
1313
### <a id="plugin-build-for"> This plugin is built for
1414

15-
- Android AppsFlyer SDK **v6.12.2**
16-
- iOS AppsFlyer SDK **v6.12.2**
15+
- Android AppsFlyer SDK **v6.13.0**
16+
- iOS AppsFlyer SDK **v6.13.0**
1717

1818
## <a id="breaking-changes"> ❗❗ Breaking changes when updating to v6.x.x❗❗
1919

@@ -51,6 +51,7 @@ If you have used 1 of the removed APIs, please check the integration guide for t
5151
- [Test integration](/Docs/RN_Testing.md)
5252
- [In-app events](/Docs/RN_InAppEvents.md)
5353
- [Uninstall measurement](/Docs/RN_UninstallMeasurement.md)
54+
- [Send consent for DMA compliance](/Docs/RN_CMP.md)
5455
## 🔗 Deep Linking
5556
- [Integration](/Docs/RN_DeepLinkIntegrate.md)
5657
- [***Expo*** Integration](/Docs/RN_ExpoDeepLinkIntegration.md)

‎android/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,5 @@ repositories {
5454
dependencies {
5555
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
5656
implementation "com.android.installreferrer:installreferrer:${safeExtGet('installReferrerVersion', '2.1')}"
57-
api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.12.2')}"
57+
api "com.appsflyer:af-android-sdk:${safeExtGet('appsflyerVersion', '6.13.0')}"
5858
}

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

+1-1
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.12.2";
9+
final static String PLUGIN_VERSION = "6.13.0";
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

+21-1
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,27 @@ public void performOnDeepLinking() {
815815
Log.d("AppsFlyer", "performOnDeepLinking: activity is null!");
816816
}
817817
}
818-
818+
819+
@ReactMethod
820+
public void enableTCFDataCollection(Boolean enabled) {
821+
AppsFlyerLib.getInstance().enableTCFDataCollection(enabled);
822+
}
823+
824+
@ReactMethod
825+
public void setConsentData(ReadableMap consentData) {
826+
JSONObject JSONConsentData = RNUtil.readableMapToJson(consentData);
827+
boolean isUserSubjectToGDPR = JSONConsentData.optBoolean("isUserSubjectToGDPR");
828+
boolean hasConsentForDataUsage = JSONConsentData.optBoolean("hasConsentForDataUsage");
829+
boolean hasConsentForAdsPersonalization = JSONConsentData.optBoolean("hasConsentForAdsPersonalization");
830+
AppsFlyerConsent consentObject;
831+
if (isUserSubjectToGDPR) {
832+
consentObject = AppsFlyerConsent.forGDPRUser(hasConsentForDataUsage, hasConsentForAdsPersonalization);
833+
} else {
834+
consentObject = AppsFlyerConsent.forNonGDPRUser();
835+
}
836+
AppsFlyerLib.getInstance().setConsentData(consentObject);
837+
}
838+
819839
@ReactMethod
820840
public void addListener(String eventName) {
821841
// Keep: Required for RN built in Event Emitter Calls.

‎demos/appsflyer-react-native-app/android/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ buildscript {
44
ext {
55
buildToolsVersion = "30.0.2"
66
minSdkVersion = 21
7-
compileSdkVersion = 31
8-
targetSdkVersion = 31
7+
compileSdkVersion = 32
8+
targetSdkVersion = 32
99
ndkVersion = "20.1.5948944"
1010
}
1111
repositories {

‎demos/appsflyer-react-native-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"react-native-elements": "^3.4.2",
1919
"react-native-gesture-handler": "^1.10.3",
2020
"react-native-safe-area-context": "^3.3.2",
21-
"react-native-screens": "^3.7.0",
22-
"react-native-vector-icons": "^8.1.0"
21+
"react-native-screens": "3.7.2",
22+
"react-native-vector-icons": "8.1.0"
2323
},
2424
"devDependencies": {
2525
"@babel/core": "^7.12.9",

‎index.d.ts

+9
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ declare module "react-native-appsflyer" {
114114
brandDomain?: string;
115115
}
116116

117+
export const AppsFlyerConsent: {
118+
forGDPRUser: (hasConsentForDataUsage: boolean, hasConsentForAdsPersonalization: boolean) => void;
119+
forNonGDPRUser: () => void;
120+
}
121+
122+
export type AppsFlyerConsentType = typeof AppsFlyerConsent;
123+
117124
const appsFlyer: {
118125
onInstallConversionData(callback: (data: ConversionData) => any): () => void;
119126
onInstallConversionFailure(callback: (data: ConversionData) => any): () => void;
@@ -151,6 +158,8 @@ declare module "react-native-appsflyer" {
151158
setPartnerData(partnerId: string, partnerData: object): void
152159
appendParametersToDeepLinkingURL(contains: string, parameters: object): void
153160
startSdk(): void
161+
enableTCFDataCollection(enabled: boolean): void
162+
setConsentData(consentData: AppsFlyerConsentType): void
154163

155164
/**
156165
* For iOS Only

‎index.js

+39-1
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,48 @@ appsFlyer.performOnDeepLinking = () => {
625625
return RNAppsFlyer.performOnDeepLinking();
626626
};
627627

628+
/**
629+
* instruct the SDK to collect the TCF data from the device.
630+
* @param enabled: if the sdk should collect the TCF data. true/false
631+
*/
632+
appsFlyer.enableTCFDataCollection= (enabled) => {
633+
return RNAppsFlyer.enableTCFDataCollection(enabled);
634+
}
635+
636+
/**
637+
* 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.
638+
* @param consentData: AppsFlyerConsent object.
639+
*/
640+
appsFlyer.setConsentData = (consentData) => {
641+
return RNAppsFlyer.setConsentData(consentData);
642+
}
643+
628644
function AFParseJSONException(_message, _data) {
629645
this.message = _message;
630646
this.data = _data;
631647
this.name = 'AFParseJSONException';
632648
}
633649

634-
export default appsFlyer;
650+
// Consent object
651+
export const AppsFlyerConsent = (function () {
652+
// Private constructor
653+
function AppsFlyerConsent(isUserSubjectToGDPR, hasConsentForDataUsage, hasConsentForAdsPersonalization) {
654+
this.isUserSubjectToGDPR = isUserSubjectToGDPR;
655+
this.hasConsentForDataUsage = hasConsentForDataUsage;
656+
this.hasConsentForAdsPersonalization = hasConsentForAdsPersonalization;
657+
}
658+
659+
return {
660+
// Factory method for GDPR user
661+
forGDPRUser: function(hasConsentForDataUsage, hasConsentForAdsPersonalization) {
662+
return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization);
663+
},
664+
665+
// Factory method for non GDPR user
666+
forNonGDPRUser: function() {
667+
return new AppsFlyerConsent(false, null, null);
668+
}
669+
};
670+
})();
671+
672+
export default appsFlyer;

0 commit comments

Comments
 (0)
Please sign in to comment.