- Requirements
- Installation
- Quick Start
- Setup and Usage
- ExportData
- Integration with Third-Party Libraries for Google Consent Mode
- Integration with Third-Party Libraries when Google Consent Mode is disabled
- Delaying Ads Display until User Consent
- WebView Consent Synchronization
Before integrating the SDK, ensure that your application meets the following requirements:
-
Minimum SDK Version:
21
(Android 5.0) -
Target/Compile SDK Version: The minimum required for Google Play compliance.
-
Internet Permission: The SDK requires internet access, so include the following permission in your
AndroidManifest.xml
:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Maven Central Repository: Ensure that mavenCentral()
is included in your project's build.gradle
file:
repositories {
mavenCentral()
}
To integrate the SDK, add the following dependency to your project's build.gradle
file:
implementation("com.clickio:clickioconsentsdk:1.0.0-rc15")
Here's the minimal implementation to get started:
Make sure to replace string "Clickio Site ID" with yours Site id.
with(ClickioConsentSDK.getInstance()) {
initialize(
context = context,
config = ClickioConsentSDK.Config("Clickio Site ID")
)
onReady { openDialog(context) }
}
In this code after successful initialization, the SDK will open the Consent dialog (a transparent Activity
with a WebView
).
All interactions with the Clickio SDK should be done using the ClickioConsentSDK.getInstance()
method to obtain the singleton instance of the SDK.
To initialize the SDK, use the initialize
method:
ClickioConsentSDK.getInstance().initialize(context: Context, config: Config)
The SDK requires a configuration object with the following parameters:
data class Config(
val siteId: String, // Your Clickio Site ID
val appLanguage: String? = null // Optional, two-letter language code in ISO 639-1
)
Use the onReady
callback to execute actions once the SDK is fully loaded:
ClickioConsentSDK.getInstance().onReady {
ClickioConsentSDK.getInstance().openDialog(context)
}
The SDK should not be used before onReady
is triggered, as it may lead to outdated data or errors.
The SDK provides the openDialog()
method to display the consent screen.
ClickioConsentSDK.getInstance().openDialog(
context: Context,
mode: ClickioConsentSDK.DialogMode = ClickioConsentSDK.DialogMode.DEFAULT
)
context
– Requires anActivity
context.mode
– Defines when the dialog should be shown. Possible values:DialogMode.DEFAULT
– Opens the dialog if GDPR applies and user hasn't given consent.DialogMode.RESURFACE
– Always forces dialog to open, regardless of the user’s jurisdiction, allowing users to modify settings for GDPR compliance or to opt out under US regulations.
If your Activity that calls openDialog()
uses launchMode="singleTask"
, make sure to call openDialog()
again in onNewIntent()
.
Returning to the app (e.g., via the launcher icon) with singleTask
launch mode can dismiss the SDK’s Activity that shows the Consent Dialog.
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
ClickioConsentSDK.getInstance().openDialog(context)
}
The SDK provides an onConsentUpdated
callback that is triggered whenever consent is updated:
ClickioConsentSDK.getInstance().onConsentUpdated {
// Handle consent update logic
}
To enable logging, use the following method:
ClickioConsentSDK.getInstance().setLogsMode(mode: LogsMode)
mode
– Defines whether logging is enabled or not:LogsMode.DISABLED
– Disables logging, default valueLogsMode.VERBOSE
– Enables logging
ClickioConsentSDK.getInstance().checkConsentScope(): String?
Returns the applicable consent scope as String.
- "gdpr" – The user is subject to GDPR requirements.
- "us" – The user is subject to US requirements.
- "out of scope" – The user is not subject to GDPR/US, other cases.
ClickioConsentSDK.getInstance().checkConsentState(): ConsentState?
Determines the consent state based on the scope and force flag and returns ConsentState.
ConsentState.NOT_APPLICABLE
– The user is not subject to GDPR/US.ConsentState.GDPR_NO_DECISION
– The user is subject to GDPR but has not made a decision.ConsentState.GDPR_DECISION_OBTAINED
– The user is subject to GDPR and has made a decision.ConsentState.US
– The user is subject to US regulations.
ClickioConsentSDK.getInstance().checkConsentForPurpose(purposeId: Int): Boolean?
Verifies whether consent for a specific TCF purpose has been granted by using IABTCF_PurposeConsents
string.
ClickioConsentSDK.getInstance().checkConsentForVendor(vendorId: Int): Boolean?
Verifies whether consent for a specific TCF vendor has been granted by using IABTCF_VendorConsents
string.
ExportData
is a class designed to retrieve consent values from SharedPreferences
. It provides methods to obtain various types of consent, including TCF, Google Consent Mode, and others.
Example of use
val exportData = ExportData(context)
val valueOfTCString = exportData.getTCString()
val listOfconsentedTCFPurposes = exportData.getConsentedTCFPurposes()
ExportData(context: Context)
context
– Requires anActivity
orAppilcation
context.
fun getTCString(): String?
Returns the IAB TCF v2.2 string if it exists.
fun getACString(): String?
Returns the Google additional consent string if it exists.
fun getGPPString(): String?
Returns the Global Privacy Platform (GPP) string if it exists.
fun getConsentedTCFVendors(): List<Int>?
Returns the IDs of TCF vendors that have given consent.
fun getConsentedTCFLiVendors(): List<Int>?
Returns the IDs of TCF vendors that have given consent for legitimate interests.
fun getConsentedTCFPurposes(): List<Int>?
Returns the IDs of TCF purposes that have given consent.
fun getConsentedTCFLiPurposes(): List<Int>?
Returns the IDs of TCF purposes that have given consent as Legitimate Interest.
fun getConsentedGoogleVendors(): List<Int>?
Returns the IDs of Google vendors that have given consent.
fun getConsentedOtherVendors(): List<Int>?
Returns the IDs of non-TCF vendors that have given consent.
fun getConsentedOtherLiVendors(): List<Int>?
Returns the IDs of non-TCF vendors that have given consent for legitimate interests.
fun getConsentedNonTcfPurposes(): List<Int>?
Returns the IDs of non-TCF purposes (simplified purposes) that have given consent.
fun getGoogleConsentMode(): GoogleConsentStatus?
Returns Google Consent Mode v2 flags wrapped into GoogleConsentStatus
class if Google Consent Mode enabled, otherwise will return null
.
data class GoogleConsentStatus(
val analyticsStorageGranted: Boolean?,
val adStorageGranted: Boolean?,
val adUserDataGranted: Boolean?,
val adPersonalizationGranted: Boolean?,
val securityStorageGranted: Boolean?,
val personalizationStorageGranted: Boolean?,
val functionalityStorageGranted: Boolean?
)
Represents the status of Google Consent Mode.
analyticsStorageGranted
— Consent for analytics storage.adStorageGranted
— Consent for ad storage.adUserDataGranted
— Consent for processing user data for ads.adPersonalizationGranted
— Consent for ad personalization.securityStorageGranted
— Consent for Security Storage.personalizationStorageGranted
— Consent for Personalization Storage.functionalityStorageGranted
— Consent for Functionality Storage.
Clickio Consent SDK supports automatic integration with external analytics and advertising platforms for Google Consent Mode V2 if enabled:
If the Firebase Analytics SDK is present in the project, the Clickio SDK will automatically send Google Consent flags to Firebase if Clickio Google Consent Mode integration enabled.
ClickioConsentSDK transmits consent flags immediately if they were updated after showing the consent dialog (when onConsentUpdated
is called) or during initialization if the consent has been accepted.
Also you might need to set default consent values in the app's AndroidManifest.xml
as described here.
After successfully transmitting the flags, a log message will be displayed (if logging is enabled) confirming the successful transmission. In case of an error, an error message will appear in the logs. You may need to update Firebase Analytics to a newer version in your project.
If any of these SDKs (Adjust, Airbridge, AppsFlyer) are present in the project, ClickioConsentSDK
will automatically send Google Consent flags to them if Clickio Google Consent Mode integration enabled.
However, interactions with ClickioConsentSDK
should be performed after initializing the SDK since ClickioConsentSDK
only transmits consent flags, while the initialization and configuration of the libraries are the responsibility of the app developer.
After successfully transmitting the flags, a log message will be displayed (if logging is enabled) to confirm the successful transmission. In case of an error, an error message will appear in the logs. You may need to update the SDK you are using (Adjust, Airbridge, or AppsFlyer) to a newer version in your project.
For other libraries, you can use the getGoogleConsentMode
method from the ExportData
class to retrieve the GoogleConsentStatus
.
For example, you can subscribe to the onConsentUpdated
callback and call getGoogleConsentMode
within it.
val exportData = ExportData(context)
ClickioConsentSDK.getInstance().onConsentUpdated {
val googleConsentFlags = exportData.getGoogleConsentMode()
if (googleConsentFlags != null){
// Send values to other SDK
}
}
If you need to send consent data on each subsequent app launch, it is recommended to wait for the onReady
callback and then call getGoogleConsentMode
.
Keep in mind: getGoogleConsentMode
can return null
if Google Consent Mode is disabled or unavailable.
If Clickio Google Consent Mode integration is disabled you can set consent flags manually.
Firebase Analytics example:
with(ClickioConsentSDK.getInstance()){
onConsentUpdated {
val purpose1 = checkConsentForPurpose(1)
val purpose3 = checkConsentForPurpose(3)
val purpose4 = checkConsentForPurpose(4)
val purpose7 = checkConsentForPurpose(7)
val purpose8 = checkConsentForPurpose(8)
val purpose9 = checkConsentForPurpose(9)
val adStorage = if (purpose1) ConsentStatus.GRANTED else ConsentStatus.DENIED
val adUserData = if (purpose1 && purpose7) ConsentStatus.GRANTED else ConsentStatus.DENIED
val adPersonalization = if (purpose3 && purpose4) ConsentStatus.GRANTED else ConsentStatus.DENIED
val analyticsStorage = if (purpose8 && purpose9) ConsentStatus.GRANTED else ConsentStatus.DENIED
val consentSettings = mapOf(
ConsentType.AD_STORAGE to adStorage,
ConsentType.AD_USER_DATA to adUserData,
ConsentType.AD_PERSONALIZATION to adPersonalization,
ConsentType.ANALYTICS_STORAGE to analyticsStorage
)
Firebase.analytics.setConsent(consentSettings)
}
}
More about Consent Mode flags mapping with TCF and non-TCF purposes
Make sure that no ads are displayed in the app until onReady
or onConsentUpdated
callback is triggered and checkConsentState() != GDPR_NO_DECISION
is confirmed. This ensures that ads are only shown after the user's consent status has been properly determined.
Note: You should make sure yourself, as shown in the example, that the ad initialization function is not called multiple times.
with(ClickioConsentSDK.getInstance()) {
onReady {
ClickioConsentSDK.getInstance().openDialog(context)
if (checkConsentState() != ClickioConsentSDK.ConsentState.GDPR_NO_DECISION) {
initAndShowAds()
}
}
onConsentUpdated {
if (checkConsentState() != ClickioConsentSDK.ConsentState.GDPR_NO_DECISION) {
initAndShowAds()
}
}
}
var adsStarted = false
// Example of function that handles ads initialization and displaying
fun initAndShowAds() {
if (!adsStarted) {
adsStarted = true
MobileAds.initialize(context) {
displayAd()
}
}
}
When an Android app contains both native content (built with Kotlin/Java) and web content inside a WebView
(e.g., embedded websites or widgets), there’s a risk that the Consent Management Platform (CMP) dialog may appear twice — once in the native UI and again in the WebView
.
The webViewLoadUrl
method helps synchronize consent between native and web layers.
It creates and returns a configured WebView
to handle saved consent, which you can then embed into your app screens as needed. You can also customize the appearance through the WebViewConfig
configuration class.
Tip: Use this method whenever you need to display web content that must respect the user’s consent settings already established in the native part of your app. This ensures a seamless experience and prevents duplicate consent prompts.
fun webViewLoadUrl(context: Context, url: String, webViewConfig: WebViewConfig): WebView
data class WebViewConfig(
val backgroundColor: Int // Default: 0 (transparent)
val height: Int // px; Default: -1( Match Parent)
val width: Int // px; Default: -1 (Match Parent)
val gravity: WebViewGravity // Default: CENTER (Gravity if appliable)
)
enum class WebViewGravity {
TOP, CENTER, BOTTOM
}
val myWebView = ClickioConsentSDK.getInstance().webViewLoadUrl(
context = context,
url = "https://example.com",
webViewConfig = WebViewConfig(
backgroundColor = android.graphics.Color.WHITE,
height = 600,
gravity = WebViewGravity.BOTTOM
)
)
binding.root.addView(myWebView)
val myWebView = remember {
ClickioConsentSDK.getInstance().webViewLoadUrl(
context = context,
url = "https://example.com"
)
}
Box(modifier = Modifier.fillMaxSize()) {
AndroidView(factory = { myWebView })
}