【问题标题】:How to implement UMP SDK correctly for eu consent?如何正确实施 UMP SDK 以获得欧盟同意?
【发布时间】:2021-03-28 18:47:57
【问题描述】:

我对 UMP SDK 的实现有很多困惑。除了google,我没有找到太多信息或完整的教程。我关注thisthis 但无法理解以下问题:

  1. 征得同意后是否需要拨打MobileAds.initialize()?如果是这样,那么应该在哪里调用它?征得同意后可能会调用:

    public void onConsentFormLoadSuccess(ConsentForm consentForm) {
        if(consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.OBTAINED) {
    }
    }
    
  2. 如何检查用户是否来自 EEA?我想根据用户位置请求同意或初始化移动广告。在Consent SDK 中有一个方法isRequestLocationInEeaOrUnknown(),但是这个SDK 已被弃用。我在 UMP SDK 中没有找到类似的东西。一种方法可能是始终使用requestConsentInfoUpdate 并在onConsentInfoUpdateSuccess 中调用isConsentFormAvailable。如果用户不是来自 EEA,则此方法返回 false。

  3. 我总是得到同意类型 consentInformation.getConsentType() 0 或 UnKnown。我试过different combination,但总是0。

  4. 是否需要将同意信息转发给 AdMob SDK 或 SDK 会处理。

  5. 关于调解,我需要同意信息,但不知道如何获得。来自文档:The UMP SDK writes consent status information to local storage

  6. 在 AdMob -> 欧盟用户同意中,Commonly used set of ad technology providers 中不包含我的一位中介合作伙伴。如果我使用Custom set of ad technology providers,是否需要包括所有Commonly used set of ad technology providers,其中有198 个广告技术提供商。或者在 Funding Choices 中包含广告技术提供商就足够了。

【问题讨论】:

  • 我也需要这些答案,有人吗?

标签: android admob mobile-ad-mediation gdprconsentform user-messaging-platform


【解决方案1】:

据我体验/了解,通过用户消息传递平台进行的 Google 资助选择(实际上甚至不清楚为什么它有两个不同的名称)在欧盟内完全没用。

欢迎您纠正我,但正如我在 2021 年 8 月 3 日所经历的那样:

如果用户点击“管理选项”,然后点击“提交”并将“在设备上存储和/或访问信息”开关关闭,则 AdMob 不会向用户显示任何广告。 因此,您最终可能需要为资源(云服务、员工等)付费以向您的用户提供免费应用。 根据出现问题的开始日期(我在本主题中看到的帖子和 cmets 的日期),这对 Google 和/或 AdMob 来说是一个低优先级的问题。 permitInformation.getConsentType() 总是返回值 0。这实际上证明(或至少我认为)这个问题在他们的列表中的优先级有多低。至少可以通过这个 getter 检查用户是否同意提供非个性化广告。然后我们可以向他展示如何正确选择退出并让他免费使用该应用程序。但是,这似乎不符合开发者的利益。

再次,欢迎任何人纠正我,也许只有我有这种负面经历。

【讨论】:

  • 我也有同样的经历……现在对你有用吗?
  • 自 2021 年 8 月 3 日起我没有尝试过。您可以尝试搜索另一个同意管理平台(例如 Tealium for Xamarin),或者您也可以将 AdMob 换成它的竞争对手之一。这是迫使公司生产优质产品的最佳方法之一;-)
  • 我也有同样的经历。难以理解的是,即使在 Google 的支持论坛上,他们也建议使用其他同意框架。我感觉UMP是死胎。
  • 在我看来,这使得 UMP 在大多数情况下都无用。我检查了android UMP SDK release notes,两天前他们进行了更新(12 个月后)。我想使用 UMP 的主要原因是向 (GDPR) 用户显示广告技术供应商列表。但是不...我将下载供应商列表并将其发布在网站和/或应用程序中...浪费了过去 3 天的 UMP。在这种情况下,谷歌的支持非常荒谬:Example(查看日期)
  • @AtakanYildirim 不,我自己实现了。不确定 Google 的 UMP 何时可以使用。不过自七月以来就没有检查过它的状态。但是,我不会在未告知广告供应商的情况下向欧盟推荐个性化广告。
【解决方案2】:

我自己一直在解决这个问题,虽然我没有回答你所有的问题,但我已经找到了一些。

UMP 将其输出写入SharedPreferences 中的一些字符串,概述here。您可以编写一些辅助方法来查询这些字符串,以了解用户给予了何种级别的广告许可或用户是否为 EEA。

  1. 如何判断用户是否为EEA?可以查看SharedPreferences中的IABTCF_gdprApplies整数,如果为1,则用户为EEA。如果为 0,则用户不是。

  2. 如何获得同意类型?这部分变得更加复杂。 Google 文档here 概述了个性化和非个性化广告所需的权限。要获得此信息,您需要查看 SharedPreference 中的 4 个字符串:IABTCF_PurposeConsentsIABTCF_PurposeLegitimateInterestsIABTCF_VendorConsentsIABTCF_VendorLegitimateInterests。正如其他人所指出的那样,用户几乎不可能实际选择非个性化广告配置,因为他们不仅必须选择“在设备上存储信息”,而且还必须滚动浏览数百个非按字母顺序组织的供应商才能找到并选择“Google”(这些字符串中的供应商 ID 为 755)。这意味着出于所有实际目的,他们要么选择个性化广告(全部同意),要么拥有一个不错的无广告应用程序,而无需支付任何费用。您至少可以使用这些检查来设置付费墙、禁用云功能或以其他方式处理您认为合适的情况。

我做了一些辅助方法来查找这些状态。

科特林

fun isGDPR(): Boolean {
    val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
    val gdpr = prefs.getInt("IABTCF_gdprApplies", 0)
    return gdpr == 1
}

fun canShowAds(): Boolean {
    val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)

    //https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
    //https://support.google.com/admob/answer/9760862?hl=en&ref_topic=9756841

    val purposeConsent = prefs.getString("IABTCF_PurposeConsents", "") ?: ""
    val vendorConsent = prefs.getString("IABTCF_VendorConsents","") ?: ""
    val vendorLI = prefs.getString("IABTCF_VendorLegitimateInterests","") ?: ""
    val purposeLI = prefs.getString("IABTCF_PurposeLegitimateInterests","") ?: ""

    val googleId = 755
    val hasGoogleVendorConsent = hasAttribute(vendorConsent, index=googleId)
    val hasGoogleVendorLI = hasAttribute(vendorLI, index=googleId)

    // Minimum required for at least non-personalized ads
    return hasConsentFor(listOf(1), purposeConsent, hasGoogleVendorConsent)
            && hasConsentOrLegitimateInterestFor(listOf(2,7,9,10), purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)

}

fun canShowPersonalizedAds(): Boolean {
    val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)

    //https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
    //https://support.google.com/admob/answer/9760862?hl=en&ref_topic=9756841

    val purposeConsent = prefs.getString("IABTCF_PurposeConsents", "") ?: ""
    val vendorConsent = prefs.getString("IABTCF_VendorConsents","") ?: ""
    val vendorLI = prefs.getString("IABTCF_VendorLegitimateInterests","") ?: ""
    val purposeLI = prefs.getString("IABTCF_PurposeLegitimateInterests","") ?: ""

    val googleId = 755
    val hasGoogleVendorConsent = hasAttribute(vendorConsent, index=googleId)
    val hasGoogleVendorLI = hasAttribute(vendorLI, index=googleId)

    return hasConsentFor(listOf(1,3,4), purposeConsent, hasGoogleVendorConsent)
            && hasConsentOrLegitimateInterestFor(listOf(2,7,9,10), purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
}

// Check if a binary string has a "1" at position "index" (1-based)
private fun hasAttribute(input: String, index: Int): Boolean {
    return input.length >= index && input[index-1] == '1'
}

// Check if consent is given for a list of purposes
private fun hasConsentFor(purposes: List<Int>, purposeConsent: String, hasVendorConsent: Boolean): Boolean {
    return purposes.all { p -> hasAttribute(purposeConsent, p)} && hasVendorConsent
}

// Check if a vendor either has consent or legitimate interest for a list of purposes
private fun hasConsentOrLegitimateInterestFor(purposes: List<Int>, purposeConsent: String, purposeLI: String, hasVendorConsent: Boolean, hasVendorLI: Boolean): Boolean {
    return purposes.all { p ->
            (hasAttribute(purposeLI, p) && hasVendorLI) ||
            (hasAttribute(purposeConsent, p) && hasVendorConsent)
    }
}

斯威夫特

func isGDPR() -> Bool {
    let settings = UserDefaults.standard
    let gdpr = settings.integer(forKey: "IABTCF_gdprApplies")
    return gdpr == 1
}

// Check if a binary string has a "1" at position "index" (1-based)    
private func hasAttribute(input: String, index: Int) -> Bool {
    return input.count >= index && String(Array(input)[index-1]) == "1"
}

// Check if consent is given for a list of purposes
private func hasConsentFor(_ purposes: [Int], _ purposeConsent: String, _ hasVendorConsent: Bool) -> Bool {
    return purposes.allSatisfy { i in hasAttribute(input: purposeConsent, index: i) } && hasVendorConsent
}

// Check if a vendor either has consent or legitimate interest for a list of purposes
private func hasConsentOrLegitimateInterestFor(_ purposes: [Int], _ purposeConsent: String, _ purposeLI: String, _ hasVendorConsent: Bool, _ hasVendorLI: Bool) -> Bool {
    return purposes.allSatisfy { i in
        (hasAttribute(input: purposeLI, index: i) && hasVendorLI) ||
        (hasAttribute(input: purposeConsent, index: i) && hasVendorConsent)
    }
}

private func canShowAds() -> Bool {
    let settings = UserDefaults.standard
    
    //https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
    //https://support.google.com/admob/answer/9760862?hl=en&ref_topic=9756841
    
    let purposeConsent = settings.string(forKey: "IABTCF_PurposeConsents") ?? ""
    let vendorConsent = settings.string(forKey: "IABTCF_VendorConsents") ?? ""
    let vendorLI = settings.string(forKey: "IABTCF_VendorLegitimateInterests") ?? ""
    let purposeLI = settings.string(forKey: "IABTCF_PurposeLegitimateInterests") ?? ""
    
    let googleId = 755
    let hasGoogleVendorConsent = hasAttribute(input: vendorConsent, index: googleId)
    let hasGoogleVendorLI = hasAttribute(input: vendorLI, index: googleId)
    
    // Minimum required for at least non-personalized ads
    return hasConsentFor([1], purposeConsent, hasGoogleVendorConsent)
        && hasConsentOrLegitimateInterestFor([2,7,9,10], purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
                         
}

private func canShowPersonalizedAds() -> Bool {
    let settings = UserDefaults.standard
            
    //https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
    //https://support.google.com/admob/answer/9760862?hl=en&ref_topic=9756841
          
    // required for personalized ads
    let purposeConsent = settings.string(forKey: "IABTCF_PurposeConsents") ?? ""
    let vendorConsent = settings.string(forKey: "IABTCF_VendorConsents") ?? ""
    let vendorLI = settings.string(forKey: "IABTCF_VendorLegitimateInterests") ?? ""
    let purposeLI = settings.string(forKey: "IABTCF_PurposeLegitimateInterests") ?? ""
    
    let googleId = 755
    let hasGoogleVendorConsent = hasAttribute(input: vendorConsent, index: googleId)
    let hasGoogleVendorLI = hasAttribute(input: vendorLI, index: googleId)
    
    return hasConsentFor([1,3,4], purposeConsent, hasGoogleVendorConsent)
        && hasConsentOrLegitimateInterestFor([2,7,9,10], purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
}

【讨论】:

    【解决方案3】:

    我也有同样的疑问,尤其是在第 3 点,即使在我的情况下,同意类型始终为 0。我在 video 中看到,基于该值初始化了不同的 adRequest

    关于第 2 点,我将 Consentdebugsettings 设置为用户无 EEA(DEBUG_GEOGRAPHY_NOT_EEA,与官方指南中所做的略有不同),并且方法 consentInformation.isConsentFormAvailable() 返回 false

    【讨论】:

      【解决方案4】:

      我想提出一些想法:

      1.获得请求同意后是否需要调用MobileAds.initialize()?

      是的

      2。我如何检查用户是否来自 EEA?

      您可以像这样使用许可信息.getConsentStatus():

      if (consentInformation.getConsentStatus()== ConsentInformation.ConsentStatus.NOT_REQUIRED) {
      
      }
      

      你可以用这个来测试这个函数:

      ConsentRequestParameters.Builder consentRequest = new ConsentRequestParameters.Builder()
          .setTagForUnderAgeOfConsent(false);
              
      ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(activity)
          .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_NOT_EEA)
          //.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
          //.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_DISABLED)
          .addTestDeviceHashedId("Your device Hashed Id")
          .build();
          
      consentRequest.setConsentDebugSettings(debugSettings);
      ConsentRequestParameters consentRequestParameters = consentRequest.build()
      

      但不要忘记每次都调用许可信息.reset()。

      3.我总是得到同意类型的许可信息.getConsentType() 0。

      getConsentType() 没用,已在 user-messaging-platform:2.0.0 中删除。对我来说原因很简单:有了这个新平台,不再有双重状态,用户授权,用户未授权。现在它更像是 3 个状态:1-yes_for_all、2-no_for_all、3-customized_by_user

      4.是否需要将同意信息转发给 AdMob SDK 或 SDK 会处理。

      Admob SDK 会处理它。这就是为什么您不需要 getConsentType() 除非您想显示用户选择。但为此,最好重新打开同意书。太糟糕了,同意书没有加载用户的正确设置。

      5.关于调解,我需要同意信息,但不知道如何获得。

      @Tyler V 所述的Here

      6.在 AdMob -> 欧盟用户同意中,我的一个中介合作伙伴不包括在常用的广告技术提供商集中。如果我使用自定义广告技术提供商集,我是否需要包括所有常用的广告技术提供商集,其中有 198 个广告技术提供商。或者在 Funding Choices 中包含广告技术提供商就足够了。

      我认为在 Funding Choices 中包含广告技术提供商就足够了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-01
        • 1970-01-01
        • 2022-12-22
        • 2019-03-31
        相关资源
        最近更新 更多