react-native-google-mobile-ads 5.0.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/RNGoogleMobileAds.podspec +1 -1
  2. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java +19 -5
  3. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.java +1 -1
  4. package/docs/common-reasons-for-ads-not-showing.mdx +26 -24
  5. package/docs/displaying-ads-hook.mdx +99 -0
  6. package/docs/displaying-ads.mdx +3 -4
  7. package/docs/european-user-consent.mdx +34 -5
  8. package/docs/index.mdx +13 -13
  9. package/docs/migrating-to-v5.mdx +17 -8
  10. package/docs.json +2 -1
  11. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m +14 -0
  12. package/lib/commonjs/AdsConsent.js +47 -16
  13. package/lib/commonjs/AdsConsent.js.map +1 -1
  14. package/lib/commonjs/AdsConsentPurposes.js +47 -0
  15. package/lib/commonjs/AdsConsentPurposes.js.map +1 -0
  16. package/lib/commonjs/AdsConsentSpecialFeatures.js +39 -0
  17. package/lib/commonjs/AdsConsentSpecialFeatures.js.map +1 -0
  18. package/lib/commonjs/hooks/useAppOpenAd.js +51 -0
  19. package/lib/commonjs/hooks/useAppOpenAd.js.map +1 -0
  20. package/lib/commonjs/hooks/useFullScreenAd.js +120 -0
  21. package/lib/commonjs/hooks/useFullScreenAd.js.map +1 -0
  22. package/lib/commonjs/hooks/useInterstitialAd.js +51 -0
  23. package/lib/commonjs/hooks/useInterstitialAd.js.map +1 -0
  24. package/lib/commonjs/hooks/useRewardedAd.js +51 -0
  25. package/lib/commonjs/hooks/useRewardedAd.js.map +1 -0
  26. package/lib/commonjs/index.js +40 -0
  27. package/lib/commonjs/index.js.map +1 -1
  28. package/lib/commonjs/types/AdStates.js +6 -0
  29. package/lib/commonjs/types/AdStates.js.map +1 -0
  30. package/lib/commonjs/version.js +1 -1
  31. package/lib/commonjs/version.js.map +1 -1
  32. package/lib/module/AdsConsent.js +44 -16
  33. package/lib/module/AdsConsent.js.map +1 -1
  34. package/lib/module/AdsConsentPurposes.js +39 -0
  35. package/lib/module/AdsConsentPurposes.js.map +1 -0
  36. package/lib/module/AdsConsentSpecialFeatures.js +31 -0
  37. package/lib/module/AdsConsentSpecialFeatures.js.map +1 -0
  38. package/lib/module/hooks/useAppOpenAd.js +38 -0
  39. package/lib/module/hooks/useAppOpenAd.js.map +1 -0
  40. package/lib/module/hooks/useFullScreenAd.js +109 -0
  41. package/lib/module/hooks/useFullScreenAd.js.map +1 -0
  42. package/lib/module/hooks/useInterstitialAd.js +38 -0
  43. package/lib/module/hooks/useInterstitialAd.js.map +1 -0
  44. package/lib/module/hooks/useRewardedAd.js +38 -0
  45. package/lib/module/hooks/useRewardedAd.js.map +1 -0
  46. package/lib/module/index.js +5 -0
  47. package/lib/module/index.js.map +1 -1
  48. package/lib/module/types/AdStates.js +2 -0
  49. package/lib/module/types/AdStates.js.map +1 -0
  50. package/lib/module/version.js +1 -1
  51. package/lib/module/version.js.map +1 -1
  52. package/lib/typescript/AdsConsentPurposes.d.ts +148 -0
  53. package/lib/typescript/AdsConsentSpecialFeatures.d.ts +22 -0
  54. package/lib/typescript/hooks/useAppOpenAd.d.ts +9 -0
  55. package/lib/typescript/hooks/useFullScreenAd.d.ts +5 -0
  56. package/lib/typescript/hooks/useInterstitialAd.d.ts +9 -0
  57. package/lib/typescript/hooks/useRewardedAd.d.ts +9 -0
  58. package/lib/typescript/index.d.ts +6 -1
  59. package/lib/typescript/types/AdStates.d.ts +85 -0
  60. package/lib/typescript/types/AdsConsent.interface.d.ts +216 -0
  61. package/lib/typescript/version.d.ts +1 -1
  62. package/package.json +6 -2
  63. package/src/AdsConsent.ts +75 -20
  64. package/src/AdsConsentPurposes.ts +182 -0
  65. package/src/AdsConsentSpecialFeatures.ts +48 -0
  66. package/src/hooks/useAppOpenAd.ts +46 -0
  67. package/src/hooks/useFullScreenAd.ts +104 -0
  68. package/src/hooks/useInterstitialAd.ts +46 -0
  69. package/src/hooks/useRewardedAd.ts +46 -0
  70. package/src/index.ts +5 -0
  71. package/src/types/AdStates.ts +87 -0
  72. package/src/types/AdsConsent.interface.ts +220 -0
  73. package/src/version.ts +1 -1
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
19
19
  s.social_media_url = 'http://twitter.com/invertaseio'
20
20
  s.ios.deployment_target = "10.0"
21
21
  s.source_files = 'ios/**/*.{h,m}'
22
- s.frameworks = "AppTrackingTransparency"
22
+ s.weak_frameworks = "AppTrackingTransparency"
23
23
 
24
24
  # React Native dependencies
25
25
  s.dependency 'React-Core'
@@ -16,11 +16,13 @@ package io.invertase.googlemobileads;
16
16
  * limitations under the License.
17
17
  *
18
18
  */
19
-
19
+ import android.content.SharedPreferences;
20
+ import android.preference.PreferenceManager;
20
21
  import com.facebook.react.bridge.Arguments;
21
22
  import com.facebook.react.bridge.Promise;
22
23
  import com.facebook.react.bridge.ReactApplicationContext;
23
24
  import com.facebook.react.bridge.ReactMethod;
25
+ import com.facebook.react.bridge.ReadableArray;
24
26
  import com.facebook.react.bridge.ReadableMap;
25
27
  import com.facebook.react.bridge.WritableMap;
26
28
  import com.google.android.ump.ConsentDebugSettings;
@@ -28,7 +30,6 @@ import com.google.android.ump.ConsentInformation;
28
30
  import com.google.android.ump.ConsentRequestParameters;
29
31
  import com.google.android.ump.UserMessagingPlatform;
30
32
  import io.invertase.googlemobileads.common.ReactNativeModule;
31
- import java.util.List;
32
33
  import javax.annotation.Nonnull;
33
34
 
34
35
  public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
@@ -63,10 +64,10 @@ public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
63
64
  new ConsentDebugSettings.Builder(getApplicationContext());
64
65
 
65
66
  if (options.hasKey("testDeviceIdentifiers")) {
66
- List<Object> devices = options.getArray("testDeviceIdentifiers").toArrayList();
67
+ ReadableArray devices = options.getArray("testDeviceIdentifiers");
67
68
 
68
- for (Object device : devices) {
69
- debugSettingsBuilder.addTestDeviceHashedId((String) device);
69
+ for (int i = 0; i < devices.size(); i++) {
70
+ debugSettingsBuilder.addTestDeviceHashedId(devices.getString(i));
70
71
  }
71
72
  }
72
73
 
@@ -152,4 +153,17 @@ public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
152
153
  public void reset() {
153
154
  consentInformation.reset();
154
155
  }
156
+
157
+ @ReactMethod
158
+ public void getTCString(Promise promise) {
159
+ try {
160
+ SharedPreferences prefs =
161
+ PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext());
162
+ // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
163
+ String tcString = prefs.getString("IABTCF_TCString", null);
164
+ promise.resolve(tcString);
165
+ } catch (Exception e) {
166
+ rejectPromiseWithCodeAndMessage(promise, "consent-string-error", e.toString());
167
+ }
168
+ }
155
169
  }
@@ -117,7 +117,7 @@ public class ReactNativeGoogleMobileAdsModule extends ReactNativeModule {
117
117
  @ReactMethod
118
118
  public void initialize(Promise promise) {
119
119
  MobileAds.initialize(
120
- getContext(),
120
+ getApplicationContext(),
121
121
  new OnInitializationCompleteListener() {
122
122
  @Override
123
123
  public void onInitializationComplete(InitializationStatus initializationStatus) {
@@ -13,6 +13,7 @@ You'll be notified of approval or rejection via email after review.
13
13
 
14
14
  New apps and ad units take some time to activate.
15
15
  Here are common reasons you may not see live impressions immediately:
16
+
16
17
  - It usually takes at least an hour after you create an app or ad unit
17
18
  - Sometimes it can take a few days for ads to appear in new apps or ad units
18
19
  - New iOS apps will not show Google ads until they’re listed in the Apple App Store
@@ -35,6 +36,7 @@ Test devices can either be added in the AdMob UI or programmatically using the G
35
36
  Follow the steps below to add your device as a test device.
36
37
 
37
38
  #### Add your test device in the AdMob UI
39
+
38
40
  For a simple, non-programmatic way to add a test device and test new or existing app builds, use the AdMob UI.
39
41
  [Learn how](https://support.google.com/admob/answer/9691433).
40
42
 
@@ -48,39 +50,39 @@ If you want to test ads in your app as you're developing, follow the steps below
48
50
 
49
51
  3. Check the console for a message that looks like this:
50
52
 
51
- ```
52
- GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers =
53
- @[ @"2077ef9a63d2b398840261c8221a0c9b" ]; // Sample device ID
54
- ```
53
+ ```
54
+ GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers =
55
+ @[ @"2077ef9a63d2b398840261c8221a0c9b" ]; // Sample device ID
56
+ ```
55
57
 
56
- Copy your test device ID to your clipboard.
58
+ Copy your test device ID to your clipboard.
57
59
 
58
60
  4. Check the logcat output for a message that looks like the one below, which shows you your device ID and how to add it as a test device:
59
61
 
60
- ```
61
- I/Ads: Use RequestConfiguration.Builder.setTestDeviceIds(Arrays.asList("33BE2250B43518CCDA7DE426D04EE231"))
62
- to get test ads on this device."
63
- ```
62
+ ```
63
+ I/Ads: Use RequestConfiguration.Builder.setTestDeviceIds(Arrays.asList("33BE2250B43518CCDA7DE426D04EE231"))
64
+ to get test ads on this device."
65
+ ```
64
66
 
65
- Copy your test device ID to your clipboard.
67
+ Copy your test device ID to your clipboard.
66
68
 
67
69
  5. Modify your code to set the test device ID through testDeviceIdentifiers
68
70
 
69
- ```js
70
- import mobileAds from 'react-native-google-mobile-ads';
71
+ ```js
72
+ import mobileAds from 'react-native-google-mobile-ads';
71
73
 
72
- mobileAds()
73
- .setRequestConfiguration({
74
- // An array of test device IDs to add to the allow list.
75
- testDeviceIdentifiers: ["2077ef9a63d2b398840261c8221a0c9b", "EMULATOR"]
76
- })
77
- .then(() => {
78
- // Request config successfully set!
79
- });
80
- ```
74
+ mobileAds()
75
+ .setRequestConfiguration({
76
+ // An array of test device IDs to add to the allow list.
77
+ testDeviceIdentifiers: ['2077ef9a63d2b398840261c8221a0c9b', 'EMULATOR'],
78
+ })
79
+ .then(() => {
80
+ // Request config successfully set!
81
+ });
82
+ ```
81
83
 
82
- 5. Re-run your app. If the ad is a Google ad, you'll see a Test Ad label centered at the top of the ad.
83
- Ads with this Test Ad label are safe to click. Requests, impressions, and clicks on test ads will not show up in your account's reports.
84
+ 6. Re-run your app. If the ad is a Google ad, you'll see a Test Ad label centered at the top of the ad.
85
+ Ads with this Test Ad label are safe to click. Requests, impressions, and clicks on test ads will not show up in your account's reports.
84
86
 
85
87
  ## Emulator vs real device
86
88
 
@@ -89,4 +91,4 @@ In some cases ads won't show up on an emulator but will show up while testing on
89
91
  ## Extra links
90
92
 
91
93
  - Mobile Ads SDK [iOS](https://developers.google.com/admob/ios/quick-start), [Android](https://developers.google.com/admob/android/quick-start)
92
- - [Common reasons for ads not showing](https://support.google.com/admob/answer/9469204)
94
+ - [Common reasons for ads not showing](https://support.google.com/admob/answer/9469204)
@@ -0,0 +1,99 @@
1
+ # Hooks
2
+
3
+ The AdMob package provides hooks to help you to display ads in a functional component with tiny code. The supported ad formats are full-screen ads: App open, Interstitial & Rewarded.
4
+
5
+ ## Load an ad
6
+
7
+ You can create a new ad by adding a corresponding ad type's hook to your component.
8
+
9
+ The first argument of the hook is the "Ad Unit ID".
10
+ For testing, we can use a Test ID, however for production the ID from the
11
+ Google AdMob dashboard under "Ad units" should be used:
12
+
13
+ ```tsx {4-8}
14
+ import { useInterstitialAd, TestIds } from 'react-native-google-mobile-ads';
15
+
16
+ export default function App() {
17
+ const interstitialAd = useInterstitialAd(TestIds.Interstitial, {
18
+ requestNonPersonalizedAdsOnly: true,
19
+ });
20
+
21
+ return <View>{/* ... */}</View>;
22
+ }
23
+ ```
24
+
25
+ > The `adUnitid` parameter can also be used to manage creation and destruction of an ad instance.
26
+ > If `adUnitid` is set or changed, new ad instance will be created and previous ad instance will be destroyed if exists.
27
+ > If `adUnitid` is set to `null`, no ad instance will be created and previous ad instance will be destroyed if exists.
28
+
29
+ The second argument is an additional optional request options object to be sent whilst loading an advert, such as keywords & location.
30
+ Setting additional request options helps AdMob choose better tailored ads from the network. View the [`RequestOptions`](/reference/admob/requestoptions)
31
+ documentation to view the full range of options available.
32
+
33
+ ## Show the ad
34
+
35
+ The hook returns several states and functions to control ad.
36
+
37
+ ```tsx
38
+ import { useInterstitialAd, TestIds } from 'react-native-google-mobile-ads';
39
+
40
+ export default function App({ navigation }) {
41
+ const { isLoaded, isClosed, load, show } = useInterstitialAd(TestIds.Interstitial, {
42
+ requestNonPersonalizedAdsOnly: true,
43
+ });
44
+
45
+ useEffect(() => {
46
+ // Start loading the interstitial straight away
47
+ load();
48
+ }, [load]);
49
+
50
+ useEffect(() => {
51
+ if (isClosed) {
52
+ // Action after the ad is closed
53
+ navigation.navigate('NextScreen');
54
+ }
55
+ }, [isClosed, navigation]);
56
+
57
+ return (
58
+ <View>
59
+ <Button
60
+ title="Navigate to next screen"
61
+ onPress={() => {
62
+ if (isLoaded) {
63
+ show();
64
+ } else {
65
+ // No advert ready to show yet
66
+ navigation.navigate('NextScreen');
67
+ }
68
+ }}
69
+ />
70
+ </View>
71
+ );
72
+ }
73
+ ```
74
+
75
+ The code above immediately starts to load a new advert from the network (via `load()`).
76
+ When user presses button, it checks if the ad is loaded via `isLoaded` value,
77
+ then the `show` function is called and the advert is shown over-the-top of your application.
78
+ Otherwise, if the ad is not loaded, the `navigation.navigate` method is called to navigate to the next screen without showing the ad.
79
+ After the ad is closed, the `isClosed` value is set to `true` and the `navigation.navigate` method is called to navigate to the next screen.
80
+
81
+ If needed, you can reuse the existing hook to load more adverts and show them when required. The states are initialized when the `load` function is called.
82
+
83
+ Return values of the hook are:
84
+
85
+ | Name | Type | Description |
86
+ | :------------- | :--------------------------------- | :----------------------------------------------------------------------------------------------------------------- |
87
+ | isLoaded | boolean | Whether the ad is loaded and ready to to be shown to the user. |
88
+ | isOpened | boolean | Whether the ad is opened. The value is remained `true` even after the ad is closed unless **new ad is requested**. |
89
+ | isClosed | boolean | Whether your ad is dismissed. |
90
+ | isShowing | boolean | Whether your ad is showing. The value is equal with `isOpened && !isClosed`. |
91
+ | error | Error \| undefined | `Error` object throwed during ad load. |
92
+ | reward | [RewardedAdReward](#) \| undefined | Loaded reward item of the Rewarded Ad. Available only in RewardedAd. |
93
+ | isEarnedReward | boolean | Whether the user earned the reward by Rewarded Ad. |
94
+ | load | Function | Start loading the advert with the provided RequestOptions. |
95
+ | show | Function | Show the loaded advert to the user. |
96
+
97
+ > Note that `isOpened` value remains `true` even after the ad is closed.
98
+ > The value changes to `false` when ad is initialized via calling `load()`.
99
+ > To determine whether the ad is currently showing, use `isShowing` value.
@@ -27,11 +27,10 @@ const appOpenAd = AppOpenAd.createForAdRequest(adUnitId, {
27
27
  });
28
28
 
29
29
  // Preload an app open ad
30
- appOpenAd.load()
30
+ appOpenAd.load();
31
31
 
32
32
  // Show the app open ad when user brings the app to the foreground.
33
- appOpenAd.show()
34
-
33
+ appOpenAd.show();
35
34
  ```
36
35
 
37
36
  ### Consider ad expiration
@@ -159,7 +158,7 @@ The purpose of a rewarded ad is to reward users with _something_ after completin
159
158
  as watching a video or submitting an option via an interactive form. If the user completes the action, you can reward them
160
159
  with something (e.g. in-game currency).
161
160
 
162
- To create a new interstitial, call the `createForAdRequest` method from the `RewardedAd` class. The first argument
161
+ To create a new rewarded ad, call the `createForAdRequest` method from the `RewardedAd` class. The first argument
163
162
  of the method is the "Ad Unit ID". For testing, we can use a Test ID, however for production the ID from the
164
163
  Google AdMob dashboard under "Ad units" should be used:
165
164
 
@@ -93,16 +93,45 @@ import { AdsConsent, AdsConsentStatus } from 'react-native-google-mobile-ads';
93
93
 
94
94
  const consentInfo = await AdsConsent.requestInfoUpdate();
95
95
 
96
- if (
97
- consentInfo.isConsentFormAvailable &&
98
- consentInfo.status === AdsConsentStatus.REQUIRED
99
- ) {
96
+ if (consentInfo.isConsentFormAvailable && consentInfo.status === AdsConsentStatus.REQUIRED) {
100
97
  const { status } = await AdsConsent.showForm();
101
98
  }
102
99
  ```
103
100
 
104
101
  > Do not persist the status. You could however store this locally in application state (e.g. React Context) and update the status on every app launch as it may change.
105
102
 
103
+ ### Inspecting consent choices
104
+
105
+ The AdsConsentStatus tells you if you should show the modal to a user or not. Often times you want to run logic based on the user's choices though.
106
+ Especially since the Google Mobile Ads SDK won't show any ads if the user didn't give consent to store and/or access information on the device.
107
+ This library exports a method that returns some of the most relevant consent flags to handle common use cases.
108
+
109
+ ```js
110
+ import { AdsConsent } from 'react-native-google-mobile-ads';
111
+
112
+ const {
113
+ activelyScanDeviceCharacteristicsForIdentification,
114
+ applyMarketResearchToGenerateAudienceInsights,
115
+ createAPersonalisedAdsProfile,
116
+ createAPersonalisedContentProfile,
117
+ developAndImproveProducts,
118
+ measureAdPerformance,
119
+ measureContentPerformance,
120
+ selectBasicAds,
121
+ selectPersonalisedAds,
122
+ selectPersonalisedContent,
123
+ storeAndAccessInformationOnDevice,
124
+ usePreciseGeolocationData,
125
+ } = await AdsConsent.getUserChoices();
126
+
127
+ if (storeAndAccessInformationOnDevice === false) {
128
+ /**
129
+ * The user declined consent for purpose 1,
130
+ * the Google Mobile Ads SDK won't serve ads.
131
+ */
132
+ }
133
+ ```
134
+
106
135
  ### Testing
107
136
 
108
137
  When developing the consent flow, the behavior of the `AdsConsent` responses may not be reliable due to the environment
@@ -136,5 +165,5 @@ It is possible to reset the UMP state for test devices. To reset the ATT state y
136
165
  ```js
137
166
  import { AdsConsent } from 'react-native-google-mobile-ads';
138
167
 
139
- AdsConsent.reset()
168
+ AdsConsent.reset();
140
169
  ```
package/docs/index.mdx CHANGED
@@ -7,21 +7,21 @@ yarn add react-native-google-mobile-ads
7
7
 
8
8
  > On Android, before releasing your app, you must select _Yes, my app contains ads_ in the Google Play Store, Policy, App content, Manage under Ads.
9
9
 
10
- # What does it do
10
+ ## What does it do
11
11
 
12
12
  The AdMob module allows you to display adverts to your users. All adverts are served over the Google AdMob network, meaning
13
13
  a [Google AdMob account](https://apps.admob.com) is required.
14
14
 
15
15
  <YouTube id="9qCxo0D-Sak" />
16
16
 
17
- The module supports three types of Ads:
17
+ The module supports four types of Ads:
18
18
 
19
19
  1. Full screen [App Open Ads](/displaying-ads#app-open-ads).
20
20
  2. Full screen [Interstitial Ads](/displaying-ads#interstitial-ads).
21
21
  3. Full screen [Rewarded Ads](/displaying-ads#rewarded-ads).
22
22
  4. Component based [Banner Ads](/displaying-ads#banner-ads).
23
23
 
24
- # Getting Started
24
+ ## Getting Started
25
25
 
26
26
  A number of steps must be taken and considered before you start serving adverts to your users:
27
27
 
@@ -33,7 +33,7 @@ A number of steps must be taken and considered before you start serving adverts
33
33
  - [Test ads](#test-ads)
34
34
  - [Next Steps](#next-steps)
35
35
 
36
- ## Setting up Google AdMob
36
+ ### Setting up Google AdMob
37
37
 
38
38
  Before you are able to display ads to your users, you must have a [Google AdMob account](https://apps.admob.com). Under the
39
39
  "Apps" menu item, create or choose an existing Android/iOS app. Each app platform exposes a unique account ID which needs to
@@ -62,14 +62,14 @@ For the changes to take effect, rebuild your project:
62
62
 
63
63
  ```bash
64
64
  # For iOS
65
- cd ios/ && pod install
65
+ npx pod-install
66
66
  npx react-native run-ios
67
67
 
68
68
  # For Android
69
69
  npx react-native run-android
70
70
  ```
71
71
 
72
- ## Configure outbound requests
72
+ ### Configure outbound requests
73
73
 
74
74
  If the default ad settings are not correct for your app, you can provide settings that will apply to all ad requests.
75
75
 
@@ -94,7 +94,7 @@ mobileAds()
94
94
  tagForUnderAgeOfConsent: true,
95
95
 
96
96
  // An array of test device IDs to allow.
97
- testDeviceIdentifiers: ["EMULATOR"]
97
+ testDeviceIdentifiers: ['EMULATOR'],
98
98
  })
99
99
  .then(() => {
100
100
  // Request config successfully set!
@@ -103,27 +103,27 @@ mobileAds()
103
103
 
104
104
  To learn more about the request configuration settings, view the [`RequestConfiguration`](/reference/admob/requestconfiguration) documentation.
105
105
 
106
- ## Initialize the Google Mobile Ads SDK
106
+ ### Initialize the Google Mobile Ads SDK
107
107
 
108
108
  Before loading ads, have your app initialize the Google Mobile Ads SDK by calling `initialize` which initializes the SDK and returns a promise once initialization is complete (or after a 30-second timeout).
109
109
  This needs to be done only once, ideally at app launch.
110
110
 
111
111
  > ⚠️ **Warning:** Ads may be preloaded by the Mobile Ads SDK or mediation partner SDKs upon calling `initialize`.
112
- If you need to obtain consent from users in the European Economic Area (EEA), set any request-specific flags (such as tagForChildDirectedTreatment), or otherwise take action before loading ads, ensure you do so before initializing the Mobile Ads SDK.
112
+ > If you need to obtain consent from users in the European Economic Area (EEA), set any request-specific flags (such as tagForChildDirectedTreatment), or otherwise take action before loading ads, ensure you do so before initializing the Mobile Ads SDK.
113
113
 
114
114
  ```js
115
115
  import mobileAds from 'react-native-google-mobile-ads';
116
116
 
117
117
  mobileAds()
118
118
  .initialize()
119
- .then((adapterStatuses) => {
119
+ .then(adapterStatuses => {
120
120
  // Initialization complete!
121
121
  });
122
122
  ```
123
123
 
124
124
  If you are using mediation, you may wish to wait until the promise is settled before loading ads, as this will ensure that all mediation adapters are initialized.
125
125
 
126
- ## European User Consent
126
+ ### European User Consent
127
127
 
128
128
  Out of the box, AdMob does not handle any related regulations which you may need to enforce on your application.
129
129
  It is up to the developer to implement and handle this on a user-by-user basis. You must consent to EEA users
@@ -133,7 +133,7 @@ being served both personalized and non-personalized adverts before showing them.
133
133
  The AdMob module provides a `AdsConsent` helper to help developers quickly implement consent flows within their application.
134
134
  See the [European User Consent page](/european-user-consent) for full examples of how to integrate the helper into your application.
135
135
 
136
- ## Test ads
136
+ ### Test ads
137
137
 
138
138
  Whilst developing your app with AdMob, you'll want to make sure you use test ads rather than production ads from your
139
139
  Google AdMob account - otherwise your account may be disabled!
@@ -157,7 +157,7 @@ RewardedAd.createForAdRequest(TestIds.REWARDED);
157
157
  <BannerAd unitId={TestIds.BANNER} />
158
158
  ```
159
159
 
160
- # Next Steps
160
+ ## Next Steps
161
161
 
162
162
  Now the basics of setting up and configuring AdMob have been explained, we can go ahead and start to display different
163
163
  adverts to our users. The AdMob module provides integration with three different types:
@@ -13,13 +13,13 @@ Please refer to the following links for more information:
13
13
 
14
14
  Previously it was possible to request the ad providers and to update the consent status. This is no longer the case.
15
15
  Also, while the old Consent SDK provided information about user preferences, the new `AdsConsentStatus` only tells you if you should show the modal to a user or not.
16
- You can read the `IABTCF_TCString` key from standardUserDefaults / SharedPreferences and decode it with a library like [@iabtcf/core](https://github.com/InteractiveAdvertisingBureau/iabtcf-es/tree/master/modules/core#iabtcfcore) though.
17
16
 
18
- * `requestInfoUpdate` does now accept an optional `AdsConsentInfoOptions` object instead of expecting `publisherIds` and returns a changed `AdsConsentInfo` interface
19
- * `showForm` does not expect any parameters any longer and now only returns the changed `AdsConsentStatus` as part of it's `AdsConsentFormResult` interface
20
- * `getAdProviders`, `getStatus` and `setStatus` methods were removed without replacements
21
- * `addTestDevices`, `setDebugGeography` and `setTagForUnderAgeOfConsent` methods were removed, but their functionality is available via `AdsConsentInfoOptions`
22
- * the `user_tracking_usage_description` key is needed in your project's `app.json` if you want to handle Apple's App Tracking Transparency
17
+ - `requestInfoUpdate` does now accept an optional `AdsConsentInfoOptions` object instead of expecting `publisherIds` and returns a changed `AdsConsentInfo` interface
18
+ - `showForm` does not expect any parameters any longer and now only returns the changed `AdsConsentStatus` as part of it's `AdsConsentFormResult` interface
19
+ - `getAdProviders`, `getStatus` and `setStatus` methods were removed without replacements
20
+ - `addTestDevices`, `setDebugGeography` and `setTagForUnderAgeOfConsent` methods were removed, but their functionality is available via `AdsConsentInfoOptions`
21
+ - the `user_tracking_usage_description` key is needed in your project's `app.json` if you want to handle Apple's App Tracking Transparency
22
+ - newly added `getUserChoices` can be used to inspect some of the consent choices
23
23
 
24
24
  ```diff
25
25
  {
@@ -33,10 +33,10 @@ You can read the `IABTCF_TCString` key from standardUserDefaults / SharedPrefere
33
33
 
34
34
  ```diff
35
35
  import { AdsConsent, AdsConsentStatus } from 'react-native-google-mobile-ads';
36
-
36
+
37
37
  -const consentInfo = await AdsConsent.requestInfoUpdate(['pub-6189033257628123']);
38
38
  +const consentInfo = await AdsConsent.requestInfoUpdate();
39
-
39
+
40
40
  if (
41
41
  - consentInfo.isRequestLocationInEeaOrUnknown &&
42
42
  + consentInfo.isConsentFormAvailable &&
@@ -50,5 +50,14 @@ You can read the `IABTCF_TCString` key from standardUserDefaults / SharedPrefere
50
50
  - withAdFree: true,
51
51
  - });
52
52
  + const formResult = await AdsConsent.showForm()
53
+ +
54
+ + const { storeAndAccessInformationOnDevice } = await AdsConsent.getUserChoices();
55
+ +
56
+ + if (storeAndAccessInformationOnDevice === false) {
57
+ + /**
58
+ + * The user declined consent for purpose 1,
59
+ + * the Google Mobile Ads SDK won't serve ads.
60
+ + */
61
+ + }
53
62
  }
54
63
  ```
package/docs.json CHANGED
@@ -4,8 +4,9 @@
4
4
  "sidebar": [
5
5
  ["Installation", "/"],
6
6
  ["Displaying Ads", "/displaying-ads"],
7
+ ["Displaying Ads via Hook", "/displaying-ads-hook"],
7
8
  ["European User Consent", "/european-user-consent"],
8
9
  ["Common Reasons For Ads Not Showing", "/common-reasons-for-ads-not-showing"],
9
10
  ["Migrating to v5", "/migrating-to-v5"]
10
11
  ]
11
- }
12
+ }
@@ -121,4 +121,18 @@ RCT_EXPORT_METHOD(showForm : (RCTPromiseResolveBlock)resolve : (RCTPromiseReject
121
121
 
122
122
  RCT_EXPORT_METHOD(reset) { [UMPConsentInformation.sharedInstance reset]; }
123
123
 
124
+ RCT_EXPORT_METHOD(getTCString : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
125
+ @try {
126
+ // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
127
+ NSString *tcString = [[NSUserDefaults standardUserDefaults] objectForKey:@"IABTCF_TCString"];
128
+ resolve(tcString);
129
+ } @catch (NSError *error) {
130
+ [RNSharedUtils rejectPromiseWithUserInfo:reject
131
+ userInfo:[@{
132
+ @"code" : @"consent-string-error",
133
+ @"message" : error.localizedDescription,
134
+ } mutableCopy]];
135
+ }
136
+ }
137
+
124
138
  @end
@@ -5,12 +5,18 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.AdsConsent = void 0;
7
7
 
8
- var _common = require("./common");
8
+ var _core = require("@iabtcf/core");
9
9
 
10
10
  var _reactNative = require("react-native");
11
11
 
12
12
  var _AdsConsentDebugGeography = require("./AdsConsentDebugGeography");
13
13
 
14
+ var _AdsConsentPurposes = require("./AdsConsentPurposes");
15
+
16
+ var _AdsConsentSpecialFeatures = require("./AdsConsentSpecialFeatures");
17
+
18
+ var _common = require("./common");
19
+
14
20
  /*
15
21
  * Copyright (c) 2016-present Invertase Limited & Contributors
16
22
  *
@@ -29,14 +35,6 @@ var _AdsConsentDebugGeography = require("./AdsConsentDebugGeography");
29
35
  */
30
36
  const native = _reactNative.NativeModules.RNGoogleMobileAdsConsentModule;
31
37
  const AdsConsent = {
32
- /**
33
- *
34
- * @param {Object} [options]
35
- * @param {AdsConsentDebugGeography} [options.debugGeography]
36
- * @param {Boolean} [options.tagForUnderAgeOfConsent]
37
- * @param {Array<String>} [options.testDeviceIdentifiers]
38
- * @returns {{ status: Number, isConsentFormAvailable: Boolean }}
39
- */
40
38
  requestInfoUpdate() {
41
39
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
42
40
 
@@ -69,19 +67,52 @@ const AdsConsent = {
69
67
  return native.requestInfoUpdate(options);
70
68
  },
71
69
 
72
- /**
73
- *
74
- * @returns {{ status: Number }}
75
- */
76
70
  showForm() {
77
71
  return native.showForm();
78
72
  },
79
73
 
80
- /**
81
- *
82
- */
83
74
  reset() {
84
75
  return native.reset();
76
+ },
77
+
78
+ getTCString() {
79
+ return native.getTCString();
80
+ },
81
+
82
+ async getTCModel() {
83
+ const tcString = await native.getTCString();
84
+ return _core.TCString.decode(tcString);
85
+ },
86
+
87
+ async getUserChoices() {
88
+ const tcString = await native.getTCString();
89
+ let tcModel;
90
+
91
+ try {
92
+ tcModel = _core.TCString.decode(tcString);
93
+ } catch (e) {
94
+ tcModel = new _core.TCModel();
95
+
96
+ if (__DEV__) {
97
+ // eslint-disable-next-line no-console
98
+ console.warn(`Failed to decode tcString ${tcString}:`, e);
99
+ }
100
+ }
101
+
102
+ return {
103
+ activelyScanDeviceCharacteristicsForIdentification: tcModel.specialFeatureOptins.has(_AdsConsentSpecialFeatures.AdsConsentSpecialFeatures.ACTIVELY_SCAN_DEVICE_CHARACTERISTICS_FOR_IDENTIFICATION),
104
+ applyMarketResearchToGenerateAudienceInsights: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.APPLY_MARKET_RESEARCH_TO_GENERATE_AUDIENCE_INSIGHTS),
105
+ createAPersonalisedAdsProfile: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.CREATE_A_PERSONALISED_ADS_PROFILE),
106
+ createAPersonalisedContentProfile: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.CREATE_A_PERSONALISED_ADS_PROFILE),
107
+ developAndImproveProducts: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.DEVELOP_AND_IMPROVE_PRODUCTS),
108
+ measureAdPerformance: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.MEASURE_AD_PERFORMANCE),
109
+ measureContentPerformance: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.MEASURE_CONTENT_PERFORMANCE),
110
+ selectBasicAds: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.SELECT_BASIC_ADS),
111
+ selectPersonalisedAds: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.SELECT_PERSONALISED_ADS),
112
+ selectPersonalisedContent: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.SELECT_PERSONALISED_CONTENT),
113
+ storeAndAccessInformationOnDevice: tcModel.purposeConsents.has(_AdsConsentPurposes.AdsConsentPurposes.STORE_AND_ACCESS_INFORMATION_ON_DEVICE),
114
+ usePreciseGeolocationData: tcModel.specialFeatureOptins.has(_AdsConsentSpecialFeatures.AdsConsentSpecialFeatures.USE_PRECISE_GEOLOCATION_DATA)
115
+ };
85
116
  }
86
117
 
87
118
  };