invertase / react-native-google-mobile-ads

React Native Google Mobile Ads enables you to monetize your app with AdMob.
https://docs.page/invertase/react-native-google-mobile-ads
Other
688 stars 139 forks source link

[๐Ÿ“š] requestNonPersonalizedAdsOnly - need help with understanding usage of this #482

Closed kurtgn closed 9 months ago

kurtgn commented 11 months ago

The current docs say:

requestNonPersonalizedAdsOnly must be true if users who are within the EEA have only given consent to non-personalized ads.

but how do I detect if they have only given consent to non-personalized ads?

The getUserChoices() method provides us with a list of available flags to look at:

  activelyScanDeviceCharacteristicsForIdentification,
  applyMarketResearchToGenerateAudienceInsights,
  createAPersonalisedAdsProfile,
  createAPersonalisedContentProfile,
  developAndImproveProducts,
  measureAdPerformance,
  measureContentPerformance,
  selectBasicAds,
  selectPersonalisedAds,
  selectPersonalisedContent,
  storeAndAccessInformationOnDevice,
  usePreciseGeolocationData,
} = await AdsConsent.getUserChoices();

but which one should we look at while determining if we should set requestNonPersonalizedAdsOnly to true?

Is this createAPersonalisedContentProfile? or selectPersonalisedAds? or selectPersonalisedContent? or something else?

mikehardy commented 11 months ago

With apologies, I believe this will be better answered in the admob forums or stackoverflow. Definitely open to a PR to our docs here but as this kind of information changes somewhat rapidly (meaning the docs go stale...) a PR here might be best if restricted to a link that points to an authoritative source

StCyr commented 11 months ago

please update your doc :-)

dylancom commented 11 months ago

Please submit a PR, this package is a community effort :-)

StCyr commented 11 months ago

I would gladly do that should I understand how this work :-)

I'm very new to advertising, so I still need to do a lot of troubleshooting before getting things rights. I'm not even sure I'm correctly following GDPR rules...

...

Hahaha I see that I'm not the only one struggling to get things rights: even the "Mobile Ads SDK Forum Advisor" user contradicts himself at https://groups.google.com/g/google-admob-ads-sdk/c/HB3ApoxDnWs/m/JsoUxJKRBAAJ

StCyr commented 11 months ago

For the record, I've come up to the following code which seems to be GDPR compliant

        // Try to show ad if user hasn't subscribed to a paying version of the app
        // For the moment, we just let the user use the app freely if he doesn't give consent for ads
        if (! await isUserSubscribed()) {
            // User hasn't subscribed to a paying version of the app, we'll try to show him/her ads. 

            // Checks if we need to re-ask consent (eg: due to conditions change at provider-side)
            const consentInfo = await AdsConsent.requestInfoUpdate()            
            console.log('Checking if we need to ask user consent')
            if (consentInfo.status !== 'OBTAINED') {
                // Asks consent
                console.log('Asking user consent')
                await AdsConsent.loadAndShowConsentFormIfRequired();
            }

            // Shows ad if user gaves enough consent
            const userChoice = await AdsConsent.getUserChoices();
            console.log('checking user choice')
            if (userChoice.storeAndAccessInformationOnDevice) {
                // Initializes ads
                console.log('Ok we got user consent to display ads')
                mobileAds().initialize().then(() => {
                    let requestOptions = { requestNonPersonalizedAdsOnly: true }
                    if (userChoice.selectPersonalisedContent) {
                        console.log('Not for personalised ads though')
                        requestOptions = {}
                    }   
                    const appOpenAd = AppOpenAd.createForAdRequest("ca-app-pub-xxxxxxxxxx", requestOptions)
                    appOpenAd.addAdEventListener(AdEventType.LOADED, () => {
                        console.log('Showing ad')
                        appOpenAd.show()
                    });
                    console.log('Loading ad')
                    appOpenAd.load()
                })
            } else {
                // For the moment, we just let the user use the app freely if he doesn't give consent for ads
                console.log('User did not gave enough consent to use admob (missing "storeAndAccessInformationOnDevice" right)')
            }
        }

However, today appOpenAd.load() doesn't seem to work as I can't use appOpenAd.show() for some reason... It happens sometime, so I'll retry later and let you know....

Also, it seems userChoice.selectPersonalisedContent is not the correct flag... :-(

StCyr commented 11 months ago

well fsck, wathever I do as a user, all the flags are set to false:

LOG checking user choice {"activelyScanDeviceCharacteristicsForIdentification": false, "applyMarketResearchToGenerateAudienceInsights": false, "createAPersonalisedAdsProfile": false, "createAPersonalisedContentProfile": false, "developAndImproveProducts": false, "measureAdPerformance": false, "measureContentPerformance": false, "selectBasicAds": false, "selectPersonalisedAds": false, "selectPersonalisedContent": false, "storeAndAccessInformationOnDevice": false, "usePreciseGeolocationData": false}

StCyr commented 11 months ago

found this which might be of interested: https://github.com/invertase/react-native-google-mobile-ads/issues/274#issuecomment-1320654501

StCyr commented 11 months ago

ok the error I got was due to https://github.com/invertase/react-native-google-mobile-ads/issues/484

StCyr commented 11 months ago

Ok, when I click on "Authorise", I authorise everything:

{"activelyScanDeviceCharacteristicsForIdentification": false, "applyMarketResearchToGenerateAudienceInsights": true, "createAPersonalisedAdsProfile": true, "createAPersonalisedContentProfile": true, "developAndImproveProducts": true, "measureAdPerformance": true, "measureContentPerformance": true, "selectBasicAds": true, "selectPersonalisedAds": true, "selectPersonalisedContent": true, "storeAndAccessInformationOnDevice": true, "usePreciseGeolocationData": true}

If I only authorise storage and access information on device with legitimate interest disabled by default in google admobs:

{"activelyScanDeviceCharacteristicsForIdentification": false, "applyMarketResearchToGenerateAudienceInsights": false, "createAPersonalisedAdsProfile": false, "createAPersonalisedContentProfile": false, "developAndImproveProducts": false, "measureAdPerformance": false, "measureContentPerformance": false, "selectBasicAds": false, "selectPersonalisedAds": false, "selectPersonalisedContent": false, "storeAndAccessInformationOnDevice": true, "usePreciseGeolocationData": false}

If I only authorise storage and access information on device with legitimate interest enabled by default in google admobs (doesn't change a thing):

{"activelyScanDeviceCharacteristicsForIdentification": false, "applyMarketResearchToGenerateAudienceInsights": false, "createAPersonalisedAdsProfile": false, "createAPersonalisedContentProfile": false, "developAndImproveProducts": false, "measureAdPerformance": false, "measureContentPerformance": false, "selectBasicAds": false, "selectPersonalisedAds": false, "selectPersonalisedContent": false, "storeAndAccessInformationOnDevice": true, "usePreciseGeolocationData": false}

If I authorise storage and access information on device and allow "select personalised ads" (with legitimate interest enabled by default in google admobs but that's not important):

{"activelyScanDeviceCharacteristicsForIdentification": false, "applyMarketResearchToGenerateAudienceInsights": false, "createAPersonalisedAdsProfile": false, "createAPersonalisedContentProfile": false, "developAndImproveProducts": false, "measureAdPerformance": false, "measureContentPerformance": false, "selectBasicAds": false, "selectPersonalisedAds": true, "selectPersonalisedContent": false, "storeAndAccessInformationOnDevice": true, "usePreciseGeolocationData": false}

2 things that I find interesting here:

  1. the selectPersonalisedAds is true but createAPersonalisedAdsProfile is false: I wonder how this works since selectPersonalisedAds is explained as "Personalised Ads may be shown based on a profile created for you" (translated from French)... Oh, actualy the detailed explanation of this setting is "select personalised ads based on a user profile OR other user historical data,....". So, probably the personalised ads are selected only based on user historical data in this case...
  2. selectBasicAds is false so showing non-personalised ads is probabaly a GDPR infraction
StCyr commented 11 months ago

so to replay to @kurtgn:

It's funny that the user may allow to create a profile (createAPersonalisedAdsProfile=true) but forbid its use (selectPersonalisedAds=false)... Well, actualy user doesn't forbid its use, he only forbids its use for displaying personalised ads in this particular app (so I guess advertiser won't mind using it to associate it with data coming from other apps/websites and enrich it for later use in another app....)

StCyr commented 11 months ago

For the record, I've come up to the following code which seems to be GDPR compliant

      // Try to show ad if user hasn't subscribed to a paying version of the app
      // For the moment, we just let the user use the app freely if he doesn't give consent for ads
      if (! await isUserSubscribed()) {
          // User hasn't subscribed to a paying version of the app, we'll try to show him/her ads. 

          // Checks if we need to re-ask consent (eg: due to conditions change at provider-side)
          const consentInfo = await AdsConsent.requestInfoUpdate()            
          console.log('Checking if we need to ask user consent')
          if (consentInfo.status !== 'OBTAINED') {
              // Asks consent
              console.log('Asking user consent')
              await AdsConsent.loadAndShowConsentFormIfRequired();
          }

          // Shows ad if user gaves enough consent
          const userChoice = await AdsConsent.getUserChoices();
          console.log('checking user choice')
          if (userChoice.storeAndAccessInformationOnDevice) {
              // Initializes ads
              console.log('Ok we got user consent to display ads')
              mobileAds().initialize().then(() => {
                  let requestOptions = { requestNonPersonalizedAdsOnly: true }
                  if (userChoice.selectPersonalisedContent) {
                      console.log('Not for personalised ads though')
                      requestOptions = {}
                  }   
                  const appOpenAd = AppOpenAd.createForAdRequest("ca-app-pub-xxxxxxxxxx", requestOptions)
                  appOpenAd.addAdEventListener(AdEventType.LOADED, () => {
                      console.log('Showing ad')
                      appOpenAd.show()
                  });
                  console.log('Loading ad')
                  appOpenAd.load()
              })
          } else {
              // For the moment, we just let the user use the app freely if he doesn't give consent for ads
              console.log('User did not gave enough consent to use admob (missing "storeAndAccessInformationOnDevice" right)')
          }
      }

However, today appOpenAd.load() doesn't seem to work as I can't use appOpenAd.show() for some reason... It happens sometime, so I'll retry later and let you know....

Also, it seems userChoice.selectPersonalisedContent is not the correct flag... :-(

Eventualy, with https://github.com/invertase/react-native-google-mobile-ads/issues/484 solved, my code works like a charm :-)

StCyr commented 11 months ago

Eventualy, with #484 solved, my code works like a charm :-)

Oh no! today it doesn't work... it seems the AdEventType.LOADED event is never fired :-(

LukasMod commented 11 months ago

I'm also trying to somehow gather these flags into some sort of logical grouping to control what happens in the app and make personalized ads independent of, say, performance tracking. I've noticed that there is a lot of confusion in the information on this topic, and I haven't found any certainty about how it should look. I point out that this is just my suggestion, after reading the comments in AdsConsent.interface.ts and #274(comment). We don't implement a complete ad blocker, because it's a goal and revenue, so the user only decides whether to personalize it.

Currently I have 3 groups where I check if the whole set of values is true. The number means that it was reused.

  1. personalized ads

    • createAPersonalisedAdsProfile
    • selectPersonalisedAds
    • selectBasicAds
    • measureAdPerformance (1)
    • applyMarketResearchToGenerateAudienceInsights (1)
    • storeAndAccessInformationOnDevice (1)
    • developAndImproveProducts (1)
  2. Preferences (content):

    • createAPersonalisedContentProfile
    • selectPersonalisedContent
    • measureContentPerformance (1)
    • storeAndAccessInformationOnDevice (2)
    • developAndImproveProducts (2)
  3. Tracking, events, performance:

    • activelyScanDeviceCharacteristicsForIdentification
    • measureAdPerformance (2)
    • measureContentPerformance (2)
    • storeAndAccessInformationOnDevice (3)
    • developAndImproveProducts (3)

Not used at all:

Maybe it will help someone, I mapped each single consent from CMP form and checked answer from userChoices(). Few can't be currently set at all.

image
haresh4d commented 11 months ago

When user dont give consent I am serving non personalized ads but still no ads are displayed not even non personalized.

LukasMod commented 11 months ago

Consent is still required to show non personalized ads (based on google docs)

If the consent requirements for personalized ads are not met, Google will serve non-personalized ads when all of the following criteria are met:

The end user grants Google consent to: Store and/or access information on a device (Purpose 1) Legitimate interest (or consent, where a publisher configures their CMP to request it) is established for Google to: Select basic ads (Purpose 2) Measure ad performance (Purpose 7) Apply market research to generate audience insights (Purpose 9) Develop and improve products (Purpose 10)

mikehardy commented 11 months ago

Interesting, just posting this specific chunk from @LukasMod 's excellent link:

If you do not have consent for Google for Purpose 1 (Store and/or access information on a device), you should not call Googleโ€™s ad tag.

Because

For non-personalized ads, consent for cookies or mobile identifiers is still required because non-personalized ads still use cookies or mobile identifiers to combat fraud and abuse, for frequency capping, and for aggregated ad reporting.

So there is a minimum consent ('store and/or access information on a device') required for ads of any kind. What to do based on whether the user grants this or not will be a project-specific decision I suppose

akaoppa commented 10 months ago

I don't even know why they used a variable in negation ? It's kinda frustrating imo. "requestNonPersonalizedAdsOnly" It should be requestPersonalizedAds ? TRUE OR FALSE

I have put below, what it should be TRUE for ads and non ads personalized to appear :

    // Personalized Ads: require purpose 1, 2, 3, 4, 7, 9, 10
    //Non PersonalizedAds: require purpose 1, 2, 7, 9, 10

const { activelyScanDeviceCharacteristicsForIdentification, applyMarketResearchToGenerateAudienceInsights, createAPersonalisedAdsProfile, createAPersonalisedContentProfile, developAndImproveProducts, measureAdPerformance, measureContentPerformance, selectBasicAds, selectPersonalisedAds, selectPersonalisedContent, storeAndAccessInformationOnDevice, usePreciseGeolocationData, } = await AdsConsent.getUserChoices();

    console.log('storeAndAccessInformationOnDevice:', storeAndAccessInformationOnDevice); //purpose 1
    console.log('selectBasicAds:', selectBasicAds); //purpose 2
    console.log('createAPersonalisedAdsProfile:', createAPersonalisedAdsProfile); //purpose 3
    console.log('selectPersonalisedAds:', selectPersonalisedAds); //purpose 4
    console.log('measureAdPerformance:', measureAdPerformance); //purpose 7
    console.log('applyMarketResearchToGenerateAudienceInsights:', applyMarketResearchToGenerateAudienceInsights); //purpose 9
    console.log('developAndImproveProducts:', developAndImproveProducts); //purpose 10

    console.log('activelyScanDeviceCharacteristicsForIdentification:', activelyScanDeviceCharacteristicsForIdentification);
    console.log('createAPersonalisedContentProfile:', createAPersonalisedContentProfile);
    console.log('selectPersonalisedContent:', selectPersonalisedContent);
    console.log('measureContentPerformance:', measureContentPerformance); 
    console.log('usePreciseGeolocationData:', usePreciseGeolocationData);
github-actions[bot] commented 9 months ago

Hello ๐Ÿ‘‹, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.