GDPR and CCPA
Keep in mind that it’s best to contact qualified legal professionals, if you haven’t done so already, to get more information and be well-prepared for compliance.
The General Data Protection Regulation, better known as GDPR, took effect on May 25, 2018. It's a set of rules designed to give EU citizens more control over their personal data. Any businesses established in the EU or with users based in Europe are required to comply with GDPR or risk facing heavy fines. The California Consumer Privacy Act (CCPA) went into effect on January 1, 2020. We have put together some guidelines to help publishers understand better the steps they need to take to be GDPR compliant.
Step 1. Update Privacy Policy
Include Additional Information To Your Privacy Policy
Don’t forget to add information about IP address and advertising ID collection, as well as the link to Appodeal’s privacy policy to your app’s privacy policy on the App Store.
To speed up the process, you could use privacy policy generators - just insert advertising ID, IP address, and location (if you collect users’ location) in the Personally Identifiable Information you collect field (in line with other information about your app) and the link to Appodeal’s privacy policy in the Link to the privacy policy of third party service providers used by the app field.
Add A Privacy Policy To Your Mobile App
You must add your explicit privacy policies in two places: on your app’s Store Listing page and within your app.
You can find detailed instructions on adding your privacy policy to your app on legal service websites. For example, Iubenda, the solution tailored to legal compliance, provides a comprehensive guide on including a privacy policy in your app.
Make sure that your privacy policy website has an SSL certificate—this point might seem obvious, but it’s still essential.
Here are two useful resources that you can utilize while working on your app compliance:
- Privacy, Security and Deception regulations (by Google Play)
- Recommendations on Developing a Meaningful Privacy Policy (by Attorney General California Department of Justice)
Please note that although we’re always eager to back you up with valuable information, we’re not authorized to provide any legal advice. It’s important to address your questions to lawyers who specialize in this area.
Step 2. Configure Stack Consent Manager with TCF v2 Support
Since Appodeal SDK 3.2.1
it is fully compatible with Google UMP and supports IAB TCF v2.
In order for Appodeal and our ad providers to deliver ads that are more relevant to your users, as a mobile app publisher, you need to collect explicit user consent in the regions covered by GDPR and CCPA.
To get consent for collecting personal data of your users, we suggest you use a ready-made solution - Stack Consent Manager based on Google User Messaging Platform (UMP).
Before you start, you need to configure Google UMP. Follow this instruction to setup a consent form.
Step 3. Integrate Stack Consent Manager
Stack Consent Manager comes with a pre-made consent window that you can easily present to your users. That means you no longer need to create your own consent window.
Consent will be requested automatically on SDK initialization, and consent form will be shown if it is necessary without any additional calls.
Please keep in mind that Consent will be shown only in the EU and California regions, you can use VPN for testing.
This means that Appodeal SDK integration code remains the same:
- Swift
- Objective-C
@UIApplicationMain
final class MyAppDelegate: UIResponder, UIApplicationDelegate, AppodealInitializationDelegate {
func application(
_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil ) -> Bool {
Appodeal.setAutocache(false, types: .interstitial)
Appodeal.setLogLevel(.verbose)
// New optional delegate for initialization completion
Appodeal.setInitializationDelegate(self)
/// Any other pre-initialization
/// app specific logic
Appodeal.initialize(
withApiKey: "APP_KEY",
types: .interstitial
)
return true
}
func appodealSDKDidInitialize() {
// Appodeal SDK did complete initialization
}
}
@interface MyAppDelegate ()
<AppodealInitializationDelegate>
@end
@implementation MyAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[Appodeal setAutocache:NO types:AppodealAdTypeInterstitial];
[Appodeal setLogLevel:APDLogLevelVerbose];
// New optional delegate for initialization completion
[Appodeal setInitializationDelegate:self];
/// Any other pre-initialization
/// app specific logic
[Appodeal initializeWithApiKey:@"APP KEY" types:AppodealAdTypeInterstitial];
return YES;
}
- (void)appodealSDKDidInitialize {
// Appodeal SDK did complete initialization
}
@end
Advanced
Starting from Appodeal SDK 3.2.1-beta.1 you do not have to update user consent manually. Appodeal SDK support the iAB TCFv2 protocol. All consent data will be read from NSUserDefaults and passed everywhere you may need. Even if you want to use an alternative solution for User Consent Management, Appodeal SDK will read and not modify the consent data.
The following code is deprecated starting from version 3.2.1-beta.1 and will be removed in the next release.
- Swift
- Objective-C
Appodeal.updateConsent(true) // deprecated
Appodeal.updateUserConsentGDPR(.personalized) // deprecated
Appodeal.updateUserConsentCCPA(.optIn) // deprecated
[Appodeal updateConsent: YES]; // deprecated
[Appodeal updateUserConsentGDPR:APDGDPRUserConsentPersonalized]; // deprecated
[Appodeal updateUserConsentCCPA:APDCCPAUserConsentOptIn]; // deprecated
Manual Consent Management
If you wish, you can manage and update consent manually using Stack Consent Manager calls.
Now StackConsentManager also supports Swift Concurrency.
Consent manager SDK can be synchronized and shown at any moment of application lifecycle. We recommend to synchronize it at application launch. Multiple synchronization calls are allowed. Appodeal SDK will not show consent dialog if it has been presented. For more details follow the example:
- Swift
- Objective-C
import StackConsentManager
/// Initialisation
class YourAppDelegate: AppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?
) -> Bool {
let parameters = ConsentUpdateRequestParameters(
appKey: "YOUR_APP_KEY",
mediationSdkName: "YOUR_SDK_NAME",
mediationSdkVersion: "YOUR_SDK_VERSION",
COPPA: true
)
// requesting consent info update
ConsentManager.shared.requestConsentInfoUpdate(parameters: parameters) { error in
guard error == nil else { return } // error occured while receiving consent info
// loading and showing consent dialog
ConsentManager.shared.loadAndPresentIfNeeded(rootViewController: UIViewController()) { error in
if let error {
// error occured
} else {
// everything was fine, now you have user's consent
// initialize SDK here
}
}
}
return true
}
}
#import <StackConsentManager/StackConsentManager-Swift.h>
@implementation YourAppDelegate
/// Initialisation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
APDConsentUpdateRequestParameters *parameters = [[APDConsentUpdateRequestParameters alloc] initWithAppKey:@"YOUR_APP_KEY" mediationSdkName:@"YOUR_SDK_NAME" mediationSdkVersion:@"YOUR_SDK_VERSION" COPPA:true];
// requesting consent info update
[APDConsentManager.shared requestConsentInfoUpdateWithParameters:parameters completion:^(NSError * error) {
if (error) {
// error occured while receiving consent info
return;
}
// loading and showing consent dialog
[APDConsentManager.shared loadAndPresentIfNeededWithRootViewController:[UIViewController new] completion:^(NSError *error) {
if (error) {
return; // error occured while receiving user consent
}
// everything was fine, now you have user's consent
// initialize SDK here
}];
}];
return YES;
}
@end
Force Present Consent Dialog
If you want to have more control over Consent dialog, you can use the following code. Here you load Consent dialog separately and can store a reference to it or do whatever you need.
- Swift
- Objective-C
/// Initialisation
class YourAppDelegate: AppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?
) -> Bool {
let parameters = ConsentUpdateRequestParameters(
appKey: "YOUR_APP_KEY",
mediationSdkName: "YOUR_SDK_NAME",
mediationSdkVersion: "YOUR_SDK_VERSION",
COPPA: true
)
// requesting consent info update
ConsentManager.shared.requestConsentInfoUpdate(parameters: parameters) { error in
guard error == nil else { return } // error occured while receiving consent info
// loading consent dialog
ConsentManager.shared.load { dialog, error in
guard error == nil else { return } // error occured while loading consent dialog
// showing consent dialog
dialog?.present(rootViewController: UIViewController(), completion: { error in
guard error == nil else { return } // error occured while receiving user consent
// everything was fine, now you have user's consent
// initialize SDK here
})
}
}
return true
}
}
/// Initialisation
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
APDConsentUpdateRequestParameters *parameters = [[APDConsentUpdateRequestParameters alloc] initWithAppKey:@"YOUR_APP_KEY" mediationSdkName:@"YOUR_SDK_NAME" mediationSdkVersion:@"YOUR_SDK_VERSION" COPPA:true];
// requesting consent info update
[APDConsentManager.shared requestConsentInfoUpdateWithParameters:parameters completion:^(NSError * error) {
if (error) {
return; // error occured while receiving consent info
}
// loading consent dialog
[APDConsentManager.shared loadWithCompletion:^(APDConsentDialog *dialog, NSError *error) {
if (error) {
return; // error occured while loading consent dialog
}
if (dialog) {
// showing consent dialog
[dialog presentWithRootViewController:[UIViewController new] completion:^(NSError *error) {
if (error) {
return; // error occured while receiving user consent
}
// everything was fine, now you have user's consent
// initialize SDK here
}];
}
}];
}];
return YES;
}
YOUR_APP_KEY
is required parameter (Appodeal APP Key)
SDK only allows calling consent window api after synchronization
Check Consent Status
After synchronization completion, you can receive information about the previous user consent.
Before synchronization this parameter is undefined
- Swift
- Objective-C
// Check consent status
let status = ConsentManager.shared.status
// Check consent status
APDConsentStatus status = [APDConsentManager.shared status];
Revoke User Consent
If you need to revoke user consent, you can use the following code:
- Swift
- Objective-C
// Check consent status
ConsentManager.shared.revoke()
// Check consent status
[APDConsentManager.shared revoke];