درخواست رضایت از کاربران اروپایی

根据 Google 欧盟地区用户意见征求政策,您必须向位于欧洲经济区 (EEA) 的用户披露相关信息;在法律有相应要求的情况下,您必须征得他们的同意才能使用 Cookie 或其他本地存储方式;您同样必须征得他们的同意才能使用个人数据(如 AdID)来投放广告。此政策反映了欧盟《电子隐私指令》和《一般数据保护条例》(GDPR) 的要求。

为了帮助发布商履行此政策规定的职责,Google 提供了 Consent SDK。Consent SDK 是一个开源库,提供用于征求用户意见的实用函数。完整的源代码可在GitHub 上找到。

Google 投放的广告可分为个性化广告和非个性化广告,投放这两类广告都需要在欧洲经济区 (EEA) 内征求用户同意。默认情况下,向 Google 发出的广告请求会投放个性化广告,并根据用户先前收集的数据来选择广告。Google 还支持配置广告请求来投放非个性化广告。 详细了解个性化广告和非个性化广告

本指南介绍了如何使用 Consent SDK 来征求用户同意。此外,还介绍了如何在征得用户同意后将用户意见转发给 Google 移动广告 SDK

前提条件

应用可以使用指向 Google Maven 代码库的 Gradle 依赖项导入 Consent SDK。如需使用该代码库,您需要在应用的项目级 build.gradle 文件中引用该代码库。打开该文件并查找 allprojects 部分:

项目级 build.gradle 示例(节选)

allprojects {
    repositories {
        google()
        jcenter()
    }
}

如果上面的 google() 指令不存在,请添加该指令。

接下来,打开应用的应用级 build.gradle 文件,并找到“依赖项”部分。

应用级 build.gradle 示例(节选)

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.ads.consent:consent-library:1.0.6'
}

请添加上面的粗体代码行,该代码会指示 Gradle 提取最新版本的 Consent SDK。完成后,保存文件并执行 Gradle 同步。

在使用 Consent SDK 中的任何其他方法之前,您应更新意见征求状态,以确保 Consent SDK 拥有与您在AdMob 界面中选择的广告技术提供商有关的最新信息。如果广告技术提供商列表在用户上次同意后发生了变化,用户意见征求状态会重新设为未知状态。

如果您不使用中介

如果您不使用中介,则有两种方法可以实现 Consent SDK 来征求用户意见。

一种方法是使用 Consent SDK 向用户显示由 Google 呈现的用户意见征求表单。用户意见征求表单会显示您在 AdMob界面中选择的广告技术提供商列表。Consent SDK 会存储用户意见征求响应。

另一种方法是使用 Consent SDK 从 AdMob动态检索完整的广告技术提供商列表,如由发布商管理的用户意见征求中所述。不过,在这种情况下,您需要确定如何向用户呈现提供商列表,并向用户显示您自己的用户意见征求表单。

用户选择意见征求选项后,您可以按照存储由发布商管理的用户意见征求中的说明,请求 Consent SDK 存储用户的意见选项。

征得用户同意后,如果用户仅同意接收非个性化广告,您需要将用户意见转发给 Google 移动广告 SDK

如果您使用中介 AdMob

您可以使用 Consent SDK 从 AdMob动态检索完整的广告技术提供商列表,详情请参阅由发布商管理的用户意见征求。您需要确定需要向用户呈现其他广告联盟中的其他广告技术提供商。

作为应用开发者,您需要针对 Consent SDK 返回的广告技术提供商以及其他广告联盟的提供商征求用户同意。如果用户仅同意接收非个性化广告,那么您还需要手动存储用户的意见回复,并将用户意见转发给 Google 移动广告 SDK

Google 目前无法为中介广告联盟征求和处理用户意见,因此您需要为每个广告联盟单独征求和处理用户意见。如需了解实现详情,请参阅每个中介合作伙伴的集成指南

更新用户意见状态

使用 Consent SDK 时,建议您在每次应用启动时确定用户意见征求状态。为此,请在 ConsentInformation 的实例上调用 requestConsentInfoUpdate()

import com.google.ads.consent.*;

public class MainActivity extends Activity {
    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        ConsentInformation consentInformation = ConsentInformation.getInstance(context);
        String[] publisherIds = {"pub-0123456789012345"};
        consentInformation.requestConsentInfoUpdate(publisherIds, new ConsentInfoUpdateListener() {
            @Override
            public void onConsentInfoUpdated(ConsentStatus consentStatus) {
                 // User's consent status successfully updated.
            }

            @Override
            public void onFailedToUpdateConsentInfo(String errorDescription) {
                 // User's consent status failed to update.
            }
        });
        ...
    }
    ...
}

调用 requestConsentInfoUpdate() 需要两个参数:

  • 一组有效且完全激活的发布商 ID,供您的应用发出广告请求。 查找您的发布商 ID

  • ConsentInfoUpdateListener 的实例。

如果用户意见征求信息已成功更新,系统会通过 ConsentInfoUpdateListeneronConsentInfoUpdated() 方法提供更新后的用户意见征求状态。返回的 ConsentStatus 可能具有下列值:

用户意见状态 定义
ConsentStatus.PERSONALIZED 用户已同意投放个性化广告。
ConsentStatus.NON_PERSONALIZED 用户已同意投放非个性化广告。
ConsentStatus.UNKNOWN 用户既未同意接收也未拒绝接收个性化广告或非个性化广告。

用户意见信息更新成功后,您还可以检查 ConsentInformation.getInstance(context).isRequestLocationInEeaOrUnknown(),以查看用户是否位于欧洲经济区内或者请求位置是否未知。

如果 isRequestLocationInEeaOrUnknown() 方法返回 false,则表明用户不在欧洲经济区内,并且无需根据《欧盟地区用户意见征求政策》征求用户意见。您可以向 Google 移动广告 SDK 发出广告请求。

如果 isRequestLocationInEeaOrUnknown() 方法返回 true

Google 的Consent SDK。提供了两种征求用户同意的方式:

请务必为用户提供更改或撤消同意的选项。

由 Google 呈现的用户意见征求表单是在应用内容之上显示的全屏可配置表单。您可以将表单配置为向用户显示以下选项的组合:

  • 同意观看个性化广告
  • 同意观看非个性化广告
  • 使用付费版应用,而不是观看广告

您应该仔细阅读同意文本:默认情况下,您会看到一条使用 Google 通过应用获利可能适合的消息,但我们无法针对适合您的用户意见征求文本提供法律建议。如需更新由 Google 呈现的用户意见征求表单的用户意见征求文本,请根据需要修改 Consent SDK 中包含的 consentform.html 文件。

使用 ConsentForm 类配置和显示由 Google 呈现的用户意见征求表单。以下代码演示了如何使用所有三个用户意见选项构建 ConsentForm

URL privacyUrl = null;
try {
    // TODO: Replace with your app's privacy policy URL.
    privacyUrl = new URL("https://www.your.com/privacyurl");
} catch (MalformedURLException e) {
    e.printStackTrace();
    // Handle error.
}
ConsentForm form = new ConsentForm.Builder(context, privacyUrl)
    .withListener(new ConsentFormListener() {
        @Override
        public void onConsentFormLoaded() {
            // Consent form loaded successfully.
        }

        @Override
        public void onConsentFormOpened() {
            // Consent form was displayed.
        }

        @Override
        public void onConsentFormClosed(
                ConsentStatus consentStatus, Boolean userPrefersAdFree) {
            // Consent form was closed.
        }

        @Override
        public void onConsentFormError(String errorDescription) {
            // Consent form error.
        }
    })
    .withPersonalizedAdsOption()
    .withNonPersonalizedAdsOption()
    .withAdFreeOption()
    .build();

上述方法使用以下选项准备由 Google 呈现的用户意见征求表单:

withListener()
ConsentForm 注册监听器。ConsentFormListener 中每种可替换的方法均与用户意见征求表单生命周期中的一个事件相对应。
可替换的方法
onConsentFormLoaded 用户意见征求表单已成功加载。
onConsentFormError 未能加载用户意见征求表单。errorDescription 参数提供对错误的说明。
onConsentFormOpened 用户意见征求表单已打开。
onConsentFormClosed 用户意见征求表单已关闭。该方法的参数提供了以下信息:
  • consentStatus 是一个 ConsentStatus 值,用于描述更新后的用户意见状态。
  • 当用户选择使用付费版本应用而不观看广告时,userPrefersAdFree 的值为 true
withPersonalizedAdsOption()
表示用户意见征求表单应显示个性化广告选项。
withNonPersonalizedAdsOption()
表示用户意见征求表单应显示非个性化广告选项。
withAdFreeOption()
表示用户意见征求表单应显示无广告应用选项。

创建 ConsentForm 对象后,请调用 ConsentFormload() 方法加载用户意见征求表单,如下所示:

form.load();

如需向用户显示由 Google 呈现的用户意见征求表单,请在 ConsentForm 实例上调用 show(),如下所示:

form.show();

在用户选择一个选项并关闭表单后,Consent SDK 会保存用户的选择并触发 onConsentFormClosed 事件。您可以监听此事件并将用户意见转发给 Google 移动广告 SDK

由发布商管理的用户意见征求

如果您选择自行征求用户意见,则可以使用 ConsentInformation 类的 getAdProviders() 方法获取与您应用中使用的发布商 ID 相关联的广告技术提供商。请注意,凡是针对您的发布商 ID 配置的所有广告技术提供商,您均需为其征求用户意见。

您必须先等待 ConsentInfoUpdateListeneronConsentInfoUpdate() 方法(如更新用户意见状态部分所述),然后才能调用 getAdProviders()

List<AdProvider> adProviders =
    ConsentInformation.getInstance(context).getAdProviders();

然后,您可以使用该广告技术提供商列表自行征求用户意见。

征得用户同意后,请使用 ConsentInformation 类的 setConsentStatus() 方法记录用户回复所对应的 ConsentStatus

ConsentInformation.getInstance(context)
    .setConsentStatus(ConsentStatus.PERSONALIZED);

在向 Consent SDK 报告用户意见后,您可以将用户意见转发给 Google 移动广告 SDK

如需允许用户更新其意见,只需在用户选择更新用户意见征求状态时重复征求用户意见部分列出的步骤。

如果发布商知道用户未达到同意年龄,则所有广告请求都必须设置 TFUA(用于表示用户位于欧洲且未达到同意年龄的标记)。要在您的应用发出的所有广告请求中包含此标记,请调用 setTagForUnderAgeOfConsent(true)。此设置将在以后的所有广告请求中生效。

ConsentInformation.getInstance(context).setTagForUnderAgeOfConsent(true);

启用 TFUA 设置后,系统将无法加载 Google 呈现的用户意见征求表单。所有包含 TFUA 的广告请求都将不符合投放个性化广告和再营销的条件。TFUA 会禁止向第三方广告技术提供商(例如广告衡量像素和第三方广告服务器)发送请求。

如需从广告请求中移除 TFUA,请调用 setTagForUnderAgeOfConsent(false)

测试

Consent SDK 的行为会有所不同,具体取决于ConsentInformation.getInstance(context).isRequestLocationInEeaOrUnknown() 的值。 例如,如果用户不在欧洲经济区 (EEA) 内,则无法加载用户意见征求表单。

为了让您在欧洲经济区 (EEA) 内外都可以更轻松地测试您的应用,Consent SDK 支持可在调用 Consent SDK 中的任何其他方法之前设置的调试选项。

  1. 按照更新用户意见状态部分中的说明调用 requestConsentInfoUpdate。然后运行您的应用。检查 logcat 输出是否存在以下日志:

    I/ConsentInformation: Use
    ConsentInformation.getInstance(context).addTestDevice("33BE2250B43518CCDA7DE426D04EE231")
    to get test ads on this device.
  2. 使用 Logcat 中的广告 ID 将您的设备指定为测试设备:

    ConsentInformation.getInstance(context).addTestDevice("33BE2250B43518CCDA7DE426D04EE231");
  3. 最后,调用 setDebugGeography 设置用于测试的首选地理位置。

    // Geography appears as in EEA for test devices.
    ConsentInformation.getInstance(context).
        setDebugGeography(DebugGeography.DEBUG_GEOGRAPHY_EEA);
    // Geography appears as not in EEA for debug devices.
    ConsentInformation.getInstance(context).
        setDebugGeography(DebugGeography.DEBUG_GEOGRAPHY_NOT_EEA);

完成这些步骤后,对更新用户意见状态的调用会将您的调试地理位置考虑在内。

کد موجود در این بخش را می توان با هر نسخه از Google Mobile Ads SDK استفاده کرد. همچنین می‌تواند بدون توجه به اینکه آیا از Consent SDK برای جمع‌آوری رضایت استفاده کرده‌اید، استفاده شود.

رفتار پیش‌فرض Google Mobile Ads SDK ارائه تبلیغات شخصی‌شده است. اگر کاربر رضایت داده است که فقط تبلیغات غیرشخصی دریافت کند، می توانید یک شی AdRequest را پیکربندی کنید تا مشخص کنید که فقط تبلیغات غیرشخصی درخواست شود. کد زیر باعث می شود بدون توجه به اینکه کاربر در منطقه اقتصادی اروپا باشد یا نه، تبلیغات غیرشخصی درخواست شود:

جاوا

Bundle extras = new Bundle();
extras.putString("npa", "1");

AdRequest request = new AdRequest.Builder()
    .addNetworkExtrasBundle(AdMobAdapter.class, extras)
    .build();

کاتلین

val extras = Bundle()
extras.putString("npa", "1")

val request = AdRequest.Builder()
    .addNetworkExtrasBundle(AdMobAdapter::class.java, extras)
    .build()

اگر تبلیغات غیرشخصی درخواست شود، URL درخواست آگهی در حال حاضر شامل &npa=1 است. با این حال، توجه داشته باشید که این جزئیات پیاده‌سازی داخلی Google Mobile Ads SDK است و ممکن است تغییر کند.

延迟应用衡量(可选)

默认情况下,Google 移动广告 SDK 会初始化应用衡量并在应用启动时立即开始向 Google 发送用户级事件数据。 此初始化行为可确保您可以启用 AdMob 用户指标,而无需更改额外的代码。

但是,如果您的应用需要在征求用户意见后才能发送这些事件,则可以延迟应用衡量,直到显式初始化移动广告 SDK 或加载广告为止。

如需延迟应用衡量,请在 AndroidManifest.xml 中添加以下 <meta-data> 标记。

<manifest>
     <application>
        <!-- Delay app measurement until MobileAds.initialize() is called. -->
        <meta-data
            android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT"
            android:value="true"/>
    </application>
</manifest>

常见问题解答

Consent SDK 支持多少家广告技术提供商?
Consent SDK 不限制发布商选择启用的广告技术提供商数量。
如果我在 AdMob 界面中更改我的选择,SDK 返回的广告技术提供商列表是否会自动更新?
可以,如果您对AdMob 界面中的广告技术提供商列表进行了更改,这些更改会在大约一小时内传播到 Google 的广告服务器。