# Integration

In this section,
1. Integrate a [consent management platform](#consent-management-platform)
2. [Initialize Core SDK with modules](#initializing-core-with-modules)
3. Set optional per [publisher metadata](#setting-publisher-metadata)

## Consent Management Platform

The Core SDK requires a Consent Management Platform (CMP) to manage the current consent state of the user and to provide consent change notifications.

Chartboost supports the following CMP providers with open source CMP adapters for the Core SDK.


#### Google User Messaging Platform

| **Open source CMP adapter** | [https://github.com/ChartBoost/chartboost-core-android-consent-adapter-google-user-messaging-platform](https://github.com/ChartBoost/chartboost-core-android-consent-adapter-google-user-messaging-platform){:target="_blank"} |

To include the Google User Messaging Platform adapter into your Android project, add the following to your Gradle. Refer to the CMP's [adapter repository](https://github.com/ChartBoost/chartboost-core-android-consent-adapter-google-user-messaging-platform){:target="_blank"} for the latest compatible version.

```gradle
"implementation"("com.chartboost:chartboost-core-consent-adapter-google-user-messaging-platform:{{version}}")
```



#### Usercentrics

| **Open source CMP adapter** | [https://github.com/ChartBoost/chartboost-core-android-consent-adapter-usercentrics](https://github.com/ChartBoost/chartboost-core-android-consent-adapter-usercentrics){:target="_blank"} |

When setting up your Usercentrics account, it is required to use a TCF2 configuration so Usercentrics provides consent info as a TCF string, which is used by most advertising partners. The CCPA configuration is also encouraged. You can achieve a hybrid setup with these and other configurations by using Usercentrics geolocation rulesets.

For more info refer to [Usercentrics account setup](https://usercentrics.com/docs/config/account-config/){:target="_blank"} and [Usercentrics user guide to account interface](https://docs.usercentrics.com/?_gl=1*ozduci*_ga*MjY5OTU0NjguMTcyMDQ1OTMxMg..*_ga_2QB41H1S1Q*MTcyMDU0Njk1MC4yLjEuMTcyMDU0NzEwMy4yOS4wLjA.#/account-interface?id=create-new-configurations){:target="_blank"} docs.

To include the Usercentrics adapter into your Android project, add the following to your Gradle. Refer to the CMP's [adapter repository](https://github.com/ChartBoost/chartboost-core-android-consent-adapter-usercentrics){:target="_blank"} for the latest compatible version.

```gradle
"implementation"("com.chartboost:chartboost-core-consent-adapter-usercentrics:{{version}}")
```


### Integrating Consent Management Platform

The `ConsentManagementPlatform` is the entry point for integrating your CMP via CMP mediation. There are two ways of integrating consent depending upon your app’s use case.

Note that some CMPs do not support the Publisher Handled Consent use case. The table below shows which CMPs are able to perform the following use cases.

| Consent Management Platform    | CMP Handled Dialog (Concise) | CMP Handled Dialog (Detailed) | Publisher Handled Dialog |
|--------------------------------|------------------------------|-------------------------------|--------------------------|
| Google User Messaging Platform | ✅                           | ✅                            | ❌                       |
| Usercentrics                   | ✅                           | ✅                            | ✅                       |


#### CMP Handled Consent Dialog

This is the most straightforward use case where you simply want to use the consent dialog that your CMP provides. In the event that your CMP provides no consent dialog, no consent dialog will be shown.

Concise dialogs are the standard user-facing consent dialogs that are typical of the web world. Detailed consent dialogs are much more verbose and typically allows users to pick and choose each individual item they are consenting to.

As a general rule of thumb, use the concise dialogs for the initial user presentation of the consent dialog, and use the detailed consent dialog for users wishing to make modifications to their consent.

```kotlin
if (ChartboostCore.consent.shouldCollectConsent) {
    CoroutineScope(Main).launch {
        ChartboostCore.consent.showConsentDialog(
            activity,
            ConsentDialogType.CONCISE, // or ConsentDialogType.DETAILED
        )
    }
} else {
    Log.d("ConsentSample", "No need to show a consent dialog")
}
```

#### Publisher Handled Consent Dialog

For advanced Publishers who wish to manage the consent dialog themselves, the following examples demonstrate how to use `ConsentManagementPlatform` to set the user’s consent programmatically.

```kotlin
if (ChartboostCore.consent.shouldCollectConsent) {
    CoroutineScope(Main).launch {
        ChartboostCore.consent.grantConsent(
            context,
            ConsentSource.DEVELOPER,
        )
        // OR
        ChartboostCore.consent.denyConsent(
            context,
            ConsentSource.DEVELOPER,
        )
    }
} else {
    Log.d("ConsentSample", "No need to grant or deny consent")
}
```

### Unsupported CMPs

If you are using a CPM that Chartboost Core doesn't support, a custom CMP adapter module must be created. This has the benefits of being able to swap out CMPs easily and allows for a high degree of customization for your specific consent workflow. Additionally, a custom CMP adapter can be reused across multiple apps, cutting down on maintenance and improving quality.

See [Creating a Module](/en/mediation/integrate/core/android/creating-a-module/) to set up a custom CMP adapter module.


### Per-Partner Consent

<div class="alert alert-warning" role="alert">
  <b>Caution:</b> This section requires the <a href="/en/mediation/integrate/android/get-started/">Chartboost Mediation 5.0.0+ SDK</a> and at least one <a href="/en/mediation/integrate/android/integrate-network-sdks/" target="_blank">partner network adapter</a> integrated.
</div>

For advanced use cases, it may be desirable to specify consent on a per-Mediation partner basis. In lieu of specifying per-partner consent, the global consent of the CMP is used. Per-partner consent values take precedence over the global consent.

Not all CMPs support per-partner consent. The table below lists per-partner consent compatibility.

Per-partner consent is usually available via the detailed consent dialog. These consent signals will be sent to the Mediation partner adapters and applied in higher priority over the global consent settings.

| Consent Management Platform  | Per-Partner Consent Supported? |
|------------------------------|--------------------------------|
| Google UMP                   | ❌                            |
| Usercentrics                 | ✅                            |


## Initializing Core with Modules

The Core SDK and all specified modules will be initialized when `ChartboostCore.initializeSdk()` is called.

By default, the following module initializations will automatically be attempted without the Publisher needing to explicitly specify the module name when calling `ChartboostCore.initializeSdk()`.

| Module               |
| -------------------- |
| Chartboost Mediation |


### Initialization Flow

Once `ChartboostCore.initializeSdk()` has been called, the Core SDK initialization flow is as follows:

![](/assets/images/articles/CoreSDKInitializationFlow.png)

Core SDK Initialization flow can be broken down into two concurrent processes: locally specified modules and remotely specified modules.

Locally specified modules are modules that are explicitly specified by the Publisher in the `SdkConfiguration` object passed into the `ChartboostCore.initializeSdk()` call. These modules will be initialized immediately and do not wait for the configuration endpoint response.

Remotely specified modules are modules that are specified by the configuration endpoint. On a fresh install, these modules won’t be initialized until the configuration endpoint has given back a response. For subsequent launches when a cached configuration is available, the cached configuration will be used to initialize the modules it knows about to speed up initialization as much as possible.

### Advanced Features

#### Skipping Specific Modules

Sometimes it is desirable to skip the initialization of certain modules. This may be due to employing multipart module initialization, or disabling a module due to performance issues or crashing.

To skip specific modules, populate the `skippedModuleIdentifiers` property of the `SdkConfiguration` object that is passed into the `ChartboostCore.initializeSdk()` call.

See [Initialization Examples](#initialization-examples) for more information.

#### Multipart Module Initialization

The Core SDK supports multipart module initialization. This is an advanced use case where a Publisher wants to fully control what modules are initialized at various points in their app’s launch lifecycle. This allows for modules critical to app functionality to initialize first, and then some time later, initialize the non-essential or nice to have modules in a subsequent `ChartboostCore.initializeSdk()` call.

For example, a Publisher may wish to initialize an analytics module only at app launch, and then initialize the mediation module after a game’s assets have finished loading.

See [Initialization Examples](#initialization-examples) for more information.

### Handling Module Initialization Callbacks

When initializing modules, you have the option of getting notified when a module completes its initialization. To do so, pass in an instance conforming to `ModuleObserver` into the `ChartboostCore.initializeSdk()` call. 

Note that initializing an already-initialized module may trigger duplicate notifications to this observer, and initializing an initializing module will be a no-op.

A `ModuleInitializationResult` is given back once the module’s initialization is complete. The result contains various metrics pertaining to that particular module initialization attempt, including the module’s identifier and version.

### CMP Adapter Initialization

CMP adapters are considered to be modules by the Core SDK. While it is not explicitly necessary to initialize the Core SDK with a CMP module, failure to do so will have the following effects:

1. Downstream modules reliant upon consent information will not have any available and will assume that they are operating in an unconsented environment.
2. Calls made to `ConsentManagementPlatform` will be no-op as there is no CMP to forward the calls to.

**In the event that more than one CMP adapter is specified for initialization, the first one will be used.**

The Core SDK currently does not support multiple initialized instances of CMPs. If your consent use case requires the usage of multiple CMPs at the same time, it is recommended that you create a custom CMP adapter to achieve your use case.

See [Creating a Module](/en/mediation/integrate/core/android/creating-a-module/) for more information.

### Module Initialization Errors and Exceptions

While the `ChartboostCore.initializeSdk()` call can accept a null value for the `moduleObserver` parameter, it is highly recommended to provide an observer to receive module initialization callbacks. This will allow you to handle any errors or exceptions that may occur during a module's initialization, and be notified when a module is ready for use.

### Initialization Examples

#### Normal

Normal initialization workflow examples prioritizing simplicity of integration.

The following code snippets demonstrate:
1. Creating a CMP module that will be used as the source of truth for consent changes and values.
2. Initializing Chartboost Core and the CMP module
3. Subscribing to the initialization completion callback

```kotlin
// Create a CMP module such as the UsercentricsAdapter
val usercentricsAdapter = UsercentricsAdapter(UsercentricsOptions(
    settingsId = [publisher Usercentrics SettingsId]),
    templateIdToPartnerIdMap = templateIdToPartnerIdMap // map of usercentrics
    // template IDs to chartboost partner IDs. This is used for per-partner
    // consent. There are defaults so this is used for only custom partners.
)

// Initialize Core with CMP module
CoroutineScope(Main).launch {
    ChartboostCore.initializeSdk(context, SdkConfiguration(chartboostApplicationIdentifier = [publisher's Chartboost App ID], modules = listOf(usercentricsAdapter)), object : ModuleObserver {
        override fun onModuleInitializationCompleted(result: ModuleInitializationResult) {
            result.exception?.let {
                Log.e("Sample", "${result.moduleId} failed to initialize", it)
            } ?: Log.d("Sample", "${result.moduleId} initialized")
        }
    })
}
```
#### Advanced

Advanced initialization workflow examples for the [advanced features](#advanced-features).

The following code snippets demonstrate:
1. Creating a CMP module that will be used as the source of truth for consent changes and values.
2. Creating a custom module to be initialized first.
3. Initializing Chartboost Core, the CMP module, and the custom module, but skipping the automatic initialization of the Chartboost Mediation module.
4. Subscribing to the initialization completion callback.
5. Waiting a predefined set of time to simulate performing other work related to the app.
6. Initializing Chartboost Core again with the Chartboost Mediation module.

```kotlin
// Create a CMP module with UsercentricsAdapter
val usercentricsAdapter = UsercentricsAdapter(UsercentricsOptions(
    settingsId = [publisher Usercentrics SettingsId]),
    templateIdToPartnerIdMap = templateIdToPartnerIdMap // map of usercentrics
    // template IDs to chartboost partner IDs. This is used for per-partner
    // consent.
)

// Create a custom Module
val customModule = CustomModule(params)

// Initialize Core with CMP and custom modules
CoroutineScope(Main).launch {
    ChartboostCore.initializeSdk(context, SdkConfiguration(chartboostApplicationIdentifier = [publisher's Chartboost App ID], modules = listOf(customModule, usercentricsAdapter), skippedModuleIdentifiers = setOf("chartboost_mediation")), object : ModuleObserver {
        override fun onModuleInitializationCompleted(result: ModuleInitializationResult) {
            result.exception?.let {
                Log.e("Sample", "${result.moduleId} failed to initialize", it)
            } ?: Log.d("Sample", "${result.moduleId} initialized")
        }
    })
}

CoroutineScope(Main).launch {
    delay(5000) // waits some time as an example
    // Initialize Core again allowing the Mediation module to initialize
    ChartboostCore.initializeSdk(context, SdkConfiguration(chartboostApplicationIdentifier = [publisher's Chartboost App ID], modules = listOf()), object : ModuleObserver {
        override fun onModuleInitializationCompleted(result: ModuleInitializationResult) {
            result.exception?.let {
                Log.e("Sample", "${result.moduleId} failed to initialize", it)
            } ?: Log.d("Sample", "${result.moduleId} initialized")
        }
    })
}
```

## Setting Publisher Metadata

Publishers may optionally set additional information that may be used by any of the modules within the ecosystem to enhance their performance or supplement consent.

The following examples demonstrate setting each of the Publisher metadata fields.

```kotlin
ChartboostCore.publisherMetadata.setIsUserUnderage(true)
ChartboostCore.publisherMetadata.setPublisherSessionIdentifier("sessionid")
ChartboostCore.publisherMetadata.setPublisherAppIdentifier("appid")
ChartboostCore.publisherMetadata.setFramework("Unity", "2022.3 LTS")
ChartboostCore.publisherMetadata.setPlayerIdentifier("playerid")
```

