Documentation Index
Fetch the complete documentation index at: https://docs.cloudx.io/llms.txt
Use this file to discover all available pages before exploring further.
CloudX Android SDK
Automated Integration with Claude Code
Integrate CloudX SDK in 15 minutes with AI-powered agents:
Requires Claude Code.
# Install CloudX agents
bash <(curl -fsSL https://raw.githubusercontent.com/cloudx-io/cloudx-sdk-agents/main/scripts/install.sh)
# In your Android project:
claude "Use @agent-cloudx-android-integrator to integrate CloudX SDK with app key: YOUR_KEY"
- First-look CloudX with automatic fallback to existing ad setup
- Privacy compliance validation (GDPR, CCPA)
- Build verification catches errors early
- Preserves existing ad setup as backup
Full Setup Guide
Manual Installation
Requires Android API 23+ and Java 8+.
Add the CloudX SDK to your app’s build.gradle:
dependencies {
implementation("io.cloudx:sdk:3.2.0")
// Adapters for ad networks
implementation("io.cloudx:adapter-meta:3.2.0") // Meta Audience Network 6.20.0 by default
implementation("io.cloudx:adapter-vungle:3.2.0") // Vungle SDK 7.7.1
implementation("io.cloudx:adapter-inmobi:3.2.0") // InMobi SDK 11.1.1
implementation("io.cloudx:adapter-mintegral:3.2.0") // Mintegral SDK 17.0.91
implementation("io.cloudx:adapter-unityads:3.2.0") // Unity Ads SDK 4.17.0
implementation("io.cloudx:adapter-magnite:3.2.0") // Magnite SDK 0.0.14
}
Bidder Network Guides
Use the bidder guides for network-side account setup and CloudX dashboard mapping:
This page focuses on SDK installation, initialization, and ad loading.
Mintegral Maven repository
If you add io.cloudx:adapter-mintegral to your dependencies, Gradle must also resolve Mintegral’s mediation SDK artifacts (for example com.mbridge.msdk.oversea:mbridge_android_sdk). Those artifacts are hosted on Mintegral’s Maven repository, not Maven Central. google() and mavenCentral() alone are not enough — builds fail with an error such as Could not find com.mbridge.msdk.oversea:mbridge_android_sdk until this repository is declared.
Add the repository next to your other Maven repos (typical locations: root build.gradle / build.gradle.kts inside allprojects { repositories { … } }, or dependencyResolutionManagement.repositories in settings.gradle, depending on your Gradle template):
maven {
url = uri("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
}
Use the same adapter version as your other io.cloudx:adapter-* lines (for example implementation("io.cloudx:adapter-mintegral:3.2.0") when your CloudX stack is on 3.2.0).
io.cloudx:adapter-meta:3.2.0 brings in Meta Audience Network 6.20.0 transitively by default. If your app uses CloudX native ads, add Meta Audience Network 6.21.0 or newer explicitly in your app module:
dependencies {
implementation("io.cloudx:adapter-meta:3.2.0")
implementation("com.facebook.android:audience-network-sdk:6.21.0")
}
Initialization
// Initialize with app key
CloudX.initialize(
configuration = CloudXInitializationConfiguration.builder("your-app-key-here")
.build(),
listener = object : CloudXInitializationListener {
override fun onInitialized(configuration: CloudXSdkConfiguration) {
Log.d("CloudX", "CloudX SDK initialized successfully")
}
override fun onInitializationFailed(cloudXError: CloudXError) {
Log.e("CloudX", "Failed to initialize CloudX SDK: ${cloudXError.message}")
}
}
)
Ad Integration
Banner Ads (320x50)
class MainActivity : AppCompatActivity(), CloudXAdViewListener, CloudXAdRevenueListener {
private lateinit var bannerAd: CloudXAdView
private fun createBannerAd() {
bannerAd = CloudX.createBanner(this, "your-banner-ad-unit-id")
bannerAd.listener = this
bannerAd.revenueListener = this
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
layoutParams.gravity = Gravity.CENTER_HORIZONTAL
findViewById<LinearLayout>(R.id.banner_container).addView(bannerAd, layoutParams)
}
override fun onDestroy() {
super.onDestroy()
bannerAd.destroy()
}
// CloudXAdViewListener callbacks
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "Banner ad loaded from ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "Banner ad failed to load: ${cloudXError.message}")
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "Banner ad clicked")
}
override fun onAdExpanded(cloudXAd: CloudXAd) {
Log.d("CloudX", "Banner ad expanded")
}
override fun onAdCollapsed(cloudXAd: CloudXAd) {
Log.d("CloudX", "Banner ad collapsed")
}
// CloudXAdRevenueListener callback
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "Banner revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
}
Banner ads auto-refresh by default. To control refresh manually:
bannerAd.stopAutoRefresh() // Stop auto-refresh
bannerAd.load() // Manually load a new ad
bannerAd.startAutoRefresh() // Re-enable auto-refresh
Optional placement and custom data for tracking:
bannerAd.setPlacement("home_screen")
bannerAd.setCustomData("level:5,coins:100")
MREC Ads (300x250)
class MainActivity : AppCompatActivity(), CloudXAdViewListener, CloudXAdRevenueListener {
private lateinit var mrecAd: CloudXAdView
private fun createMrecAd() {
mrecAd = CloudX.createMREC(this, "your-mrec-ad-unit-id")
mrecAd.listener = this
mrecAd.revenueListener = this
val layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
layoutParams.gravity = Gravity.CENTER_HORIZONTAL
findViewById<LinearLayout>(R.id.mrec_container).addView(mrecAd, layoutParams)
}
override fun onDestroy() {
super.onDestroy()
mrecAd.destroy()
}
// CloudXAdViewListener callbacks (same as Banner)
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC ad loaded from ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "MREC ad failed to load: ${cloudXError.message}")
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC ad clicked")
}
override fun onAdExpanded(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC ad expanded")
}
override fun onAdCollapsed(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC ad collapsed")
}
// CloudXAdRevenueListener callback
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "MREC revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
}
MREC ads also auto-refresh by default. Use the same refresh control methods as Banner ads.
Interstitial Ads
class MainActivity : AppCompatActivity(), CloudXInterstitialListener, CloudXAdRevenueListener {
private lateinit var interstitialAd: CloudXInterstitialAd
private fun createInterstitialAd() {
interstitialAd = CloudX.createInterstitial(this, "your-interstitial-ad-unit-id")
interstitialAd.listener = this
interstitialAd.revenueListener = this
interstitialAd.load()
}
private fun showInterstitialAd() {
if (interstitialAd.isAdReady) {
// Basic show
interstitialAd.show(this)
// Or with optional placement and custom data for tracking
// interstitialAd.show(this, "level_complete", "level:5,score:1000")
} else {
Log.w("CloudX", "Interstitial ad not ready yet")
}
}
override fun onDestroy() {
super.onDestroy()
interstitialAd.destroy()
}
// CloudXInterstitialListener callbacks
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "Interstitial ad loaded from ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "Interstitial ad failed to load: ${cloudXError.message}")
}
override fun onAdDisplayed(cloudXAd: CloudXAd) {
Log.d("CloudX", "Interstitial ad displayed")
}
override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
Log.e("CloudX", "Interstitial ad failed to display: ${cloudXError.message}")
}
override fun onAdHidden(cloudXAd: CloudXAd) {
Log.d("CloudX", "Interstitial ad hidden")
// Reload for next use
interstitialAd.load()
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "Interstitial ad clicked")
}
// CloudXAdRevenueListener callback
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "Interstitial revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
}
Rewarded Ads
class MainActivity : AppCompatActivity(), CloudXRewardedListener, CloudXAdRevenueListener {
private lateinit var rewardedAd: CloudXRewardedAd
private fun createRewardedAd() {
rewardedAd = CloudX.createRewarded(this, "your-rewarded-ad-unit-id")
rewardedAd.listener = this
rewardedAd.revenueListener = this
rewardedAd.load()
}
private fun showRewardedAd() {
if (rewardedAd.isAdReady) {
// Basic show
rewardedAd.show(this)
// Or with optional placement and custom data for tracking
// rewardedAd.show(this, "bonus_coins", "level:5,coins:100")
} else {
Log.w("CloudX", "Rewarded ad not ready yet")
}
}
override fun onDestroy() {
super.onDestroy()
rewardedAd.destroy()
}
// CloudXRewardedListener callbacks
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "Rewarded ad loaded from ${cloudXAd.networkName}")
}
override fun onAdLoadFailed(adUnitId: String, cloudXError: CloudXError) {
Log.e("CloudX", "Rewarded ad failed to load: ${cloudXError.message}")
}
override fun onAdDisplayed(cloudXAd: CloudXAd) {
Log.d("CloudX", "Rewarded ad displayed")
}
override fun onAdDisplayFailed(cloudXAd: CloudXAd, cloudXError: CloudXError) {
Log.e("CloudX", "Rewarded ad failed to display: ${cloudXError.message}")
}
override fun onAdHidden(cloudXAd: CloudXAd) {
Log.d("CloudX", "Rewarded ad hidden")
// Reload for next use
rewardedAd.load()
}
override fun onAdClicked(cloudXAd: CloudXAd) {
Log.d("CloudX", "Rewarded ad clicked")
}
override fun onUserRewarded(cloudXAd: CloudXAd, reward: CloudXReward) {
Log.d("CloudX", "User rewarded: ${reward.amount} ${reward.label}")
// Grant the reward to the user
}
// CloudXAdRevenueListener callback
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "Rewarded revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
}
Native Ads (Reels)
Coming Soon — Native ads are not yet available for general use. This section is published for early integration partners only. The native ads API is subject to change before public release.
Native ads let you render ad creatives using your own UI components — title, body, icon, media, call-to-action — in your own layout. With video creatives and the right playback settings, native ads become full-screen vertical “Reels” (the same UX as Instagram Reels or TikTok).
A Reel is built from three things:
- A native ad with video content. The ad’s
mediaView contains the video player. Other assets (title, body, icon, CTA) are overlaid on top.
- Video playback settings. Three properties on the loader disable fullscreen, start the video with sound, and hide media controls.
- A full-screen paging container. A
ViewPager2 with android:orientation="vertical". Each page is one Reel.
Reels API Surface
| Capability | CloudX API | Description |
|---|
| Detect video creative | ad.nativeAd?.isVideoContent | Returns true when the loaded creative is a video |
| Get video duration | ad.nativeAd?.videoDuration | Duration of the video in seconds (0.0 if unknown) |
| Ad dismissed by user | onNativeAdClosed(ad) listener callback | Fires when the user reports or hides the ad via AdChoices |
| Disable fullscreen | loader.isVideoFullScreenDisabled = true | Prevents the video from entering fullscreen on tap |
| Start unmuted | loader.isStartVideoUnmuted = true | Starts playback with sound on |
| Hide media controls | loader.isVideoMediaControlsHidden = true | Hides play/pause and progress bar controls |
Native ads currently require the Meta Audience Network adapter (adapter-meta). Bids from other adapters are not yet supported for the native format.
Requirements
- CloudX Android SDK 3.2.0+
io.cloudx:adapter-meta:3.2.0+
- Meta Audience Network SDK 6.21.0+
- Android API 23+
Create a Layout and View Binder
res/layout/native_ad_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<FrameLayout
android:id="@+id/native_ad_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/native_ad_icon"
android:layout_width="48dp"
android:layout_height="48dp" />
<TextView
android:id="@+id/native_ad_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/native_ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<FrameLayout
android:id="@+id/native_ad_media_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/native_ad_advertiser"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#888" />
<Button
android:id="@+id/native_ad_cta"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
val binder = CloudXNativeAdViewBinder.Builder(R.layout.native_ad_layout)
.setTitleTextViewId(R.id.native_ad_title)
.setBodyTextViewId(R.id.native_ad_body)
.setIconImageViewId(R.id.native_ad_icon)
.setMediaContentViewGroupId(R.id.native_ad_media_container)
.setCallToActionButtonId(R.id.native_ad_cta)
.setOptionsContentViewGroupId(R.id.native_ad_options)
.setAdvertiserTextViewId(R.id.native_ad_advertiser)
.build()
class YourActivity : AppCompatActivity(), CloudXNativeAdListener, CloudXAdRevenueListener {
private lateinit var nativeAdLoader: CloudXNativeAdLoader
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
nativeAdLoader = CloudX.createNativeAdLoader(this, "your-native-ad-unit-id")
nativeAdLoader.nativeAdListener = this
nativeAdLoader.revenueListener = this
nativeAdLoader.isVideoFullScreenDisabled = true
nativeAdLoader.isStartVideoUnmuted = true
nativeAdLoader.isVideoMediaControlsHidden = true
}
override fun onDestroy() {
super.onDestroy()
nativeAdLoader.destroy()
}
}
| Property | Default | Reels Value | Description |
|---|
isVideoFullScreenDisabled | false | true | Prevents the video from entering fullscreen when tapped |
isStartVideoUnmuted | false | true | Starts video playback with sound on |
isVideoMediaControlsHidden | false | true | Hides play/pause and progress bar controls |
Set these properties before calling loadAd(). They are ignored for static image creatives. For a Reels-style feed, set all three to true.
Load the Ad
Flow A — Load into a pre-built view:
val adView = CloudXNativeAdView(this, binder)
nativeAdLoader.loadAd(adView)
Flow B — Load first, render later (deferred rendering):
nativeAdLoader.loadAd()
override fun onNativeAdLoaded(adView: CloudXNativeAdView?, ad: CloudXAd) {
val newAdView = CloudXNativeAdView(this@YourActivity, binder)
nativeAdLoader.render(newAdView, ad)
container.addView(newAdView)
}
Handle Callbacks
// Required callbacks
override fun onNativeAdLoaded(adView: CloudXNativeAdView?, ad: CloudXAd) {
Log.d("CloudX", "Native ad loaded from ${ad.networkName}")
ad.nativeAd?.let { nativeAd ->
if (nativeAd.isVideoContent) {
Log.d("CloudX", "Video duration: ${nativeAd.videoDuration}s")
}
}
adView?.let { container.addView(it) }
}
override fun onNativeAdLoadFailed(adUnitId: String, error: CloudXError) {
Log.e("CloudX", "Native ad failed to load: ${error.message}")
}
override fun onNativeAdClicked(ad: CloudXAd) {
Log.d("CloudX", "Native ad clicked")
}
// Optional callbacks (default no-op)
override fun onNativeAdExpired(ad: CloudXAd) {
Log.d("CloudX", "Native ad expired — destroy and reload")
nativeAdLoader.destroy(ad)
nativeAdLoader.loadAd()
}
override fun onNativeAdClosed(ad: CloudXAd) {
Log.d("CloudX", "User dismissed the ad via AdChoices")
nativeAdLoader.destroy(ad)
}
// Revenue callback
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "Native ad revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
Clean Up
Always destroy ads when you’re done with them:
// Destroy a specific loaded ad
nativeAdLoader.destroy(ad)
// Destroy the loader and all associated resources
nativeAdLoader.destroy()
Native Ad Assets (CloudXNativeAd)
The CloudXNativeAd interface is available via ad.nativeAd in listener callbacks:
| Property | Type | Description |
|---|
title | String? | Headline text |
body | String? | Body / description text |
callToAction | String? | CTA button text (e.g., “Install Now”) |
advertiser | String? | Advertiser name |
icon | CloudXNativeAdImage? | App icon (as Drawable or Uri) |
mainImage | CloudXNativeAdImage? | Main image (static creatives) |
mediaView | View? | Video/media player view (adapter-provided) |
optionsView | View? | AdChoices or options view (adapter-provided) |
mediaContentAspectRatio | Float | Aspect ratio of the media content |
starRating | Double? | App store rating (0–5) |
isVideoContent | Boolean | Whether the creative is a video |
videoDuration | Double | Video length in seconds (0.0 if unknown) |
isExpired | Boolean | Whether the ad has expired |
Reels Feed Tips
- Use a
ViewPager2 with android:orientation="vertical". Each item should be MATCH_PARENT in both dimensions.
- Call
prepareForReuse() on the CloudXNativeAdView when recycling items.
- Create one
CloudXNativeAdLoader per slot. Load ads sequentially.
- Destroy ads when no longer needed via
destroy(ad).
The CloudXAd object is passed to listener callbacks and contains information about the loaded/displayed ad:
| Property | Type | Description |
|---|
adFormat | CloudXAdFormat | Ad format (BANNER, MREC, INTERSTITIAL, REWARDED) |
adUnitId | String | The ad unit ID |
networkName | String | Name of the winning ad network |
networkPlacement | String? | Network-specific placement ID |
placement | String? | Custom placement set via setPlacement() |
revenue | Double | Impression-level revenue in USD |
override fun onAdLoaded(cloudXAd: CloudXAd) {
Log.d("CloudX", "Ad format: ${cloudXAd.adFormat}")
Log.d("CloudX", "Network: ${cloudXAd.networkName}")
Log.d("CloudX", "Revenue: ${cloudXAd.revenue}")
}
Error Handling
All SDK errors are returned as CloudXError objects in listener callbacks:
| Property | Type | Description |
|---|
code | CloudXErrorCode | Error category |
message | String | Human-readable description |
cause | Throwable? | Optional underlying exception |
formattedMessage | String | Pre-formatted message including code and description |
Error Code Categories
| Range | Category | Common Codes |
|---|
| 0 | General | INTERNAL_ERROR |
| 100-199 | Network | NETWORK_ERROR, NETWORK_TIMEOUT, NETWORK_SERVER_ERROR, NETWORK_NO_CONNECTION |
| 200-299 | Initialization | NOT_INITIALIZED, SDK_DISABLED, NO_ADAPTERS_FOUND, INVALID_APP_KEY |
| 300-399 | Ad Loading | NO_FILL, INVALID_AD_UNIT, ADS_DISABLED |
| 400-499 | Display | AD_NOT_READY, AD_ALREADY_SHOWING |
| 600-699 | Adapter | ADAPTER_NO_FILL, ADAPTER_TIMEOUT, ADAPTER_LOAD_TIMEOUT, ADAPTER_INITIALIZATION_ERROR |
Advanced Features
Debug Logging
CloudX.setMinLogLevel(CloudXLogLevel.DEBUG) // Enable debug logging
CloudX.setMinLogLevel(CloudXLogLevel.NONE) // Disable all logging
Log Levels: VERBOSE < DEBUG < INFO < WARN < ERROR < NONE
Filter logcat with tag CloudX to see SDK logs.
Impression-Level Revenue Tracking
Set a revenueListener on any ad format to receive impression-level revenue (ILR) callbacks. The CloudXAd object contains the revenue value in USD and the winning network name.
bannerAd.revenueListener = object : CloudXAdRevenueListener {
override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
Log.d("CloudX", "Revenue: ${cloudXAd.revenue} from ${cloudXAd.networkName}")
}
}
Works with all ad formats (banner, MREC, interstitial, rewarded).
Test Mode
Test mode is server-controlled via device whitelisting. This provides better security and control over which devices receive test ads.
To enable test mode:
-
Initialize the SDK and check logcat for your device advertising ID:
[CloudX][AdvertisingIdProvider] Device IFA for test whitelisting: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX (LAT: false)
-
Copy the advertising ID and add it to your device whitelist on the CloudX server dashboard
-
The SDK will automatically configure adapters for test mode and include the test flag in bid requests
Note: Test mode is determined by the server, so you don’t need to change any code between development and production builds.
Privacy Compliance
The CloudX SDK supports GDPR and CCPA privacy compliance by reading standard IAB privacy strings from SharedPreferences. These values are typically set automatically by your Consent Management Platform (CMP) such as Google UMP, OneTrust, or Sourcepoint.
How It Works
The SDK automatically detects user location and reads consent signals:
- EU Users (GDPR): Checks TCF v2 consent for purposes 1 and 2 per the IAB Global Vendor List and vendor consent (CloudX Vendor ID: 1510)
- US Users (CCPA): Checks for sale/sharing opt-out signals
- Other Regions: No restrictions applied
When consent is denied or user opts out, the SDK removes PII from ad requests:
- Advertising ID (GAID) is cleared
- Geo coordinates (lat/lon) are removed
- User key-values are not sent
- Hashed user ID is excluded
Supported Privacy Keys
| Key | Standard | Description |
|---|
IABGPP_HDR_GppString | GPP | Global Privacy Platform string (modern) |
IABGPP_GppSID | GPP | Section IDs (e.g., “2” for EU, “7” for US-National, “8” for US-CA) |
IABTCF_TCString | TCF v2 | GDPR consent string (legacy) |
IABTCF_gdprApplies | TCF v2 | Whether GDPR applies (1 = yes, 0 = no) |
IABUSPrivacy_String | US Privacy | CCPA privacy string (legacy, e.g., “1YNN”) |
Note: The SDK prioritizes GPP (modern standard) over legacy TCF/US Privacy strings when both are available.
Manual Privacy API
If you manage user consent yourself (without a CMP), you can set GDPR and CCPA privacy status directly. These can be called before or after SDK initialization.
// GDPR consent: true, false, or null to defer to CMP
CloudX.setHasUserConsent(true)
// CCPA do-not-sell: true, false, or null to defer to CMP
CloudX.setDoNotSell(true)
When both manual values and CMP signals are present, CMP signals (GPP/TCF/US Privacy) take priority. Manual values act as a fallback when no CMP is integrated.
User Targeting
// Set hashed user ID for targeting
CloudX.setHashedUserId("hashed-user-id")
// Set custom user key-value pairs
CloudX.setUserKeyValue("age", "25")
CloudX.setUserKeyValue("gender", "male")
CloudX.setUserKeyValue("location", "US")
// Set custom app key-value pairs
CloudX.setAppKeyValue("app_version", "1.0.0")
CloudX.setAppKeyValue("user_level", "premium")
// Clear all custom key-values
CloudX.clearAllKeyValues()
Support
For support, contact mobile@cloudx.io