GDPR И CCPA
Пожалуйста, обратите внимание, что лучше всего обратиться к квалифицированным юристам, чтобы получить дополнительную информацию и быть хорошо подготовленным к соблюдению требований.
Закон Европейского союза о защите персональных данных, более известный как GDPR, вступил в силу 25 Мая 2018 года. Это набор правил, разработанный для жителей Европейского союза, о получении контроля над сбором их персональных данных. Любые бизнесы, основанные в Европейском союзе или имеющие пользователей из Европейского союза, обязаны соответствовать закону о защите персональных данных (GDPR) во избежание связанных рисков. Закон California Consumer Privacy Act (CCPA) вступил в силу 1 Января 2020 года. Мы собрали вместе полезную информацию, для того что бы помочь вам лучше понять необходимые шаги в соответсвии вашего приложения требованиям GDRP.
Шаг 1. Обновление Политики Конфеденциальности
Добавьте Дополнительную Информацию В Вашу Политику Конфиденциальности
Не забудьте добавить информацию о сборе IP адреса и рекламного ID, так же как ссылку на политику конфиденциальности Appodeal в вашу политику конфиденциальности в App Store и Google Play.
Для ускорения процесса вы можете воспользоваться генераторами политики конфиденциальности, где вам необходимо будет указать ID, IP адрес и локацию (если вы ее собираете) в поле Personally Identifiable Information you collect (в поле с дополнительной информацией о вашем приложении) а так же как ссылку на политику конфиденциальности Appodeal в поле Link to the privacy policy of third party service providers used by the app.
Добавьте Политику Конфиденциальности В Ваше Мобильное Приложение
Вам необходимо явно добавить ссылку на вашу политику конфиденциальности в два места: на страницу приложения в app’s store и в ваше приложение.
Вы можете найти подробные инструкции о добавлении политики конфиденциальности в ваше приложения на официальных ресурсах, например: Iubenda - решение, адаптированное к требованиям законодательства, которое содержит подробное руководство по включению политики конфиденциальности в ваше приложение.
Убедитесь что ваш сайт с политикой конфиденциальности содержит SSL-сертификат — это пункт может казаться очевидным, но это важно.
Ниже вы можете найти две ссылки на ресурсы, которые вы можете использовать во время работы над соответствием вашего приложения:
- Privacy, Security and Deception regulations (by Google Play)
- Recommendations on Developing a Meaningful Privacy Policy (by Attorney General California Department of Justice)
Пожалуйста, обратите внимание, что, хотя мы всегда готовы предоставить вам ценную информацию, мы не уполномочены предоставлять какие-либо юридические консультации. Важно адресовать свои вопросы юристам, которые работают в соответствующей области.
Шаг 2. Stack Consent Manager
В соответствии с Appodeal и рекламными сетями в предоставлении наиболее подходящей мобильной рекламы конечному пользователю, вам необходимо запрашивать соглашение в регионах GDPR и CCPA.
Библиотека Stack Consent Manager включает разработанное окно согласия, показ которого вы можете предоставлять конечному пользователю. Это означает, что вам больше не требуется создавать данное окно согласия самостоятельно.
Согласие будет запрошено автоматически при инициализации SDK, и форма согласия будет показана, если это необходимо, без каких-либо дополнительных вызовов.
Обратите внимание, что окно согласия будет показано только в ЕС и Калифорнии, вы можете использовать VPN для тестирования.
- UPM Дистрибуция
- Manual Дистрибуция
private void Start()
{
int adTypes = AppodealAdType.Interstitial | AppodealAdType.Banner | AppodealAdType.RewardedVideo | AppodealAdType.Mrec;
string appKey = "YOUR_APPODEAL_APP_KEY";
AppodealCallbacks.Sdk.OnInitialized += OnInitializationFinished;
Appodeal.Initialize(appKey, adTypes);
}
#region Initialization Callback
public void OnInitializationFinished(object sender, SdkInitializedEventArgs e) { }
#endregion
class Test : IAppodealInitializationListener
{
private void Start()
{
int adTypes = Appodeal.INTERSTITIAL | Appodeal.BANNER | Appodeal.REWARDED_VIDEO | Appodeal.MREC;
string appKey = "YOUR_APPODEAL_APP_KEY";
Appodeal.initialize(appKey, adTypes, this);
}
#region Initialization Callback
public void onInitializationFinished(List <-string-> errors) { }
#endregion
}
Продвинутые Настройки
Пользовательская Логика Согласия
Stack Consent Manager включен в Appodeal SDK по умолчанию. Согласие будет запрошено автоматически при инициализации SDK, и форма согласия будет показана, если это необходимо, без дополнительных вызовов.
Если вы хотите настроить свою логику управления согласием, вызовите метод обновления согласия в Appodeal перед инициализацией и передайте значение полученного согласия.
- UPM Дистрибуция
- Manual Дистрибуция
private void Init()
{
// Either
Appodeal.UpdateConsent(consentObj);
// OR
Appodeal.UpdateConsentGdpr(GdprUserConsent.Personalized);
// OR
Appodeal.UpdateConsentCcpa(CcpaUserConsent.OptIn);
Appodeal.Initialize(appKey, adTypes);
}
private void Init()
{
// Either
Appodeal.updateConsent(consentObj);
// OR
Appodeal.updateConsentGdpr(GdprUserConsent.Personalized);
// OR
Appodeal.updateConsentCcpa(CcpaUserConsent.OptIn);
Appodeal.initialize(appKey, adTypes, this);
}
Вы можете использовать этот метод, чтобы предоставить согласие пользователя GDPR/CCPA для рекламных сетей в Appodeal SDK, в любом месте вашего приложения.
Управление Согласием Вручную
При желании вы можете управлять согласием и обновлять его вручную с помощью прямых вызовов Stack Consent Manager
Обновите Статус Согласия
- UPM Дистрибуция
- Manual Дистрибуция
Вызовите метод RequestConsentInfoUpdate()
у экземпляра класса ConsentManager
:
private ConsentManager _consentManager;
_consentManager = ConsentManager.GetInstance();
_consentManager?.RequestConsentInfoUpdate(AppKey, this);
Подпишитесь на желаемое событие, используя один из методов из нашей инструкции.
Вы можете использовать методы обратного вызова, как показано ниже:
public void SomeMethod()
{
ConsentManagerCallbacks.ConsentInfo.OnUpdated += OnConsentInfoUpdated;
ConsentManagerCallbacks.ConsentInfo.OnFailedToUpdate += OnFailedToUpdateConsentInfo;
}
#region ConsentInfo Callbacks
private void OnConsentInfoUpdated(object sender, ConsentEventArgs e)
{
Debug.Log("Consent Info Updated");
}
private void OnFailedToUpdateConsentInfo(object sender, ConsentManagerExceptionEventArgs e)
{
Debug.Log("Failed to update Consent Info");
}
#endregion
Все возвращаемые ошибки являются экземплярами исключений с настраиваемыми кодами:
Код | Описание |
---|---|
INTERNAL(1) | Ошибка на стороне SDK. Включает в себя ошибки JS и кодирования/декодирования |
NETWORKING(2) | Ошибки HTTP, парсинга запроса/ответа |
INCONSISTENT(3) | Некооректное использование SDK API |
SDK Consent Manager можно синхронизировать в любой момент жизненного цикла приложения. Рекомендуем синхронизировать его при запуске приложения. Разрешены множественные вызовы синхронизации.
Если информация о согласии успешно обновлена, обновленный consent
предоставляется с помощью метода
ConsentManagerCallbacks.ConsentInfo.OnUpdated
.
Теперь вы можете получать информацию о предыдущем соглашении пользователя и зоне регулирования. Перед запросом
эти параметры undefined
.
_consentManager?.GetConsentStatus();
Статус согласия | Описание |
---|---|
Unknown | Статус неизвестен. Окно согласия не отображалось. |
NonPersonalized | Пользователь НЕ давал согласия на персонализированную рекламу. |
PartlyPersonalized | Пользователь дал частичное (только для некоторых сетей) согласие на персонализированную рекламу. |
Personalized | Пользователь дал согласие на персонализированную рекламу. |
Вызовите метод requestConsentInfoUpdate()
у экземпляра класса ConsentManager
:
private ConsentManager consentManager;
consentManager = ConsentManager.getInstance();
consentManager?.requestConsentInfoUpdate(appKey, this);
Наследуйте ваш класс от IConsentInfoUpdateListener
:
SomeClassName : IConsentInfoUpdateListener { }
Теперь вы можете использовать следующие методы обратного вызова в своем общедоступном классе:
public void onConsentInfoUpdated(Consent consent)
{
Debug.Log("onConsentInfoUpdated");
}
public void onFailedToUpdateConsentInfo(ConsentManagerException error)
{
Debug.Log($"onFailedToUpdateConsentInfo Reason: {error.getReason()}");
}
Все возвращаемые ошибки являются экземплярами исключений с настраиваемыми кодами:
Код | Описание |
---|---|
INTERNAL(1) | Ошибка на стороне SDK. Включает в себя ошибки JS и кодирования/декодирования |
NETWORKING(2) | Ошибки HTTP, парсинга запроса/ответа |
INCONSISTENT(3) | Некооректное использование SDK API |
SDK Consent Manager можно синхронизировать в любой момент жизненного цикла приложения. Рекомендуем синхронизировать его при запуске приложения. Разрешены множественные вызовы синхронизации
Если информация о согласии успешно обновлена, обновленный consent
предоставляется с помощью метода
onConsentInfoUpdated()
.
Теперь вы можете получать информацию о предыдущем соглашении пользователя и зоне регулирования. Перед запросом
эти параметры undefined
.
consentManager.getConsentStatus();
Статус согласия | Описание |
---|---|
Unknown | Статус неизвестен. Окно согласия не отображалось. |
NonPersonalized | Пользователь НЕ давал согласия на персонализированную рекламу. |
PartlyPersonalized | Пользователь дал частичное (только для некоторых сетей) согласие на персонализированную рекламу. |
Personalized | Пользователь дал согласие на персонализированную рекламу. |
Необходимость Показа Окна Согласия
После вызова метода OnConsentInfoUpdated
вам необходимо определить, подпадают ли ваши пользователи под действие
GDPR и CCPA и следует ли отображать окно согласия для сбора персональных данных.
Вы можете проверить, показывать ли диалог согласия. Перед запросом эти параметры undefined
(Unknown status)
- UPM Дистрибуция
- Manual Дистрибуция
_consentManager?.ShouldShowConsentDialog()
Параметр ShouldShow | Описание |
---|---|
True | Пользователь находится в сфере действия законов GDPR или CCPA, окно согласия должно быть показано. |
False | Пользователь не находится в сфере действия законов GDPR или CCPA, или окно согласия уже было показано. |
Unknown | Значение не определно (метод RequestConsentInfoUpdate() не вызывался). |
consentManager.shouldShowConsentDialog()
Параметр ShouldShow | Описание |
---|---|
True | Пользователь находится в сфере действия законов GDPR или CCPA, окно согласия должно быть показано. |
False | Пользователь не находится в сфере действия законов GDPR или CCPA, или окно согласия уже было показано. |
Unknown | Значение не определно (метод RequestConsentInfoUpdate() не вызывался). |
Отображение Окна Согласия
После запроса SDK вы можете создать и загрузить окно согласия. Загрузка разрешена в любой регулируемой зоне и независима от предварительного согласия.
- UPM Дистрибуция
- Manual Дистрибуция
private ConsentForm _consentForm;
_consentForm = ConsentForm.GetInstance(this);
_consentForm?.Load();
Вы можете проверить, готово ли окно согласия.
bool loaded = _consentForm.IsLoaded();
После того, как окно согласия готово, вы можете отобразить его.
_consentForm?.Show();
После первого отображения окна согласия метод ShouldShowConsentDialog()
вернёт значение ConsentShouldShow.False
в следующих сессиях.
private ConsentForm consentForm;
consentForm = ConsentForm.getInstance(this);
consentForm?.load();
Вы можете проверить, готово ли окно согласия.
bool loaded = consentForm.isLoaded();
После того, как окно согласия готово, вы можете отобразить его.
consentForm.show();
После первого отображения окна согласия метод shouldShowConsentDialog()
вернет значение Consent.ShouldShow.FALSE
в следующих сеансах.
Обработка Методов Обратного Вызова
- UPM Дистрибуция
- Manual Дистрибуция
Используйте коллбэки как показано ниже:
public void SomeMethod()
{
ConsentManagerCallbacks.ConsentForm.OnLoaded += OnConsentFormLoaded;
ConsentManagerCallbacks.ConsentForm.OnExceptionOccurred += OnConsentFormExceptionOccurred;
ConsentManagerCallbacks.ConsentForm.OnOpened += OnConsentFormOpened;
ConsentManagerCallbacks.ConsentForm.OnClosed += OnConsentFormClosed;
}
#region ConsentForm Callbacks
private void OnConsentFormLoaded(object sender, EventArgs e)
{
Debug.Log("Consent Form loaded");
}
private void OnConsentFormExceptionOccurred(object sender, ConsentManagerExceptionEventArgs e)
{
Debug.Log("Consent Form Exception Occurred");
}
private void OnConsentFormOpened(object sender, EventArgs e)
{
Debug.Log("Consent Form Opened");
}
private void OnConsentFormClosed(object sender, ConsentEventArgs e)
{
Debug.Log("Consent Form Closed");
}
#endregion
- Наследуйте свой класс от
IConsentFormListener
:
SomeClassName : IConsentFormListener {}
- Реализуйте все методы обратного вызова:
public void onConsentFormLoaded()
{
Debug.Log("ConsentFormListener - onConsentFormLoaded");
}
public void onConsentFormError(ConsentManagerException exception)
{
Debug.Log($"ConsentFormListener - onConsentFormError, reason - {exception.getReason()}");
}
public void onConsentFormOpened()
{
Debug.Log("ConsentFormListener - onConsentFormOpened");
}
public void onConsentFormClosed(Consent consent)
{
Debug.Log($"ConsentFormListener - onConsentFormClosed, consentStatus - {consent.getStatus()}");
}
Продвинутые Настройки
- UPM Дистрибуция
- Manual Дистрибуция
Вы можете заставить диспетчер согласия записывать ключи iAB в SharedPreference
, настроив свойство хранилища перед
запросом в ConsentManagerStorage
.
_consentManager = ConsentManager.GetInstance();
_consentManager.SetStorage(ConsentManagerStorage.SharedPreference);
SharedPreference
, а только заменяет их.Вы можете зарегистрироваться в качестве вендора (продавца) перед запросом. Должен быть вызван перед запросом.
_consentManager = ConsentManager.GetInstance();
var customVendor = new Vendor.Builder(
"Appodeal Test",
"com.appodeal.test",
"https://customvendor.com")
.SetPurposeIds()
.SetFeatureIds()
.SetLegitimateInterestPurposeIds()
.Build();
_consentManager?.SetCustomVendor(customVendor);
var vendor = _consentManager?.GetCustomVendor("com.appodeal.test");
Параметр | Тип | Описание |
---|---|---|
name | String | Имя. Будет показано в окне согласия |
bundle | String | Кастомная строка, проверяющая результат согласия для вендора |
policyUrl | String | URL-адрес политики конфиденциальности |
purposeIds | Array of integers | Массив id целей iAB |
featureIds | Array of integers | Массив id функций iAB |
legitimateInterestPurposeIds | Array of integers | Массив id законных интересов iAB |
После того, как консент форма закрыта, вы можете проверить, было ли получено согласие для конкретного вендора:
consent?.HasConsentForVendor("com.appodeal.test");
Параметр HasConsent | Описание |
---|---|
True | Значение согласия вендора равно true. |
False | Значение согласия вендора равно false. |
Unknown | Значение не определно (метод RequestConsentInfoUpdate() не вызывался). |
Вы можете заставить диспетчер согласия записывать ключи iAB в SharedPreference
, настроив свойство хранилища перед
запросом в ConsentManager.Storage
.
consentManager = ConsentManager.getInstance();
consentManager.setStorage(ConsentManager.Storage.SHARED_PREFERENCE);
SharedPreference
, а только заменяет их.Вы можете зарегистрироваться в качестве вендора (продавца) перед запросом. Должен быть вызван перед запросом.
consentManager = ConsentManager.getInstance();
var customVendor = new Vendor.Builder(
"Appodeal Test",
"com.appodeal.test",
"https://customvendor.com")
.setPurposeIds()
.setFeatureIds()
.setLegitimateInterestPurposeIds()
.build();
consentManager.setCustomVendor(customVendor);
var vendor = consentManager.getCustomVendor("com.appodeal.test");
Параметр | Тип | Описание |
---|---|---|
name | String | Имя. Будет показано в окне согласия |
bundle | String | Кастомная строка, проверяющая результат согласия для вендора |
policyUrl | String | URL-адрес политики конфиденциальности |
purposeIds | Array of integers | Массив id целей iAB |
featureIds | Array of integers | Массив id функций iAB |
legitimateInterestPurposeIds | Array of integers | Массив id законных интересов iAB |
После того как консент форма закрыта, вы можете проверить, было ли получено согласие для конкретного вендора:
consent.hasConsentForVendor("com.appodeal.test");
Параметр HasConsent | Описание |
---|---|
TRUE | Значение согласия вендора равно true. |
FALSE | Значение согласия вендора равно false. |
UNKNOWN | Значение не определно (метод RequestConsentInfoUpdate() не вызывался). |