How to Enable Consent Management in Mobile SDKs

Enable consent management in the Kotlin and Swift SDKs and update the user’s consent choices at runtime.

This guide walks you through enabling consent management in the RudderStack Android (Kotlin) and iOS (Swift) SDKs and updating the user’s choices at runtime.

Consent management works from the consent settings you configure in the RudderStack dashboard, so set those up first:

  1. Open the destination you want to gate, and go to its Consent settings section.
  2. Choose Custom as the provider.
  3. Enter the consent category IDs that apply to this destination.
  4. Choose the consent logicAND (the user must consent to every listed category) or OR (consenting to at least one is enough).

For the full walkthrough, see Custom Consent Management and the Consent Management Overview.

Consent category IDs are case-sensitive. The IDs you pass to the SDK must match the ones you entered in the dashboard exactly, or the destination will not be gated the way you expect.

Consent management is disabled by default. Turn it on when you initialize the SDK, and supply the user’s current choices at the same time.

Enabling consent management is a load-time decision. You cannot turn it on later in the session — so if your app can ever need it, enable it at initialization and let the consent values reflect what the user has chosen.
kotlin
import com.rudderstack.sdk.kotlin.android.*
import com.rudderstack.sdk.kotlin.android.consent.*

val analytics = Analytics(
    configuration = Configuration(
        application = application,
        writeKey = WRITE_KEY,
        dataPlaneUrl = DATA_PLANE_URL,
        consentManagement = ConsentManagementConfiguration(
            enabled = true,
            provider = ConsentManagementProvider.CUSTOM,
            allowedConsentIds = listOf("marketing", "analytics"),
            deniedConsentIds = listOf("advertising"),
        ),
    )
)

The corresponding Java snippet is shown below:

java
import com.rudderstack.sdk.kotlin.android.consent.*;
import com.rudderstack.sdk.kotlin.android.javacompat.*;

import java.util.Arrays;

ConsentManagementConfiguration consentManagement = new ConsentManagementConfigurationBuilder()
        .setEnabled(true)
        .setProvider(ConsentManagementProvider.CUSTOM)
        .setAllowedConsentIds(Arrays.asList("marketing", "analytics"))
        .setDeniedConsentIds(Arrays.asList("advertising"))
        .build();

JavaAnalytics analytics = new JavaAnalytics(
        new ConfigurationBuilder(application, WRITE_KEY, DATA_PLANE_URL)
                .setConsentManagement(consentManagement)
                .build()
);

Configuration parameters

ParameterType
Description
enabledBooleanTurns consent management on for the session. Defaults to false.
providerEnumThe consent provider. Only the custom provider is supported — ConsentManagementProvider.CUSTOM (Kotlin) / .custom (Swift). This is the default.
allowedConsentIdsList of stringsThe consent category IDs the user has allowed. Defaults to empty.
deniedConsentIdsList of stringsThe consent category IDs the user has denied. Defaults to empty.
Supply at least one consent ID. Enabling consent management with both lists empty leaves it inactive for the whole session — see Handle empty consent IDs.

When the user changes their choices, pass the new state to setConsent. The values you supply fully replace the previous state, so always pass the user’s complete choices, not just what changed.

kotlin
analytics.setConsent(
    ConsentManagementOptions(
        allowedConsentIds = listOf("marketing"),
        deniedConsentIds = listOf("analytics", "advertising"),
    )
)

The corresponding Java snippet is shown below:

java
ConsentManagementOptions options = new ConsentManagementOptionsBuilder()
        .setAllowedConsentIds(Arrays.asList("marketing"))
        .setDeniedConsentIds(Arrays.asList("analytics", "advertising"))
        .build();

analytics.setConsent(options);

Calling setConsent takes effect immediately:

  • Destinations the user has newly allowed are initialized, without restarting the app.
  • Destinations the user has newly denied stop receiving events. The destination’s own SDK is left in place — most third-party SDKs have no reliable teardown — but RudderStack sends it nothing further.
  • Events tracked while a destination was denied are not delivered to it when the user allows it later.

Enabling consent management requires at least one consent category ID. How the SDK handles an empty pair depends on when it happens:

WhenWhat happens
At initialization, with both lists emptyAccepted, but consent management stays inactive for the session — exactly as if you had left it disabled. Events carry no consent block and no destination is gated. The SDK logs this at info.
At runtime, setConsent with both lists emptyIgnored, with a warning. Your current consent state is left unchanged.

To record that the user refused everything, pass those categories in deniedConsentIds — do not call setConsent with two empty lists:

kotlin
// Correct: the user rejected everything
analytics.setConsent(
    ConsentManagementOptions(
        allowedConsentIds = emptyList(),
        deniedConsentIds = listOf("marketing", "analytics", "advertising"),
    )
)

Only allowedConsentIds decides whether a destination is gated. deniedConsentIds is stamped onto the event for your records and is never consulted when resolving a destination.

To block a destination, ensure its consent category IDs are absent from allowedConsentIds — adding them to deniedConsentIds alone does not block it.

An empty call is never how a refusal is expressed — that is why the SDK treats it as a mistake rather than as “deny everything”.

See more

Questions? Let's figure it out together.

Join the RudderStack Slack community to connect with other users, customers, and the RudderStack team — or reach out for direct support.