Skip to main content

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 iOS SDK

Requires iOS 13.0+, Xcode 16.0+, and Swift 6.0+.

Installation

CocoaPods

Podfile
platform :ios, '13.0'

target 'YourApp' do
  use_frameworks!

  # Core SDK
  pod 'CloudXCore', '~> 3.2.0'

  # Adapters for ad networks (add as needed)
  pod 'CloudXMetaAdapter', '~> 3.2.0'       # Meta Audience Network 6.9.0+
  pod 'CloudXVungleAdapter', '~> 3.2.0'     # Vungle SDK 7.4.0+
  pod 'CloudXInMobiAdapter', '~> 3.2.0'     # InMobi SDK 11.0.0+
  pod 'CloudXMintegralAdapter', '~> 3.2.0'  # Mintegral SDK 8.0+
  pod 'CloudXUnityAdsAdapter', '~> 3.2.0'   # Unity Ads SDK 4.17.0+
  pod 'CloudXMagniteAdapter', '~> 3.2.0'    # Magnite SDK 0.0.8+
end
pod install --repo-update

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.

Initialization

#import <CloudXCore/CloudXCore.h>

CLXInitializationConfiguration *config =
    [CLXInitializationConfiguration configurationWithAppKey:@"your-app-key-here"];

[[CloudXCore shared] initializeWithConfiguration:config completion:^(CLXSdkConfiguration *sdkConfig, CLXError * _Nullable error) {
    if (sdkConfig) {
        NSLog(@"CloudX SDK initialized successfully");
    } else {
        NSLog(@"Failed to initialize CloudX SDK: %@", error.localizedDescription);
    }
}];

Ad Integration

@interface YourViewController () <CLXBannerDelegate, CLXAdRevenueDelegate>
@property (nonatomic, strong) CLXBannerAdView *bannerAd;
@end

@implementation YourViewController

- (void)createBannerAd {
    self.bannerAd = [[CloudXCore shared] createBannerWithAdUnitId:@"your-banner-ad-unit-id"
                                                   viewController:self];
    self.bannerAd.delegate = self;
    self.bannerAd.revenueDelegate = self;

    if (self.bannerAd) {
        self.bannerAd.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:self.bannerAd];

        [NSLayoutConstraint activateConstraints:@[
            [self.bannerAd.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
            [self.bannerAd.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
            [self.bannerAd.widthAnchor constraintEqualToConstant:320],
            [self.bannerAd.heightAnchor constraintEqualToConstant:50]
        ]];

        [self.bannerAd load];
    }
}

- (void)dealloc {
    [self.bannerAd destroy];
}

#pragma mark - CLXBannerDelegate

- (void)didLoadAd:(CLXAd *)ad {
    NSLog(@"Banner ad loaded from %@", ad.networkName);
}

- (void)didFailToLoadAd:(NSString *)adUnitId error:(CLXError *)error {
    NSLog(@"Banner ad failed to load: %@", error.localizedDescription);
}

- (void)didClickAd:(CLXAd *)ad {
    NSLog(@"Banner ad clicked");
}

// Optional: Called when banner expands (e.g., MRAID)
- (void)didExpandAd:(CLXAd *)ad {
    NSLog(@"Banner ad expanded");
}

// Optional: Called when banner collapses
- (void)didCollapseAd:(CLXAd *)ad {
    NSLog(@"Banner ad collapsed");
}

#pragma mark - CLXAdRevenueDelegate

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"Banner revenue: %@ from %@", ad.revenue, ad.networkName);
}

@end
Banner ads auto-refresh by default. To control refresh manually:
[self.bannerAd stopAutoRefresh];    // Stop auto-refresh
[self.bannerAd load];               // Manually load a new ad
[self.bannerAd startAutoRefresh];   // Re-enable auto-refresh
Optional placement and custom data for tracking:
self.bannerAd.placement = @"home_screen";
self.bannerAd.customData = @"level:5,coins:100";

MREC Ads (300x250)

@interface YourViewController () <CLXBannerDelegate, CLXAdRevenueDelegate>
@property (nonatomic, strong) CLXBannerAdView *mrecAd;
@end

@implementation YourViewController

- (void)createMRECAd {
    self.mrecAd = [[CloudXCore shared] createMRECWithAdUnitId:@"your-mrec-ad-unit-id"
                                               viewController:self];
    self.mrecAd.delegate = self;
    self.mrecAd.revenueDelegate = self;

    if (self.mrecAd) {
        self.mrecAd.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:self.mrecAd];

        [NSLayoutConstraint activateConstraints:@[
            [self.mrecAd.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
            [self.mrecAd.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-20],
            [self.mrecAd.widthAnchor constraintEqualToConstant:300],
            [self.mrecAd.heightAnchor constraintEqualToConstant:250]
        ]];

        [self.mrecAd load];
    }
}

- (void)dealloc {
    [self.mrecAd destroy];
}

#pragma mark - CLXBannerDelegate

- (void)didLoadAd:(CLXAd *)ad {
    NSLog(@"MREC ad loaded from %@", ad.networkName);
}

- (void)didFailToLoadAd:(NSString *)adUnitId error:(CLXError *)error {
    NSLog(@"MREC ad failed to load: %@", error.localizedDescription);
}

- (void)didClickAd:(CLXAd *)ad {
    NSLog(@"MREC ad clicked");
}

// Optional: Called when MREC expands (e.g., MRAID)
- (void)didExpandAd:(CLXAd *)ad {
    NSLog(@"MREC ad expanded");
}

// Optional: Called when MREC collapses
- (void)didCollapseAd:(CLXAd *)ad {
    NSLog(@"MREC ad collapsed");
}

#pragma mark - CLXAdRevenueDelegate

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"MREC revenue: %@ from %@", ad.revenue, ad.networkName);
}

@end
MREC ads also auto-refresh by default. Use the same refresh control methods as Banner ads.

Interstitial Ads

@interface YourViewController () <CLXInterstitialDelegate, CLXAdRevenueDelegate>
@property (nonatomic, strong) CLXInterstitial *interstitialAd;
@end

@implementation YourViewController

- (void)createInterstitialAd {
    self.interstitialAd = [[CloudXCore shared] createInterstitialWithAdUnitId:@"your-interstitial-ad-unit-id"];
    self.interstitialAd.delegate = self;
    self.interstitialAd.revenueDelegate = self;
    [self.interstitialAd load];
}

- (void)showInterstitialAd {
    if (self.interstitialAd.isReady) {
        // Basic show
        [self.interstitialAd showFromViewController:self];

        // Or with optional placement and custom data for tracking
        // [self.interstitialAd showFromViewController:self placement:@"level_complete" customData:@"level:5,score:1000"];
    } else {
        NSLog(@"Interstitial ad not ready");
    }
}

- (void)dealloc {
    [self.interstitialAd destroy];
}

#pragma mark - CLXInterstitialDelegate

- (void)didLoadAd:(CLXAd *)ad {
    NSLog(@"Interstitial ad loaded from %@", ad.networkName);
}

- (void)didFailToLoadAd:(NSString *)adUnitId error:(CLXError *)error {
    NSLog(@"Interstitial ad failed to load: %@", error.localizedDescription);
}

- (void)didDisplayAd:(CLXAd *)ad {
    NSLog(@"Interstitial ad displayed");
}

- (void)didFailToDisplayAd:(CLXAd *)ad error:(CLXError *)error {
    NSLog(@"Interstitial ad failed to display: %@", error.localizedDescription);
}

- (void)didHideAd:(CLXAd *)ad {
    NSLog(@"Interstitial ad hidden");
    [self createInterstitialAd]; // Reload for next use
}

- (void)didClickAd:(CLXAd *)ad {
    NSLog(@"Interstitial ad clicked");
}

#pragma mark - CLXAdRevenueDelegate

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"Interstitial revenue: %@ from %@", ad.revenue, ad.networkName);
}

@end

Rewarded Ads

@interface YourViewController () <CLXRewardedDelegate, CLXAdRevenueDelegate>
@property (nonatomic, strong) CLXRewarded *rewardedAd;
@end

@implementation YourViewController

- (void)createRewardedAd {
    self.rewardedAd = [[CloudXCore shared] createRewardedWithAdUnitId:@"your-rewarded-ad-unit-id"];
    self.rewardedAd.delegate = self;
    self.rewardedAd.revenueDelegate = self;
    [self.rewardedAd load];
}

- (void)showRewardedAd {
    if (self.rewardedAd.isReady) {
        // Basic show
        [self.rewardedAd showFromViewController:self];

        // Or with optional placement and custom data for tracking
        // [self.rewardedAd showFromViewController:self placement:@"bonus_coins" customData:@"level:5,coins:100"];
    } else {
        NSLog(@"Rewarded ad not ready");
    }
}

- (void)dealloc {
    [self.rewardedAd destroy];
}

#pragma mark - CLXRewardedDelegate

- (void)didLoadAd:(CLXAd *)ad {
    NSLog(@"Rewarded ad loaded from %@", ad.networkName);
}

- (void)didFailToLoadAd:(NSString *)adUnitId error:(CLXError *)error {
    NSLog(@"Rewarded ad failed to load: %@", error.localizedDescription);
}

- (void)didDisplayAd:(CLXAd *)ad {
    NSLog(@"Rewarded ad displayed");
}

- (void)didFailToDisplayAd:(CLXAd *)ad error:(CLXError *)error {
    NSLog(@"Rewarded ad failed to display: %@", error.localizedDescription);
}

- (void)didHideAd:(CLXAd *)ad {
    NSLog(@"Rewarded ad hidden");
    [self createRewardedAd]; // Reload for next use
}

- (void)didClickAd:(CLXAd *)ad {
    NSLog(@"Rewarded ad clicked");
}

- (void)didRewardUserForAd:(CLXAd *)ad withReward:(CLXReward *)reward {
    NSLog(@"User rewarded: %ld %@", (long)reward.amount, reward.label);
    // Grant the reward to the user
}

#pragma mark - CLXAdRevenueDelegate

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"Rewarded revenue: %@ from %@", ad.revenue, ad.networkName);
}

@end

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:
  1. A native ad with video content. The ad’s mediaView contains the video player. Other assets (title, body, icon, CTA) are overlaid on top.
  2. Video playback settings. Three properties on the loader disable fullscreen, start the video with sound, and hide media controls.
  3. A full-screen paging container. A UICollectionView with pagingEnabled = YES and a vertical flow layout. Each cell is one Reel.

Reels API Surface

CapabilityCloudX APIDescription
Detect video creativead.nativeAd.isVideoContentReturns YES when the loaded creative is a video
Get video durationad.nativeAd.videoDurationDuration of the video in seconds (0 if unknown)
Ad dismissed by userdidCloseNativeAd: delegate callbackFires when the user reports or hides the ad via AdChoices
Disable fullscreenloader.disableVideoFullScreen = YESPrevents the video from entering fullscreen on tap
Start unmutedloader.startVideoUnmuted = YESStarts playback with sound on
Hide media controlsloader.hideVideoMediaControls = YESHides play/pause and mute/unmute controls
Native ads currently require the Meta Audience Network adapter (CloudXMetaAdapter). Bids from other adapters are not yet supported for the native format.

Requirements

  • CloudX iOS SDK 2.3.0+
  • CloudXMetaAdapter 2.3.0+
  • Meta Audience Network SDK 6.21.0+
  • iOS 13.0+

Create a Loader and Configure Video

@interface YourViewController () <CLXNativeAdDelegate, CLXAdRevenueDelegate>
@property (nonatomic, strong) CLXNativeAdLoader *nativeAdLoader;
@end

@implementation YourViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.nativeAdLoader = [[CloudXCore shared] createNativeAdLoaderWithAdUnitIdentifier:@"your-native-ad-unit-id"];
    self.nativeAdLoader.nativeAdDelegate = self;
    self.nativeAdLoader.revenueDelegate = self;

    self.nativeAdLoader.disableVideoFullScreen = YES;
    self.nativeAdLoader.startVideoUnmuted = YES;
    self.nativeAdLoader.hideVideoMediaControls = YES;
}

- (void)dealloc {
    [self.nativeAdLoader destroy];
}

@end
PropertyDefaultReels ValueDescription
disableVideoFullScreenNOYESPrevents the video from entering fullscreen when tapped
startVideoUnmutedNOYESStarts video playback with sound on
hideVideoMediaControlsNOYESHides play/pause and mute/unmute controls
Set these properties before calling loadAd. They are ignored for static image creatives. For a Reels-style feed, set all three to YES.

Build a Native Ad Layout

Create a CLXNativeAdView using a view binder that maps your custom subviews to asset roles:
- (CLXNativeAdView *)createNativeAdView {
    CLXNativeAdViewBinder *binder = [[CLXNativeAdViewBinder alloc] initWithBuilderBlock:^(CLXNativeAdViewBinderBuilder *builder) {
        builder.titleLabelTag = CLXNativeAdViewTagTitleLabel;
        builder.bodyLabelTag = CLXNativeAdViewTagBodyLabel;
        builder.iconImageViewTag = CLXNativeAdViewTagIconImageView;
        builder.callToActionButtonTag = CLXNativeAdViewTagCallToActionButton;
        builder.mediaContentViewTag = CLXNativeAdViewTagMediaViewContainer;
        builder.optionsContentViewTag = CLXNativeAdViewTagOptionsContentView;
        builder.advertiserLabelTag = CLXNativeAdViewTagAdvertiserLabel;
    }];

    CLXNativeAdView *adView = [[CLXNativeAdView alloc] init];
    [adView bindViewsWithViewBinder:binder];
    return adView;
}
Alternatively, set outlets directly on the CLXNativeAdView:
CLXNativeAdView *adView = [[CLXNativeAdView alloc] init];
adView.titleLabel = myTitleLabel;
adView.bodyLabel = myBodyLabel;
adView.iconImageView = myIconImageView;
adView.callToActionButton = myCTAButton;
adView.mediaContentView = myMediaContainer;
adView.optionsContentView = myOptionsContainer;
adView.advertiserLabel = myAdvertiserLabel;

Load the Ad

Flow A — Load into a pre-built view:
CLXNativeAdView *adView = [self createNativeAdView];
[self.nativeAdLoader loadAdIntoAdView:adView];
Flow B — Load first, render later (deferred rendering):
[self.nativeAdLoader loadAd];

- (void)didLoadNativeAd:(nullable CLXNativeAdView *)nativeAdView forAd:(CLXAd *)ad {
    CLXNativeAdView *adView = /* create your ad view */;
    [self.nativeAdLoader renderNativeAdView:adView withAd:ad];
    [self.view addSubview:adView];
}

Handle Callbacks

#pragma mark - CLXNativeAdDelegate (Required)

- (void)didLoadNativeAd:(nullable CLXNativeAdView *)nativeAdView forAd:(CLXAd *)ad {
    NSLog(@"Native ad loaded from %@", ad.networkName);

    if (ad.nativeAd.isVideoContent) {
        NSLog(@"Video duration: %.1fs", ad.nativeAd.videoDuration);
    }

    if (nativeAdView) {
        [self.view addSubview:nativeAdView];
    }
}

- (void)didFailToLoadNativeAdForAdUnitIdentifier:(NSString *)adUnitId error:(CLXError *)error {
    NSLog(@"Native ad failed to load: %@", error.localizedDescription);
}

- (void)didClickNativeAd:(CLXAd *)ad {
    NSLog(@"Native ad clicked");
}

#pragma mark - CLXNativeAdDelegate (Optional)

- (void)didExpireNativeAd:(CLXAd *)ad {
    NSLog(@"Native ad expired — destroy and reload");
    [self.nativeAdLoader destroyAd:ad];
    [self.nativeAdLoader loadAd];
}

- (void)didCloseNativeAd:(CLXAd *)ad {
    NSLog(@"User dismissed the ad via AdChoices");
    [self.nativeAdLoader destroyAd:ad];
}

#pragma mark - CLXAdRevenueDelegate

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"Native ad revenue: %@ from %@", ad.revenue, ad.networkName);
}

Clean Up

Always destroy ads when you’re done with them:
// Destroy a specific loaded ad
[self.nativeAdLoader destroyAd:ad];

// Destroy the loader and all associated resources
[self.nativeAdLoader destroy];

Native Ad Assets (CLXNativeAd)

The CLXNativeAd object is available via ad.nativeAd in delegate callbacks:
PropertyTypeDescription
titleNSString?Headline text
bodyNSString?Body / description text
callToActionNSString?CTA button text (e.g., “Install Now”)
advertiserNSString?Advertiser name
iconCLXNativeAdImage?App icon image
mainImageCLXNativeAdImage?Main image (static creatives)
mediaViewUIView?Video/media player view (adapter-provided)
optionsViewUIView?AdChoices or options view (adapter-provided)
mediaContentAspectRatioCGFloatAspect ratio of the media content
starRatingNSNumber?App store rating (0–5)
isVideoContentBOOLWhether the creative is a video
videoDurationNSTimeIntervalVideo length in seconds (0 if unknown)
expiredBOOLWhether the ad has expired

Reels Feed Tips

  • Use a UICollectionView with pagingEnabled = YES and a vertical UICollectionViewFlowLayout with minimumLineSpacing = 0. Each cell should be full-screen.
  • Call prepareForReuse on the CLXNativeAdView when recycling cells.
  • Create one CLXNativeAdLoader per slot. Load ads sequentially.
  • Destroy ads when no longer needed via destroyAd:.

Ad Information (CLXAd)

The CLXAd object is passed to delegate callbacks and contains information about the loaded/displayed ad:
PropertyTypeDescription
adFormatCLXAdFormatAd format (banner, mrec, interstitial, rewarded)
adUnitIdNSString?The ad unit ID
adUnitNameNSString?The ad unit name
networkNameNSString?Name of the winning ad network
networkPlacementNSString?Network-specific placement ID
placementNSString?Custom placement set via placement property
revenueNSNumber?Impression-level revenue in USD
- (void)didLoadAd:(CLXAd *)ad {
    NSLog(@"Ad format: %ld", (long)ad.adFormat);
    NSLog(@"Network: %@", ad.networkName);
    NSLog(@"Revenue: %@", ad.revenue);
}

Error Handling

All SDK errors are returned as CLXError objects in delegate callbacks:
PropertyTypeDescription
codeCLXErrorCodeError category
localizedDescriptionNSStringHuman-readable description
underlyingErrorNSError?Optional underlying error

Error Code Categories

RangeCategoryCommon Codes
0GeneralCLXErrorCodeInternalError
100-199NetworkCLXErrorCodeNetworkError, CLXErrorCodeNetworkTimeout, CLXErrorCodeServerError, CLXErrorCodeNoConnection
200-299InitializationCLXErrorCodeNotInitialized, CLXErrorCodeSDKDisabled, CLXErrorCodeNoAdaptersFound, CLXErrorCodeInvalidAppKey
300-399Ad LoadingCLXErrorCodeNoFill, CLXErrorCodeInvalidAdUnit, CLXErrorCodeAdsDisabled
400-499DisplayCLXErrorCodeAdNotReady, CLXErrorCodeAdAlreadyShowing
600-699AdapterCLXErrorCodeAdapterNoFill, CLXErrorCodeAdapterTimeout, CLXErrorCodeAdapterLoadTimeout, CLXErrorCodeAdapterInitializationError

Advanced Features

Debug Logging

[CloudXCore setMinLogLevel:CLXLogLevelDebug];  // Enable debug logging
[CloudXCore setMinLogLevel:CLXLogLevelNone];   // Disable all logging
Log Levels: verbose < debug < info < warn < error < none

Impression-Level Revenue Tracking

Set a revenueDelegate on any ad format to receive impression-level revenue (ILR) callbacks. The CLXAd object contains the revenue value in USD and the winning network name.
self.bannerAd.revenueDelegate = self;

- (void)didPayRevenueForAd:(CLXAd *)ad {
    NSLog(@"Revenue: %@ from %@", ad.revenue, ad.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:
  1. Initialize the SDK and check the logs for your device IFA:
    [CloudX][INFO] Device IFA for test whitelisting: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
    
  2. Copy the IFA and add it to your device whitelist on the CloudX server dashboard
  3. The SDK will automatically configure adapters for test mode and include the test flag in bid requests
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 NSUserDefaults. 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:
  1. 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)
  2. US Users (CCPA): Checks for sale/sharing opt-out signals
  3. Other Regions: No restrictions applied
When consent is denied or user opts out, the SDK removes PII from ad requests:
  • Advertising ID (IDFA) is cleared
  • Geo coordinates (lat/lon) are removed
  • User key-values are not sent
  • Hashed user ID is excluded

Supported Privacy Keys

KeyStandardDescription
IABGPP_HDR_GppStringGPPGlobal Privacy Platform string (modern)
IABGPP_GppSIDGPPSection IDs (e.g., “2” for EU, “7” for US-National, “8” for US-CA)
IABTCF_TCStringTCF v2GDPR consent string (legacy)
IABTCF_gdprAppliesTCF v2Whether GDPR applies (1 = yes, 0 = no)
IABUSPrivacy_StringUS PrivacyCCPA privacy string (legacy, e.g., “1YNN”)
The SDK prioritizes GPP (modern standard) over legacy TCF/US Privacy strings when both are available.

App Tracking Transparency (ATT)

On iOS 14.5+, you must request App Tracking Transparency authorization before the SDK can access the IDFA. Request ATT permission before initializing the CloudX SDK:
#import <AppTrackingTransparency/AppTrackingTransparency.h>

if (@available(iOS 14.5, *)) {
    [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        // Initialize CloudX SDK after ATT response
        [self initializeCloudX];
    }];
} else {
    [self initializeCloudX];
}
Add the NSUserTrackingUsageDescription key to your Info.plist with a description of why you need tracking permission.

Manual Privacy API

If you manage user consent yourself (without a CMP), you can set GDPR and CCPA privacy status directly. Call these before initializing the SDK — some ad network SDKs require privacy settings at initialization time and will not apply values set after init.
// Set privacy BEFORE initializing the SDK
[CloudXCore setHasUserConsent:@YES];
[CloudXCore setDoNotSell:@NO];

[[CloudXCore shared] initializeWithConfiguration:config completion:completion];
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. Pass nil to clear manual values and defer entirely to your CMP.

User Targeting

// Set hashed user ID for targeting
[[CloudXCore shared] setHashedUserID:@"hashed-user-id"];

// Set custom user key-value pairs (cleared by privacy regulations)
[[CloudXCore shared] setUserKeyValue:@"age" value:@"25"];
[[CloudXCore shared] setUserKeyValue:@"gender" value:@"male"];
[[CloudXCore shared] setUserKeyValue:@"location" value:@"US"];

// Set custom app key-value pairs (NOT affected by privacy regulations)
[[CloudXCore shared] setAppKeyValue:@"app_version" value:@"1.0.0"];
[[CloudXCore shared] setAppKeyValue:@"user_level" value:@"premium"];

// Clear all custom key-values
[[CloudXCore shared] clearAllKeyValues];

Support

For support, contact mobile@cloudx.io