Compliant with GDPR, CCPA, COPPA, LGPD, PECR, PDPA, PIPEDA, and more.
This guide explains how to integrate the UniConsent CMP SDK into your React Native application for handling GDPR IAB TCF 2.4 consent management.
You can find a demo app integrated with this SDK in the demo directory provided alongside the SDK package.
uniconsent-react-native-sdk-26.10.0.zip), downloaded from your UniConsent dashboard or obtained from support.Download and unzip the SDK package (e.g., uniconsent-react-native-sdk-26.10.0.zip). Inside you will find:
uniconsent-react-native-sdk-26.10.0.tgz — npm-installable SDK packageuniconsent-sdk/ — Pre-built SDK library filesdemo/ — Demo applicationREADME.md — DocumentationInstall the .tgz file using npm or Yarn:
# Replace <path-to-package-file.tgz> with the actual path to the file
npm install <path-to-package-file.tgz>
# or
yarn add <path-to-package-file.tgz>
Example: If you place the .tgz file in the root of your project:
npm install ./uniconsent-react-native-sdk-26.10.0.tgz
# or
yarn add file:./uniconsent-react-native-sdk-26.10.0.tgz
This SDK requires the following peer dependencies:
npm install react-native-webview react-native-default-preference react-native-device-info
# or
yarn add react-native-webview react-native-default-preference react-native-device-info
If developing for iOS, navigate to your project's ios directory and install the pods:
cd ios
pod install
cd ..
Before integrating the SDK, customize the consent banner appearance in the UniConsent Dashboard to match your brand and optimize consent rates.
Go to Projects → Select your Project → Settings → Step 5: UI & Style Settings to configure:
For more precise control, add custom CSS in the CSS Content field under Step 5. This is recommended to make the banner feel native to your app and achieve the best consent rate:
/* Example: Style the accept button to match your brand */
.unic-btn-accept {
background-color: #4CAF50;
border-radius: 8px;
font-weight: 600;
}
/* Example: Adjust banner font */
.unic-banner {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
/* Example: Make the reject button less prominent */
.unic-btn-reject {
background-color: transparent;
border: 1px solid #ccc;
color: #666;
}
Tip: A well-branded consent UI that feels native to your app typically achieves higher consent rates. Users are more likely to engage positively with a banner that matches the look and feel they expect.
Wrap your application's root component (or the relevant part) with UniConsentProvider. You must provide your licenseId (Publisher ID/pid from UniConsent).
// Your main App file (e.g., App.tsx or index.js)
import React from 'react';
import { UniConsentProvider } from 'uniconsent-sdk';
import YourAppRootComponent from './src/YourAppRootComponent';
const App = () => {
return (
<UniConsentProvider licenseId="YOUR_LICENSE_ID">
<YourAppRootComponent />
</UniConsentProvider>
);
};
export default App;
The SDK supports three display modes for the CMP UI, configured via the displayMode prop on UniConsentProvider:
| Mode | Description |
|---|---|
'fullScreen' | Full-screen page (default) |
'bottomSheet' | Modal sheet anchored to the bottom of the screen |
'dialog' | Centered modal dialog |
// Full screen (default — no prop needed)
<UniConsentProvider licenseId="YOUR_LICENSE_ID">
// Bottom sheet
<UniConsentProvider licenseId="YOUR_LICENSE_ID" displayMode="bottomSheet">
// Bottom sheet at 70% of the screen height
<UniConsentProvider licenseId="YOUR_LICENSE_ID" displayMode="bottomSheet" heightRatio={0.7}>
// Center dialog
<UniConsentProvider licenseId="YOUR_LICENSE_ID" displayMode="dialog">
// Center dialog at 80% width and 60% height
<UniConsentProvider licenseId="YOUR_LICENSE_ID" displayMode="dialog" widthRatio={0.8} heightRatio={0.6}>
Available from SDK version 26.8.0.
Both ratios are optional — every display mode works without them. Pass a ratio (a fraction of the screen, greater than 0 and at most 1) only to override the default size; invalid values throw RangeError:
| Prop | Applies to | Default when omitted |
|---|---|---|
heightRatio | 'bottomSheet', 'dialog' | Sheet: 90% of the screen. Dialog: 70% |
widthRatio | 'dialog' only | 90% of the screen width, up to 500 |
Ratios that don't apply to the chosen display mode are ignored ('fullScreen' ignores both).
Listen for SDK lifecycle events with the onEvent prop on UniConsentProvider.
Available event types:
'sdkInit' — SDK initialization started'ready' — SDK initialization completed'uiDisplay' — Consent UI is displayed'uiClose' — Consent UI is closed<UniConsentProvider
licenseId="YOUR_LICENSE_ID"
onEvent={(event) => {
switch (event.type) {
case 'ready':
console.log('SDK ready');
break;
case 'uiClose':
console.log('Consent UI closed');
break;
}
}}
>
<YourAppRootComponent />
</UniConsentProvider>
Use the useConsent hook within a component inside the Provider to get the openCMP function, then call it when needed (e.g., from a button press).
import React from 'react';
import { View, Text, Button, ActivityIndicator } from 'react-native';
import { useConsent } from 'uniconsent-sdk';
const ConsentInfoComponent = () => {
const { consentStatus, isLoading, openCMP } = useConsent();
return (
<View>
<Text>Consent Status:</Text>
{isLoading ? (
<ActivityIndicator />
) : (
<Text>{consentStatus ?? 'Initializing...'}</Text>
)}
<Button
title="Manage Privacy Settings"
onPress={() => openCMP()}
disabled={isLoading}
/>
</View>
);
};
Use the utility functions to check consent status directly without the hook:
import {
getTCString,
isEURegion,
isPurposeConsented,
isVendorConsented,
getConsentData,
} from 'uniconsent-sdk';
// Get the full TC String
const tcString = await getTCString();
// Check if user is in EU/EEA region
const inEU = await isEURegion();
// Check if a specific TCF purpose has consent (1-based ID)
const hasPurpose1 = await isPurposeConsented(1);
// Check if a specific vendor has consent (1-based ID)
const hasVendor755 = await isVendorConsented(755);
// Get all consent data as a single object
const consentData = await getConsentData();
Available from SDK version 26.7.0. If you build your own first-layer consent UI instead of showing the CMP webview, you can save consent directly:
import { agreeAll, rejectAll } from 'uniconsent-sdk';
// Grant consent for all purposes, special features and vendors
const saved = await agreeAll();
// Reject all purposes, special features and vendors
const rejected = await rejectAll();
Both APIs save the same consent values as the CMP UI flow (IAB TCF keys, additional consent and consent mode signals), update the provider's consentStatus and fire the uiClose event to onEvent. They use the licenseId registered by UniConsentProvider, so call them after the provider has mounted.
For users in the US and Canada, both APIs also save the CCPA, US State Privacy and IAB TCF Canada choice that applies to them, by the same rules as the CMP UI, and write the IAB GPP and US Privacy keys. Turn on the API-only modes in the project settings of the UniConsent dashboard so the CMP banner is not shown for those regions.
They also save the cookie categories choice where a cookie categories banner applies (every category, or only Strictly Necessary), and the project's custom purposes and custom vendors.
To know which first layer to show, call getPolicy() (from SDK version 26.10.0). It returns the policy that applies to the user, by the same rules as the CMP: gdpr (IAB TCF), tcfca (IAB TCF Canada), uss (US State Privacy), ccpa, categories (see Cookie Categories below) or none.
import { useEffect } from 'react';
import { useConsent, getPolicy } from 'uniconsent-sdk';
// inside a function component
const { consentStatus } = useConsent();
useEffect(() => {
if (consentStatus === 'pending') {
// the user needs to make a choice: show your first layer for this policy
getPolicy().then(policy => { /* gdpr, tcfca or categories */ });
}
}, [consentStatus]);
Important: Your custom first layer must still meet IAB TCF requirements (disclose purposes and vendors, and offer accept and reject with equal prominence). Users should still be able to open the full CMP UI (
openCMP()) to make granular choices.
If your app opens a WebView that loads a web page with the UniConsent CMP tag, you can pass the native consent status so the CMP tag recognises existing consent and does not show the banner again.
Use getConsentSyncScript() with injectedJavaScriptBeforeContentLoaded to inject consent before any page scripts run:
import React, { useState, useEffect } from 'react';
import { WebView } from 'react-native-webview';
import { getConsentSyncScript } from 'uniconsent-sdk';
const MyWebView = () => {
const [consentScript, setConsentScript] = useState<string | null>(null);
useEffect(() => {
getConsentSyncScript().then(setConsentScript);
}, []);
if (!consentScript) return null;
return (
<WebView
source={{ uri: 'https://example.com' }}
injectedJavaScriptBeforeContentLoaded={consentScript}
/>
);
};
The SDK provides helper functions for development and debugging:
import { listKV, clearKV } from 'uniconsent-sdk';
// Log all stored consent keys to console
await listKV();
// Clear all stored consent data
await clearKV();
UniConsentProvider Props| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
licenseId | string | Yes | — | Your UniConsent Publisher ID (pid). |
displayMode | CMPDisplayMode | No | 'fullScreen' | CMP display style: 'fullScreen', 'bottomSheet', or 'dialog'. |
heightRatio | number | No | Sheet: 0.9, dialog: 0.7 | UI height as a screen-height fraction in (0, 1]. Applies to 'bottomSheet' and 'dialog'. |
widthRatio | number | No | 0.9 (capped at 500) | Dialog width as a screen-width fraction in (0, 1]. Applies to 'dialog' only. |
onEvent | CMPEventCallback | No | — | Callback for SDK lifecycle events (sdkInit, ready, uiDisplay, uiClose). |
langCode | string | No | Device language | CMP language as a two-letter code, for example 'FR'. |
testRegion | string | No | User's region | For testing only: show the CMP as for a user in another region: 'EU', 'CA' (Canada), 'CAQC' (Quebec), 'US' plus a state code such as 'USCA' or 'USTX', or 'N' (outside these regions). Remove it in release builds. |
logLevel | 'debug' | 'error' | No | 'error' | 'debug' logs from the SDK and the CMP page. |
| Export | Description |
|---|---|
UniConsentProvider | React component to wrap your application. Requires licenseId prop. |
useConsent() | Hook returning { consentStatus, isLoading, openCMP }. |
| Function | Returns | Description |
|---|---|---|
getTCString() | Promise<string> | Get the IAB TCF consent string. |
isEURegion() | Promise<boolean> | Check if the user is in an EU/EEA region. |
isPurposeConsented(purposeId) | Promise<boolean> | Check consent for a specific TCF purpose (1-based ID). |
isVendorConsented(vendorId) | Promise<boolean> | Check consent for a specific TCF vendor (1-based ID). |
getConsentData() | Promise<ConsentData> | Get a comprehensive consent data object. |
getConsentSyncScript() | Promise<string> | Get a JS snippet to inject consent into a WebView. |
agreeAll() | Promise<boolean> | Grant consent for all purposes, special features and vendors (custom first layer). |
rejectAll() | Promise<boolean> | Reject all purposes, special features and vendors (custom first layer). |
getPolicy() | Promise<string> | The policy that applies to the user, for your own first layer: gdpr, tcfca, uss, ccpa, categories or none. |
listKV() | Promise<void> | Debug: log all stored consent keys to console. |
clearKV() | Promise<void> | Debug: clear all stored consent data. |
| Type | Description |
|---|---|
CMPDisplayMode | 'fullScreen' | 'bottomSheet' | 'dialog' |
CMPEventType | 'sdkInit' | 'ready' | 'uiDisplay' | 'uiClose' |
CMPEventCallback | (event: { type: CMPEventType }) => void |
ConsentContextValue | Shape of the useConsent() return value. |
ConsentData | Shape of the getConsentData() return value. |
ConsentData Fields| Field | Type | Description |
|---|---|---|
tcString | string | Full IAB TCF consent string. |
isEURegion | boolean | Whether the user is in an EU/EEA region. |
gdprApplies | boolean | GDPR applies flag. |
cmpSdkId | number | Registered CMP SDK ID (68 for UniConsent). |
cmpSdkVersion | number | CMP SDK version. |
policyVersion | number | TCF policy version. |
purposeConsents | string | Binary string of consented purposes (e.g., "10110"). |
vendorConsents | string | Binary string of consented vendors. |
additionalConsent | string | Google Additional Consent (AC) string. |
gvlVersion | number | Global Vendor List version used. |
Open the CMP at a specific screen, for example from a "Privacy settings" link in your app. The screen you ask for always opens. For US users, the settings screens open the CCPA or US State Privacy settings that apply to them. Users in Canada see the IAB TCF Canada version of the IAB TCF screens.
| Screen | Shows |
|---|---|
CMPStage.GDPRFirstScreen | First layer (banner) |
CMPStage.GDPRSecondScreen | Settings (purposes) |
CMPStage.GDPRVendorsScreen | Vendors |
CMPStage.CCPAFirstScreen | CCPA first layer |
CMPStage.CCPASecondScreen | CCPA settings |
CMPStage.USStateFirstScreen | US State Privacy first layer |
CMPStage.USStateSecondScreen | US State Privacy settings |
CMPStage.CategoriesFirstScreen | Cookie categories first layer (banner) |
CMPStage.CategoriesSecondScreen | Cookie categories settings |
import { UniConsentProvider, useConsent, CMPStage, getGEO, getGEOState } from 'uniconsent-sdk';
// show the CMP in French instead of the device language, with debug logs (use 'error', the default, in release builds)
<UniConsentProvider licenseId="YOUR_PUBLISHER_ID" langCode="FR" logLevel="debug">
{/* your app */}
</UniConsentProvider>
// for testing only: show the CMP as for a user in another region, 'EU', 'CA' (Canada), 'CAQC' (Quebec), 'US' plus a state code such as 'USCA' or 'USTX', 'BR', 'CN', 'ZA', 'VN' or any other country code, or 'N' (outside these regions). It also applies to getPolicy() and the consent checks; remove it in release builds
<UniConsentProvider licenseId="YOUR_PUBLISHER_ID" testRegion="CA">
{/* your app */}
</UniConsentProvider>
// inside a component: open the settings screen
const { openCMP } = useConsent();
openCMP(CMPStage.GDPRSecondScreen);
// the user's region and, for the US and Canada, the state or province code
const geo = await getGEO();
const state = await getGEOState();
The CMP stores the IAB GPP keys and the US Privacy key in the app's native storage (SharedPreferences on Android, UserDefaults on iOS), as the IAB specifications define them. Ad SDKs in your app read them from there; no code changes are needed. The GPP keys are written when GPP, US State Privacy or IAB TCF Canada is enabled in the project settings of the UniConsent dashboard. The US Privacy key is written whenever CCPA is enabled.
| Key | Value |
|---|---|
IABGPP_HDR_Version | GPP version (1) |
IABGPP_HDR_Sections | Section IDs in the GPP string, separated by _ |
IABGPP_HDR_GppString | The full GPP string |
IABGPP_GppSID | Section IDs that apply to the user, separated by _, or -1 when none apply |
IABGPP_2_String | IAB TCF EU string, when GDPR applies |
IABGPP_5_String | IAB TCF Canada string, when Canada TCF applies |
IABGPP_6_String | US Privacy string, when CCPA applies |
IABGPP_7_String | US National (usnat) string, when US State Privacy or CCPA applies |
IABGPP_8_String to IABGPP_27_String | The section for the user's state (8 California to 27 Rhode Island), when US State Privacy applies, or California under CCPA, following the GPP Sections setting |
IABUSPrivacy_String | US Privacy string whenever CCPA is enabled: the user's choice in the CCPA region, otherwise 1--- |
The keys are updated each time the CMP loads and after every consent choice. When GPP is turned off, the IABGPP_ keys are removed. To read them yourself:
import DefaultPreference from 'react-native-default-preference';
const gppString = await DefaultPreference.get('IABGPP_HDR_GppString');
const gppSid = await DefaultPreference.get('IABGPP_GppSID');
Apps support the same US and Canada options as websites: CCPA, US State Privacy (with the states list, GPP Sections and MSPA settings) and IAB TCF Canada. UniConsentProvider opens the CMP for Canadian users IAB TCF Canada applies to until they make a choice. US privacy is opt-out, so US users are not asked on their own: they see the US banner or settings when your app calls openCMP(), for example from a privacy settings link. Until then, when CCPA or US State Privacy is enabled, the SDK writes the default US Privacy and GPP keys for US users without showing anything: not opted out, or opted out when the device ad tracking opt-out is on. US State Privacy starts off for new Mobile App projects; turn it on in the dashboard.
When the user has turned off ad tracking on the device, the CMP treats it as a US opt-out of sale, sharing and targeted advertising, as Global Privacy Control does on websites. On iOS this is tracking not allowed in App Tracking Transparency; on Android it is a deleted advertising ID or limit ad tracking, read through Google Play services when your app includes it. A choice the user then saves in the banner takes precedence.
The SDK also returns the stored strings:
import { getGPPString, getGPPSID, getUSPrivacyString } from 'uniconsent-sdk';
const gppString = await getGPPString();
const gppSid = await getGPPSID();
const usPrivacy = await getUSPrivacyString();
Available from SDK version 26.10.0. Where a region uses cookie categories instead of IAB TCF or the US policies, the CMP shows a banner with four categories: Strictly Necessary, Performance, Functionality, and Targeting or Advertising. This applies to:
Opt-in categories start with only Strictly Necessary on, and UniConsentProvider opens the CMP (consentStatus is pending) until the user makes a choice, and again after you change the config version. Opt-out categories start with every category on (Targeting off when the device ad tracking opt-out is on in the US), and the app does not ask on its own: users change them from your privacy settings link. Opt-out applies to an opt-out rule for other countries and, in apps, to a Consent Categories project in the US.
Open the categories screens with CMPStage.CategoriesFirstScreen (banner) and CMPStage.CategoriesSecondScreen (settings). The testRegion prop also takes BR, CN, ZA, VN and other country codes, to test these regions.
Available from SDK version 26.10.0. The custom purposes and the custom vendors you add in the project settings of the UniConsent dashboard show in the CMP screens: the custom purposes in the IAB TCF first layer and settings and in the cookie categories settings, the custom vendors in the IAB TCF vendors list. In the CCPA and US State Privacy settings only sensitive custom purposes are listed. In the cookie categories settings the custom vendors follow the Targeting or Advertising category. Where IAB TCF does not apply (cookie categories and the US), the custom vendors are listed read-only under Vendors List in the menu, and in the cookie categories settings under Targeting or Advertising.
To start or stop your own SDKs by them, ask the SDK whether the app may use a custom purpose or custom vendor now. The answer follows the user's policy, by the same rules the CMP uses for tags:
import { isCustomPurposeConsented, isCustomVendorConsented, getCustomConsents } from 'uniconsent-sdk';
// inside an async function
if (await isCustomPurposeConsented(1)) {
// start the SDK your custom purpose 1 covers
}
const vendorAllowed = await isCustomVendorConsented(2);
const all = await getCustomConsents(); // { purposes: { '1': true }, vendors: { '2': false } }
Call them again after the CMP closes or the consent changes. Ids the project does not have, and every id before the SDK is ready, return false.
The CMP can list the third-party SDKs in your app (ad networks, analytics, attribution and others) with their company, what they are used for and their privacy policy. Users see them under Vendors List, read-only in every region: there are no toggles, and your app keeps turning each SDK on or off from the user's choices for purposes or cookie categories.
To set the list, turn on Enable Third-party SDKs in Step 4: Advanced Features of your app project, pick your SDKs in the Third-party SDKs tab or add your own, then save and publish. No code is needed in your app.
openCMP() function obtained from the useConsent hook.UniConsentProvider automatically checks consent status when your app starts, including whether the Global Vendor List (GVL) has been updated since the user last gave consent. If the GVL version has changed, the user will be re-prompted.getGPPString(), getGPPSID() and getUSPrivacyString()openCMP(stage); add the langCode and logLevel props, getGEO() and getGEOState()CMPStage.CCPAFirstScreen and CMPStage.USStateFirstScreen; add the testRegion prop to test the CMP as a user in another region, such as CanadaCMPStage.CategoriesFirstScreen and CMPStage.CategoriesSecondScreengetPolicy(); agreeAll() and rejectAll() also save the cookie categories, custom purposes and custom vendorstestRegion prop also takes BR, CN, ZA, VN and other country codes, and applies to getPolicy() and the consent checksisCustomPurposeConsented(), isCustomVendorConsented() and getCustomConsents(): the custom purposes and custom vendors the app may use now, under the user's policyPrivacy laws, consent and compliance updates, a few emails a month.