cloudx-react-native 2.0.0-beta.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/README.md +420 -1046
  2. package/android/src/main/AndroidManifest.xml +0 -4
  3. package/android/src/main/java/com/cloudxreactnative/CloudXAdEvents.kt +39 -0
  4. package/android/src/main/java/com/cloudxreactnative/CloudXAdInfo.kt +32 -0
  5. package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +694 -0
  6. package/android/src/{newarch/com/cloudxreactnative/CloudXReactNativePackage.kt → main/java/com/cloudxreactnative/CloudXPackage.kt} +14 -13
  7. package/android/src/newarch/com/cloudxreactnative/{CloudXReactNativeModule.kt → CloudXModule.kt} +31 -34
  8. package/android/src/oldarch/com/cloudxreactnative/{CloudXReactNativeModule.kt → CloudXModule.kt} +27 -32
  9. package/cloudx-react-native.podspec +1 -1
  10. package/ios/CloudX.h +47 -0
  11. package/ios/CloudX.mm +1406 -0
  12. package/lib/commonjs/AppTrackingTransparency.js +13 -13
  13. package/lib/commonjs/AppTrackingTransparency.js.map +1 -1
  14. package/lib/commonjs/CloudX.js +16 -12
  15. package/lib/commonjs/CloudX.js.map +1 -1
  16. package/lib/commonjs/CloudXAdPosition.js +23 -0
  17. package/lib/commonjs/CloudXAdPosition.js.map +1 -0
  18. package/lib/commonjs/{BannerAd.js → CloudXBannerAd.js} +42 -37
  19. package/lib/commonjs/CloudXBannerAd.js.map +1 -0
  20. package/lib/commonjs/CloudXErrorCode.js +116 -0
  21. package/lib/commonjs/CloudXErrorCode.js.map +1 -0
  22. package/lib/commonjs/{InterstitialAd.js → CloudXInterstitialAd.js} +10 -10
  23. package/lib/commonjs/CloudXInterstitialAd.js.map +1 -0
  24. package/lib/commonjs/{MRecAd.js → CloudXMRECAd.js} +42 -37
  25. package/lib/commonjs/CloudXMRECAd.js.map +1 -0
  26. package/lib/commonjs/{RewardedAd.js → CloudXRewardedAd.js} +10 -10
  27. package/lib/commonjs/CloudXRewardedAd.js.map +1 -0
  28. package/lib/commonjs/EventEmitter.js +3 -3
  29. package/lib/commonjs/EventEmitter.js.map +1 -1
  30. package/lib/commonjs/hooks.js +25 -26
  31. package/lib/commonjs/hooks.js.map +1 -1
  32. package/lib/commonjs/index.js +27 -41
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/specs/{NativeCloudXModule.js → NativeCloudX.js} +2 -2
  35. package/lib/commonjs/specs/NativeCloudX.js.map +1 -0
  36. package/lib/commonjs/types/AdProps.js +6 -0
  37. package/lib/commonjs/types/AdProps.js.map +1 -0
  38. package/lib/commonjs/types/InterstitialAd.js +6 -0
  39. package/lib/commonjs/types/InterstitialAd.js.map +1 -0
  40. package/lib/commonjs/types/MRECAd.js +6 -0
  41. package/lib/commonjs/types/MRECAd.js.map +1 -0
  42. package/lib/commonjs/types/ViewAd.js +6 -0
  43. package/lib/commonjs/types/ViewAd.js.map +1 -0
  44. package/lib/module/AppTrackingTransparency.js +12 -12
  45. package/lib/module/AppTrackingTransparency.js.map +1 -1
  46. package/lib/module/CloudX.js +16 -12
  47. package/lib/module/CloudX.js.map +1 -1
  48. package/lib/module/CloudXAdPosition.js +17 -0
  49. package/lib/module/CloudXAdPosition.js.map +1 -0
  50. package/lib/module/{BannerAd.js → CloudXBannerAd.js} +41 -36
  51. package/lib/module/CloudXBannerAd.js.map +1 -0
  52. package/lib/module/CloudXErrorCode.js +110 -0
  53. package/lib/module/CloudXErrorCode.js.map +1 -0
  54. package/lib/module/{InterstitialAd.js → CloudXInterstitialAd.js} +9 -9
  55. package/lib/module/CloudXInterstitialAd.js.map +1 -0
  56. package/lib/module/{MRecAd.js → CloudXMRECAd.js} +41 -36
  57. package/lib/module/CloudXMRECAd.js.map +1 -0
  58. package/lib/module/{RewardedAd.js → CloudXRewardedAd.js} +9 -9
  59. package/lib/module/CloudXRewardedAd.js.map +1 -0
  60. package/lib/module/EventEmitter.js +2 -2
  61. package/lib/module/EventEmitter.js.map +1 -1
  62. package/lib/module/hooks.js +14 -15
  63. package/lib/module/hooks.js.map +1 -1
  64. package/lib/module/index.js +9 -10
  65. package/lib/module/index.js.map +1 -1
  66. package/lib/module/specs/{NativeCloudXModule.js → NativeCloudX.js} +2 -2
  67. package/lib/module/specs/NativeCloudX.js.map +1 -0
  68. package/lib/module/types/AdProps.js +2 -0
  69. package/lib/module/types/AdProps.js.map +1 -0
  70. package/lib/module/types/InterstitialAd.js +2 -0
  71. package/lib/module/types/InterstitialAd.js.map +1 -0
  72. package/lib/module/types/MRECAd.js +2 -0
  73. package/lib/module/types/MRECAd.js.map +1 -0
  74. package/lib/module/types/ViewAd.js +2 -0
  75. package/lib/module/types/ViewAd.js.map +1 -0
  76. package/lib/typescript/src/AppTrackingTransparency.d.ts +4 -4
  77. package/lib/typescript/src/AppTrackingTransparency.d.ts.map +1 -1
  78. package/lib/typescript/src/CloudX.d.ts.map +1 -1
  79. package/lib/typescript/src/CloudXAdPosition.d.ts +16 -0
  80. package/lib/typescript/src/CloudXAdPosition.d.ts.map +1 -0
  81. package/lib/typescript/src/CloudXBannerAd.d.ts +4 -0
  82. package/lib/typescript/src/CloudXBannerAd.d.ts.map +1 -0
  83. package/lib/typescript/src/{ErrorCode.d.ts → CloudXErrorCode.d.ts} +2 -2
  84. package/lib/typescript/src/CloudXErrorCode.d.ts.map +1 -0
  85. package/lib/typescript/src/CloudXInterstitialAd.d.ts +4 -0
  86. package/lib/typescript/src/CloudXInterstitialAd.d.ts.map +1 -0
  87. package/lib/typescript/src/CloudXMRECAd.d.ts +4 -0
  88. package/lib/typescript/src/CloudXMRECAd.d.ts.map +1 -0
  89. package/lib/typescript/src/CloudXRewardedAd.d.ts +4 -0
  90. package/lib/typescript/src/CloudXRewardedAd.d.ts.map +1 -0
  91. package/lib/typescript/src/EventEmitter.d.ts +4 -2
  92. package/lib/typescript/src/EventEmitter.d.ts.map +1 -1
  93. package/lib/typescript/src/hooks.d.ts +7 -8
  94. package/lib/typescript/src/hooks.d.ts.map +1 -1
  95. package/lib/typescript/src/index.d.ts +12 -13
  96. package/lib/typescript/src/index.d.ts.map +1 -1
  97. package/lib/typescript/src/specs/{NativeCloudXModule.d.ts → NativeCloudX.d.ts} +47 -64
  98. package/lib/typescript/src/specs/NativeCloudX.d.ts.map +1 -0
  99. package/lib/typescript/src/types/AdEvent.d.ts +3 -3
  100. package/lib/typescript/src/types/AdEvent.d.ts.map +1 -1
  101. package/lib/typescript/src/types/AdInfo.d.ts +7 -7
  102. package/lib/typescript/src/types/AdInfo.d.ts.map +1 -1
  103. package/lib/typescript/src/types/AdProps.d.ts +21 -0
  104. package/lib/typescript/src/types/AdProps.d.ts.map +1 -0
  105. package/lib/typescript/src/types/BannerAd.d.ts +8 -34
  106. package/lib/typescript/src/types/BannerAd.d.ts.map +1 -1
  107. package/lib/typescript/src/types/CloudX.d.ts +7 -4
  108. package/lib/typescript/src/types/CloudX.d.ts.map +1 -1
  109. package/lib/typescript/src/types/Configuration.d.ts +7 -3
  110. package/lib/typescript/src/types/Configuration.d.ts.map +1 -1
  111. package/lib/typescript/src/types/FullscreenAd.d.ts +10 -9
  112. package/lib/typescript/src/types/FullscreenAd.d.ts.map +1 -1
  113. package/lib/typescript/src/types/InterstitialAd.d.ts +8 -0
  114. package/lib/typescript/src/types/InterstitialAd.d.ts.map +1 -0
  115. package/lib/typescript/src/types/MRECAd.d.ts +13 -0
  116. package/lib/typescript/src/types/MRECAd.d.ts.map +1 -0
  117. package/lib/typescript/src/types/RewardedAd.d.ts +5 -4
  118. package/lib/typescript/src/types/RewardedAd.d.ts.map +1 -1
  119. package/lib/typescript/src/types/ViewAd.d.ts +29 -0
  120. package/lib/typescript/src/types/ViewAd.d.ts.map +1 -0
  121. package/lib/typescript/src/types/index.d.ts +11 -7
  122. package/lib/typescript/src/types/index.d.ts.map +1 -1
  123. package/package.json +8 -10
  124. package/src/AppTrackingTransparency.ts +10 -10
  125. package/src/CloudX.ts +21 -16
  126. package/src/CloudXAdPosition.ts +16 -0
  127. package/src/{BannerAd.ts → CloudXBannerAd.ts} +69 -47
  128. package/src/{ErrorCode.ts → CloudXErrorCode.ts} +1 -1
  129. package/src/{InterstitialAd.ts → CloudXInterstitialAd.ts} +17 -17
  130. package/src/{MRecAd.ts → CloudXMRECAd.ts} +69 -47
  131. package/src/{RewardedAd.ts → CloudXRewardedAd.ts} +18 -18
  132. package/src/EventEmitter.ts +4 -4
  133. package/src/hooks.ts +20 -22
  134. package/src/index.ts +27 -24
  135. package/src/specs/{NativeCloudXModule.ts → NativeCloudX.ts} +61 -82
  136. package/src/types/AdEvent.ts +3 -3
  137. package/src/types/AdInfo.ts +7 -7
  138. package/src/types/AdProps.ts +27 -0
  139. package/src/types/BannerAd.ts +8 -54
  140. package/src/types/CloudX.ts +10 -5
  141. package/src/types/Configuration.ts +8 -3
  142. package/src/types/FullscreenAd.ts +10 -9
  143. package/src/types/InterstitialAd.ts +8 -0
  144. package/src/types/MRECAd.ts +13 -0
  145. package/src/types/RewardedAd.ts +5 -4
  146. package/src/types/ViewAd.ts +38 -0
  147. package/src/types/index.ts +11 -7
  148. package/android/src/main/java/com/cloudxreactnative/CloudXAdViewEvent.kt +0 -15
  149. package/android/src/main/java/com/cloudxreactnative/CloudXBannerViewManagerImpl.kt +0 -472
  150. package/android/src/main/java/com/cloudxreactnative/CloudXReactNativeModuleImpl.kt +0 -861
  151. package/android/src/newarch/com/cloudxreactnative/CloudXBannerViewManager.kt +0 -90
  152. package/android/src/oldarch/com/cloudxreactnative/CloudXBannerViewManager.kt +0 -76
  153. package/android/src/oldarch/com/cloudxreactnative/CloudXReactNativePackage.kt +0 -16
  154. package/ios/RNCloudXBannerView.h +0 -51
  155. package/ios/RNCloudXBannerView.mm +0 -633
  156. package/ios/RNCloudXBannerViewManager.h +0 -11
  157. package/ios/RNCloudXBannerViewManager.mm +0 -60
  158. package/ios/RNCloudXModule.h +0 -30
  159. package/ios/RNCloudXModule.mm +0 -1088
  160. package/lib/commonjs/AdView.js +0 -151
  161. package/lib/commonjs/AdView.js.map +0 -1
  162. package/lib/commonjs/BannerAd.js.map +0 -1
  163. package/lib/commonjs/ErrorCode.js +0 -116
  164. package/lib/commonjs/ErrorCode.js.map +0 -1
  165. package/lib/commonjs/InterstitialAd.js.map +0 -1
  166. package/lib/commonjs/MRecAd.js.map +0 -1
  167. package/lib/commonjs/RewardedAd.js.map +0 -1
  168. package/lib/commonjs/specs/CloudXAdViewNativeComponent.js +0 -26
  169. package/lib/commonjs/specs/CloudXAdViewNativeComponent.js.map +0 -1
  170. package/lib/commonjs/specs/NativeCloudXModule.js.map +0 -1
  171. package/lib/module/AdView.js +0 -144
  172. package/lib/module/AdView.js.map +0 -1
  173. package/lib/module/BannerAd.js.map +0 -1
  174. package/lib/module/ErrorCode.js +0 -110
  175. package/lib/module/ErrorCode.js.map +0 -1
  176. package/lib/module/InterstitialAd.js.map +0 -1
  177. package/lib/module/MRecAd.js.map +0 -1
  178. package/lib/module/RewardedAd.js.map +0 -1
  179. package/lib/module/specs/CloudXAdViewNativeComponent.js +0 -20
  180. package/lib/module/specs/CloudXAdViewNativeComponent.js.map +0 -1
  181. package/lib/module/specs/NativeCloudXModule.js.map +0 -1
  182. package/lib/typescript/src/AdView.d.ts +0 -69
  183. package/lib/typescript/src/AdView.d.ts.map +0 -1
  184. package/lib/typescript/src/BannerAd.d.ts +0 -4
  185. package/lib/typescript/src/BannerAd.d.ts.map +0 -1
  186. package/lib/typescript/src/ErrorCode.d.ts.map +0 -1
  187. package/lib/typescript/src/InterstitialAd.d.ts +0 -4
  188. package/lib/typescript/src/InterstitialAd.d.ts.map +0 -1
  189. package/lib/typescript/src/MRecAd.d.ts +0 -4
  190. package/lib/typescript/src/MRecAd.d.ts.map +0 -1
  191. package/lib/typescript/src/RewardedAd.d.ts +0 -4
  192. package/lib/typescript/src/RewardedAd.d.ts.map +0 -1
  193. package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts +0 -61
  194. package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts.map +0 -1
  195. package/lib/typescript/src/specs/NativeCloudXModule.d.ts.map +0 -1
  196. package/src/AdView.tsx +0 -213
  197. package/src/specs/CloudXAdViewNativeComponent.ts +0 -82
package/README.md CHANGED
@@ -1,1258 +1,632 @@
1
1
  # CloudX React Native SDK
2
2
 
3
- A React Native wrapper for the CloudX native SDKs, providing a comprehensive solution for programmatic advertising with full privacy compliance support.
3
+ [![npm](https://img.shields.io/npm/v/cloudx-react-native)](https://www.npmjs.com/package/cloudx-react-native)
4
+
5
+ The CloudX React Native SDK enables monetization of your React Native apps with banner, MREC, interstitial, and rewarded ads on iOS and Android. It supports both the New Architecture (Fabric) and the legacy architecture (Paper).
4
6
 
5
7
  ## Features
6
8
 
7
- - **Full SDK Integration**: Complete wrapper for CloudX Core SDK
8
- - **Cross-Platform Ready**: iOS support (Android coming soon)
9
- - **All Ad Types**: Banner, Interstitial, Rewarded, Native, and MREC ads
10
- - **Privacy**: IAB privacy compliance is handled by the native SDK automatically
11
- - **Event System**: React Native event emitter pattern for ad lifecycle management
12
- - **Error Handling**: Comprehensive error handling with detailed error codes
13
- - **Type Safety**: Full TypeScript support with complete type definitions
14
- - **React Hooks**: Custom hooks for seamless React integration
15
- - **Modern Patterns**: Follows React Native 0.70+ best practices
9
+ - **Cross-Platform**: Full iOS and Android support
10
+ - **Dual Architecture**: Works on both Fabric (New Architecture) and Paper (Legacy)
11
+ - **All Ad Formats**: Banner, MREC, Interstitial, and Rewarded ads
12
+ - **Programmatic Ad APIs**: Overlay APIs for banner and MREC, plus fullscreen formats
13
+ - **React Hooks**: Declarative hooks for fullscreen and banner ad lifecycles
14
+ - **Privacy Compliance**: IAB privacy handled automatically via CMP shared storage
15
+ - **App Tracking Transparency**: Built-in ATT support for iOS 14+
16
+ - **Type Safety**: Full TypeScript definitions with CloudX-prefixed namespace
16
17
 
17
18
  ## Installation
18
19
 
20
+ Requires React Native 0.70+, React 18.0+, iOS 13.0+, and Android API 23+.
21
+
19
22
  ```bash
20
23
  npm install cloudx-react-native
21
- # or
22
- yarn add cloudx-react-native
23
24
  ```
24
25
 
25
26
  ### iOS Setup
26
27
 
27
- 1. Add to your `Podfile`:
28
+ Add ad network adapter pods to your `ios/Podfile`:
28
29
 
29
30
  ```ruby
30
- # CloudX Core SDK
31
- pod 'CloudXCore'
31
+ target 'YourApp' do
32
+ # ... existing config ...
32
33
 
33
- # Optional: CloudX Adapters
34
- pod 'CloudXMetaAdapter'
34
+ # CloudX ad network adapters (add as needed)
35
+ pod 'CloudXMetaAdapter', '~> 2.2.0-beta'
36
+ pod 'CloudXVungleAdapter', '~> 2.2.0-beta'
37
+ pod 'CloudXInMobiAdapter', '~> 2.2.0-beta'
38
+ pod 'CloudXRenderer', '~> 2.2.0-beta'
39
+ end
35
40
  ```
36
41
 
37
- 2. Install pods:
42
+ Then install pods:
38
43
 
39
44
  ```bash
40
45
  cd ios && pod install
41
46
  ```
42
47
 
43
- 3. Add required permissions to `Info.plist`:
44
-
45
- ```xml
46
- <key>NSUserTrackingUsageDescription</key>
47
- <string>This app uses tracking to provide personalized ads and better user experience.</string>
48
-
49
- <key>SKAdNetworkItems</key>
50
- <array>
51
- <!-- Add your SKAdNetwork IDs -->
52
- </array>
53
- ```
54
-
55
- ### Android Setup
56
-
57
- > ⚠️ **Android support coming soon**
48
+ > **Note:** The `CloudXCore` pod is automatically included as a dependency of the `cloudx-react-native` npm package. You only need to add the adapter pods you want.
58
49
 
59
- ---
50
+ #### App Transport Security
60
51
 
61
- ## Quick Start
52
+ If your ads use HTTP URLs, add the following to your `Info.plist`:
62
53
 
63
- ### 1. Initialize the SDK
64
-
65
- ```javascript
66
- import CloudXSDK from 'cloudx-react-native';
67
-
68
- // Initialize CloudX SDK (testMode: false = production, true = test ads)
69
- const result = await CloudXSDK.initialize({
70
- appKey: 'YOUR_APP_KEY',
71
- testMode: false, // false = production, true = test ads
72
- });
73
-
74
- if (result.success) {
75
- console.log('CloudX SDK initialized successfully');
76
- } else {
77
- console.error('Failed to initialize CloudX SDK:', result.message);
78
- }
79
-
80
-
81
- // Check if initialized
82
- const isInitialized = await CloudXSDK.isInitialized();
54
+ ```xml
55
+ <key>NSAppTransportSecurity</key>
56
+ <dict>
57
+ <key>NSAllowsArbitraryLoads</key>
58
+ <true/>
59
+ </dict>
83
60
  ```
84
61
 
85
- #### Test Mode
86
-
87
- The SDK supports an optional `testMode` parameter:
88
-
89
- - **Production (`testMode: false`)**: Real ads with actual billing. Use for production releases.
90
- - **Test Mode (`testMode: true`)**: Test ads without billing. Use for development and QA testing.
91
-
92
- When `testMode` is enabled:
93
- - Bid requests include `test=1` flag per OpenRTB spec
94
- - Adapter SDKs are configured for test mode (e.g., Meta test ads)
95
- - No real monetization occurs
96
-
97
- ### 2. Using React Hooks (Recommended)
98
-
99
- ```jsx
100
- import { useCloudXInterstitial, useCloudXRewarded } from 'cloudx-react-native';
101
-
102
- function GameOverScreen() {
103
- const interstitial = useCloudXInterstitial({
104
- placement: 'game-over-interstitial',
105
- adId: 'interstitial-1',
106
- onLoaded: (ad) => console.log('Interstitial ready:', ad.placementName),
107
- onFailed: (error) => console.error('Failed to load:', error),
108
- onShown: (ad) => console.log('Interstitial shown'),
109
- onClosed: (ad) => console.log('Interstitial closed'),
110
- onRevenuePaid: (ad) => console.log('Revenue:', ad.revenue, ad.currency),
111
- });
112
-
113
- return (
114
- <View>
115
- <Button
116
- title="Show Interstitial"
117
- onPress={() => interstitial.show()}
118
- disabled={!interstitial.isReady || interstitial.isLoading}
119
- />
120
- {interstitial.isLoading && <ActivityIndicator />}
121
- </View>
122
- );
123
- }
124
- ```
62
+ ### Android Setup
125
63
 
126
- ### 3. Banner Ads (Component)
64
+ Add CloudX SDK and adapter dependencies to your `android/app/build.gradle`:
127
65
 
128
- ```jsx
129
- import { CloudXBannerView, BannerSizes } from 'cloudx-react-native';
66
+ ```kotlin
67
+ dependencies {
68
+ // CloudX Android SDK
69
+ implementation "io.cloudx:sdk:2.0.0"
130
70
 
131
- function HomeScreen() {
132
- return (
133
- <View style={styles.container}>
134
- <Text>Your Content Here</Text>
135
-
136
- <CloudXBannerView
137
- placement="home-banner"
138
- adId="banner-1"
139
- bannerSize={BannerSizes.BANNER}
140
- autoRefresh={true}
141
- refreshInterval={30000}
142
- onAdLoaded={(event) => console.log('Banner loaded:', event.ad)}
143
- onAdFailedToLoad={(event) => console.error('Banner failed:', event.error)}
144
- onAdImpression={(event) => trackImpression(event.ad)}
145
- onRevenuePaid={(event) => trackRevenue(event.ad)}
146
- style={styles.banner}
147
- />
148
- </View>
149
- );
71
+ // Adapters for ad networks (add as needed)
72
+ implementation "io.cloudx:adapter-cloudx:2.0.0"
73
+ implementation "io.cloudx:adapter-meta:2.0.0"
74
+ implementation "io.cloudx:adapter-vungle:2.0.0"
75
+ implementation "io.cloudx:adapter-inmobi:2.0.0"
150
76
  }
151
-
152
- const styles = StyleSheet.create({
153
- banner: {
154
- width: 320,
155
- height: 50,
156
- marginVertical: 10,
157
- },
158
- });
159
77
  ```
160
78
 
161
- ---
162
-
163
- ## API Reference
79
+ > **Note:** At least one adapter is required for the SDK to serve ads.
164
80
 
165
- ### SDK Initialization
81
+ ## Initialization
166
82
 
167
- #### `initialize(appKey: string | InitOptions): Promise<InitResult>`
83
+ Initialize the SDK before loading any ads:
168
84
 
169
- Initialize the CloudX SDK. Must be called before using any other SDK methods.
85
+ ```typescript
86
+ import { CloudX, CloudXLogLevel } from 'cloudx-react-native';
170
87
 
171
- ```javascript
172
- // Production initialization
173
- const result = await CloudXSDK.initialize({
174
- appKey: 'YOUR_APP_KEY',
175
- testMode: false, // false = production, true = test ads
176
- });
88
+ // Optional: enable verbose logging (development only)
89
+ CloudX.setMinLogLevel(CloudXLogLevel.VERBOSE);
177
90
 
178
- // result = { success: boolean, message?: string }
91
+ // Initialize with your app key
92
+ const result = await CloudX.initialize('YOUR_APP_KEY');
93
+ if (result.success) {
94
+ console.log('CloudX initialized');
95
+ } else {
96
+ console.error('CloudX init failed:', result.message);
97
+ }
179
98
  ```
180
99
 
181
- **InitOptions:**
182
- - `appKey` (string, required): Your CloudX app key
183
- - `testMode` (boolean, optional): Enable test mode (false = production, true = test ads)
100
+ ### Initialization API
184
101
 
185
- **Note:** To set a hashed user ID for targeting, call `CloudXSDK.setHashedUserID()` separately before or after initialization.
102
+ | Method | Returns | Description |
103
+ |--------|---------|-------------|
104
+ | `CloudX.initialize(appKey)` | `Promise<CloudXInitializationResult>` | Initialize the SDK with your app key |
105
+ | `CloudX.isInitialized()` | `Promise<boolean>` | Check if the SDK has been initialized |
106
+ | `CloudX.getVersion()` | `Promise<string>` | Get the native SDK version string |
107
+ | `CloudX.isTablet()` | `Promise<boolean>` | Check if the device is a tablet |
186
108
 
187
- #### `isInitialized(): Promise<boolean>`
109
+ The `CloudXInitializationResult` contains:
110
+ - `success: boolean` — whether initialization succeeded
111
+ - `message?: string` — additional details on failure
188
112
 
189
- Check if the SDK has been initialized.
113
+ ## Ad Integration
190
114
 
191
- ```javascript
192
- const initialized = await CloudXSDK.isInitialized();
193
- ```
115
+ ### Banner Ads (Programmatic Overlay)
194
116
 
195
- #### `getVersion(): Promise<string>`
117
+ Banners overlay your content at a fixed screen position:
196
118
 
197
- Get the CloudX SDK version.
119
+ ```typescript
120
+ import { CloudXBannerAd, CloudXAdPosition } from 'cloudx-react-native';
198
121
 
199
- ```javascript
200
- const version = await CloudXSDK.getVersion();
201
- console.log('CloudX SDK version:', version);
202
- ```
122
+ const AD_UNIT_ID = 'home_banner';
203
123
 
204
- #### `setLoggingEnabled(enabled: boolean): Promise<void>`
124
+ // Set up event listeners
125
+ CloudXBannerAd.addAdLoadedEventListener((adInfo) => {
126
+ console.log('Banner loaded from', adInfo.networkName);
127
+ });
128
+ CloudXBannerAd.addAdLoadFailedEventListener((error) => {
129
+ console.log('Banner failed:', error.code, error.message);
130
+ });
131
+ CloudXBannerAd.addAdRevenuePaidListener((adInfo) => {
132
+ console.log('Banner revenue:', adInfo.revenue);
133
+ });
205
134
 
206
- Enable or disable verbose SDK logging (useful for debugging).
135
+ // Create and show
136
+ CloudXBannerAd.createAd(AD_UNIT_ID, CloudXAdPosition.BOTTOM_CENTER);
137
+ CloudXBannerAd.showAd(AD_UNIT_ID);
207
138
 
208
- ```javascript
209
- // Enable logging in development
210
- if (__DEV__) {
211
- await CloudXSDK.setLoggingEnabled(true);
212
- }
139
+ // Hide / destroy when done
140
+ CloudXBannerAd.hideAd(AD_UNIT_ID);
141
+ CloudXBannerAd.destroyAd(AD_UNIT_ID);
213
142
  ```
214
143
 
215
- #### `setEnvironment(environment: 'dev' | 'staging' | 'production'): Promise<void>`
144
+ Auto-refresh is enabled by default. To control it manually:
216
145
 
217
- Set the SDK environment. Must be called **before** `initialize()`.
218
-
219
- ```javascript
220
- await CloudXSDK.setEnvironment('staging');
221
- await CloudXSDK.initialize('YOUR_APP_KEY');
146
+ ```typescript
147
+ CloudXBannerAd.stopAutoRefresh(AD_UNIT_ID);
148
+ CloudXBannerAd.startAutoRefresh(AD_UNIT_ID);
222
149
  ```
223
150
 
224
- ---
151
+ #### Full Banner API
225
152
 
226
- ## User Targeting
153
+ | Method | Description |
154
+ |--------|-------------|
155
+ | `createAd(adUnitId, position)` | Create a banner at the given `CloudXAdPosition` |
156
+ | `createAdWithOffsets(adUnitId, position, xOffset, yOffset)` | Create with pixel offsets from the position anchor |
157
+ | `showAd(adUnitId)` | Show the banner |
158
+ | `hideAd(adUnitId)` | Hide the banner (preserves the ad) |
159
+ | `destroyAd(adUnitId)` | Destroy the banner and release resources |
160
+ | `updatePosition(adUnitId, position)` | Move to a new `CloudXAdPosition` |
161
+ | `updateOffsets(adUnitId, xOffset, yOffset)` | Update pixel offsets |
162
+ | `setBackgroundColor(adUnitId, hexColor)` | Set banner background color (e.g., `"#000000"`) |
163
+ | `setPlacement(adUnitId, placement)` | Set placement name for reporting |
164
+ | `setCustomData(adUnitId, customData)` | Set custom data string |
165
+ | `startAutoRefresh(adUnitId)` | Resume auto-refresh |
166
+ | `stopAutoRefresh(adUnitId)` | Pause auto-refresh |
227
167
 
228
- ### Hashed User ID
168
+ #### Banner Events
229
169
 
230
- ```javascript
231
- // Set hashed user ID for targeting
232
- await CloudXSDK.setHashedUserID('hashed-email-or-user-id');
170
+ | Method | Callback Parameter |
171
+ |--------|--------------------|
172
+ | `addAdLoadedEventListener(fn)` | `CloudXAdInfo` |
173
+ | `addAdLoadFailedEventListener(fn)` | `CloudXAdLoadFailedInfo` |
174
+ | `addAdClickedEventListener(fn)` | `CloudXAdInfo` |
175
+ | `addAdExpandedEventListener(fn)` | `CloudXAdInfo` |
176
+ | `addAdCollapsedEventListener(fn)` | `CloudXAdInfo` |
177
+ | `addAdRevenuePaidListener(fn)` | `CloudXAdInfo` |
233
178
 
234
- // Get current user ID
235
- const userId = await CloudXSDK.getUserID();
179
+ Each `add*` listener has a corresponding `remove*` method (e.g., `removeAdLoadedEventListener()`).
236
180
 
237
- // Clear user ID
238
- await CloudXSDK.setUserID(null);
239
- ```
181
+ ### MREC Ads (Programmatic Overlay)
240
182
 
241
- ### User-Level Targeting
183
+ MRECs work identically to banners but with a 300x250 size:
242
184
 
243
- User-level key-values are **cleared automatically** when privacy regulations require removing personal data.
185
+ ```typescript
186
+ import { CloudXMRECAd, CloudXAdPosition } from 'cloudx-react-native';
244
187
 
245
- ```javascript
246
- import { CloudX } from 'cloudx-react-native';
188
+ const AD_UNIT_ID = 'home_mrec';
247
189
 
248
- // User-specific targeting (privacy-sensitive)
249
- CloudX.setUserKeyValue('age', '25');
250
- CloudX.setUserKeyValue('interests', 'gaming');
251
- CloudX.setUserKeyValue('subscription', 'premium');
252
- ```
253
-
254
- ### App-Level Targeting
190
+ CloudXMRECAd.addAdLoadedEventListener((adInfo) => {
191
+ console.log('MREC loaded from', adInfo.networkName);
192
+ });
255
193
 
256
- App-level key-values are **NOT affected** by privacy regulations and persist across privacy changes.
194
+ CloudXMRECAd.createAd(AD_UNIT_ID, CloudXAdPosition.CENTERED);
195
+ CloudXMRECAd.showAd(AD_UNIT_ID);
257
196
 
258
- ```javascript
259
- // App-specific targeting (persistent)
260
- CloudX.setAppKeyValue('app_version', '1.2.0');
261
- CloudX.setAppKeyValue('build_type', 'release');
262
- CloudX.setAppKeyValue('theme', 'dark');
197
+ // Destroy when done
198
+ CloudXMRECAd.destroyAd(AD_UNIT_ID);
263
199
  ```
264
200
 
265
- ### Clear Targeting
201
+ The MREC API surface is identical to Banner — all the same methods and events are available on `CloudXMRECAd`, including `createAdWithOffsets`, `updatePosition`, `updateOffsets`, `setBackgroundColor`, `setPlacement`, `setCustomData`, auto-refresh control, and all event listeners.
266
202
 
267
- ```javascript
268
- // Clear all targeting key-values
269
- CloudX.clearAllKeyValues();
270
- ```
203
+ ### Interstitial Ads
271
204
 
272
- ---
273
-
274
- ## Banner Ads
275
-
276
- ### Using BannerView Component (Recommended)
277
-
278
- ```jsx
279
- import { CloudXBannerView, BannerSizes } from 'cloudx-react-native';
280
-
281
- function MyComponent() {
282
- return (
283
- <CloudXBannerView
284
- // Required
285
- placement="banner-placement"
286
- adId="banner-1"
287
-
288
- // Optional
289
- bannerSize={BannerSizes.BANNER} // BANNER, MREC, LEADERBOARD
290
- autoRefresh={true}
291
- refreshInterval={30000} // milliseconds
292
-
293
- // Event callbacks
294
- onAdLoaded={(event) => console.log('Banner loaded:', event.ad)}
295
- onAdFailedToLoad={(event) => console.error('Failed:', event.error)}
296
- onAdShown={(event) => console.log('Banner shown')}
297
- onAdImpression={(event) => console.log('Impression tracked')}
298
- onAdClicked={(event) => console.log('Banner clicked')}
299
- onAdExpanded={(event) => console.log('Banner expanded')}
300
- onAdCollapsed={(event) => console.log('Banner collapsed')}
301
- onRevenuePaid={(event) => console.log('Revenue:', event.ad.revenue)}
302
-
303
- // Styling
304
- style={{ width: 320, height: 50 }}
305
- />
306
- );
307
- }
308
- ```
205
+ Full-screen ads shown at natural transition points.
309
206
 
310
- ### Using Custom Hook
311
-
312
- ```jsx
313
- import { useCloudXBanner } from 'cloudx-react-native';
314
-
315
- function MyComponent() {
316
- const banner = useCloudXBanner({
317
- placement: 'banner-placement',
318
- adId: 'banner-1',
319
- bannerSize: BannerSizes.BANNER,
320
- autoRefresh: true,
321
- onLoaded: (ad) => console.log('Banner ready'),
322
- onRevenuePaid: (ad) => trackRevenue(ad),
323
- });
324
-
325
- return (
326
- <View>
327
- {banner.render({ style: styles.banner })}
328
- {banner.isLoading && <ActivityIndicator />}
329
- </View>
330
- );
331
- }
332
- ```
207
+ ```typescript
208
+ import { CloudXInterstitialAd } from 'cloudx-react-native';
333
209
 
334
- ### Imperative API
210
+ const AD_UNIT_ID = 'level_complete';
335
211
 
336
- ```javascript
337
- // Create banner
338
- await CloudXSDK.createBanner({
339
- placement: 'banner-placement',
340
- adId: 'banner-1',
341
- bannerSize: BannerSizes.BANNER,
212
+ // Set up event listeners
213
+ CloudXInterstitialAd.addAdLoadedEventListener((adInfo) => {
214
+ console.log('Interstitial loaded');
215
+ });
216
+ CloudXInterstitialAd.addAdLoadFailedEventListener((error) => {
217
+ console.log('Interstitial load failed:', error.code, error.message);
218
+ });
219
+ CloudXInterstitialAd.addAdDisplayedEventListener((adInfo) => {
220
+ console.log('Interstitial displayed');
221
+ });
222
+ CloudXInterstitialAd.addAdFailedToDisplayEventListener((error) => {
223
+ console.log('Interstitial display failed:', error.code, error.message);
224
+ });
225
+ CloudXInterstitialAd.addAdHiddenEventListener((adInfo) => {
226
+ // Reload for next use
227
+ CloudXInterstitialAd.loadAd(AD_UNIT_ID);
228
+ });
229
+ CloudXInterstitialAd.addAdRevenuePaidListener((adInfo) => {
230
+ console.log('Revenue:', adInfo.revenue);
342
231
  });
343
232
 
344
- // Load banner
345
- await CloudXSDK.loadBanner({ adId: 'banner-1' });
346
-
347
- // Show banner (if hidden)
348
- await CloudXSDK.showBanner({ adId: 'banner-1' });
349
-
350
- // Hide banner (keeps it loaded)
351
- await CloudXSDK.hideBanner({ adId: 'banner-1' });
233
+ // Load
234
+ CloudXInterstitialAd.loadAd(AD_UNIT_ID);
352
235
 
353
- // Auto-refresh control
354
- await CloudXSDK.startAutoRefresh({ adId: 'banner-1' });
355
- await CloudXSDK.stopAutoRefresh({ adId: 'banner-1' });
236
+ // Show when ready (with optional placement and custom data)
237
+ const isReady = await CloudXInterstitialAd.isAdReady(AD_UNIT_ID);
238
+ if (isReady) {
239
+ CloudXInterstitialAd.showAd(AD_UNIT_ID);
240
+ // or with placement/custom data:
241
+ // CloudXInterstitialAd.showAd(AD_UNIT_ID, 'level_end', 'custom_data');
242
+ }
356
243
 
357
- // Destroy banner (cleanup)
358
- await CloudXSDK.destroyAd({ adId: 'banner-1' });
244
+ // Destroy when done
245
+ CloudXInterstitialAd.destroyAd(AD_UNIT_ID);
359
246
  ```
360
247
 
361
- ### Banner Sizes
248
+ #### Interstitial API
362
249
 
363
- ```javascript
364
- export const BannerSizes = {
365
- BANNER: 'BANNER', // 320x50
366
- MREC: 'MREC', // 300x250
367
- LEADERBOARD: 'LEADERBOARD', // 728x90
368
- };
369
- ```
250
+ | Method | Description |
251
+ |--------|-------------|
252
+ | `loadAd(adUnitId)` | Start loading an interstitial |
253
+ | `isAdReady(adUnitId)` | Returns `Promise<boolean>` — whether an ad is ready to show |
254
+ | `showAd(adUnitId, placement?, customData?)` | Show the loaded interstitial |
255
+ | `destroyAd(adUnitId)` | Destroy the interstitial and release resources |
370
256
 
371
- ---
257
+ #### Interstitial Events
372
258
 
373
- ## Interstitial Ads
259
+ | Method | Callback Parameter |
260
+ |--------|--------------------|
261
+ | `addAdLoadedEventListener(fn)` | `CloudXAdInfo` |
262
+ | `addAdLoadFailedEventListener(fn)` | `CloudXAdLoadFailedInfo` |
263
+ | `addAdDisplayedEventListener(fn)` | `CloudXAdInfo` |
264
+ | `addAdFailedToDisplayEventListener(fn)` | `CloudXAdDisplayFailedInfo` |
265
+ | `addAdClickedEventListener(fn)` | `CloudXAdInfo` |
266
+ | `addAdHiddenEventListener(fn)` | `CloudXAdInfo` |
267
+ | `addAdRevenuePaidListener(fn)` | `CloudXAdInfo` |
374
268
 
375
- ### Using React Hook (Recommended)
269
+ ### Rewarded Ads
376
270
 
377
- ```jsx
378
- import { useCloudXInterstitial } from 'cloudx-react-native';
271
+ Full-screen ads that grant users a reward upon completion.
379
272
 
380
- function GameOverScreen() {
381
- const interstitial = useCloudXInterstitial({
382
- placement: 'game-over-interstitial',
383
- adId: 'interstitial-1',
384
-
385
- // Event callbacks
386
- onLoaded: (ad) => {
387
- console.log('Interstitial ready:', ad.placementName);
388
- setAdReady(true);
389
- },
390
- onFailedToLoad: (error) => {
391
- console.error('Failed to load:', error);
392
- },
393
- onShown: (ad) => {
394
- console.log('Interstitial shown');
395
- pauseGame();
396
- },
397
- onFailedToShow: (error) => {
398
- console.error('Failed to show:', error);
399
- },
400
- onImpression: (ad) => {
401
- console.log('Impression tracked:', ad.revenue);
402
- },
403
- onClosed: (ad) => {
404
- console.log('Interstitial closed');
405
- resumeGame();
406
- },
407
- onClicked: (ad) => {
408
- console.log('Interstitial clicked');
409
- },
410
- onRevenuePaid: (ad) => {
411
- console.log('Revenue:', ad.revenue, ad.currency);
412
- trackRevenue(ad);
413
- },
414
- });
415
-
416
- useEffect(() => {
417
- // Auto-load on mount
418
- interstitial.load();
419
-
420
- // Cleanup on unmount
421
- return () => {
422
- interstitial.destroy();
423
- };
424
- }, []);
425
-
426
- return (
427
- <View>
428
- <Text>Game Over!</Text>
429
- <Button
430
- title="Continue (Watch Ad)"
431
- onPress={() => interstitial.show()}
432
- disabled={!interstitial.isReady || interstitial.isShowing}
433
- />
434
- {interstitial.isLoading && <ActivityIndicator />}
435
- </View>
436
- );
437
- }
438
- ```
273
+ ```typescript
274
+ import { CloudXRewardedAd } from 'cloudx-react-native';
439
275
 
440
- ### Imperative API
276
+ const AD_UNIT_ID = 'rewarded_coins';
441
277
 
442
- ```javascript
443
- // Create interstitial
444
- await CloudXSDK.createInterstitial({
445
- placement: 'interstitial-placement',
446
- adId: 'interstitial-1',
278
+ // Set up event listeners
279
+ CloudXRewardedAd.addAdLoadedEventListener((adInfo) => {
280
+ console.log('Rewarded loaded');
281
+ });
282
+ CloudXRewardedAd.addAdLoadFailedEventListener((error) => {
283
+ console.log('Rewarded load failed:', error.code, error.message);
284
+ });
285
+ CloudXRewardedAd.addAdDisplayedEventListener((adInfo) => {
286
+ console.log('Rewarded displayed');
287
+ });
288
+ CloudXRewardedAd.addAdFailedToDisplayEventListener((error) => {
289
+ console.log('Rewarded display failed:', error.code, error.message);
290
+ });
291
+ CloudXRewardedAd.addAdReceivedRewardEventListener((rewardInfo) => {
292
+ console.log(`Earned ${rewardInfo.rewardAmount} ${rewardInfo.rewardLabel}`);
293
+ });
294
+ CloudXRewardedAd.addAdHiddenEventListener((adInfo) => {
295
+ // Reload for next use
296
+ CloudXRewardedAd.loadAd(AD_UNIT_ID);
297
+ });
298
+ CloudXRewardedAd.addAdRevenuePaidListener((adInfo) => {
299
+ console.log('Revenue:', adInfo.revenue);
447
300
  });
448
301
 
449
- // Load interstitial
450
- await CloudXSDK.loadInterstitial({ adId: 'interstitial-1' });
451
-
452
- // Check if ready
453
- const isReady = await CloudXSDK.isInterstitialReady({ adId: 'interstitial-1' });
302
+ // Load
303
+ CloudXRewardedAd.loadAd(AD_UNIT_ID);
454
304
 
455
- // Show interstitial
305
+ // Show when ready (with optional placement and custom data)
306
+ const isReady = await CloudXRewardedAd.isAdReady(AD_UNIT_ID);
456
307
  if (isReady) {
457
- await CloudXSDK.showInterstitial({ adId: 'interstitial-1' });
308
+ CloudXRewardedAd.showAd(AD_UNIT_ID);
458
309
  }
459
310
 
460
311
  // Destroy when done
461
- await CloudXSDK.destroyAd({ adId: 'interstitial-1' });
312
+ CloudXRewardedAd.destroyAd(AD_UNIT_ID);
462
313
  ```
463
314
 
464
- ---
315
+ #### Rewarded API
465
316
 
466
- ## Rewarded Ads
317
+ | Method | Description |
318
+ |--------|-------------|
319
+ | `loadAd(adUnitId)` | Start loading a rewarded ad |
320
+ | `isAdReady(adUnitId)` | Returns `Promise<boolean>` — whether an ad is ready to show |
321
+ | `showAd(adUnitId, placement?, customData?)` | Show the loaded rewarded ad |
322
+ | `destroyAd(adUnitId)` | Destroy the rewarded ad and release resources |
467
323
 
468
- ### Using React Hook (Recommended)
324
+ #### Rewarded Events
469
325
 
470
- ```jsx
471
- import { useCloudXRewarded } from 'cloudx-react-native';
472
-
473
- function RewardButton() {
474
- const rewarded = useCloudXRewarded({
475
- placement: 'extra-lives-rewarded',
476
- adId: 'rewarded-1',
477
-
478
- onLoaded: (ad) => console.log('Rewarded ad ready'),
479
- onFailedToLoad: (error) => console.error('Failed:', error),
480
- onShown: (ad) => console.log('Showing rewarded ad'),
481
- onRewardEarned: (ad) => {
482
- console.log('🎉 User earned reward!');
483
- grantExtraLife();
484
- },
485
- onVideoStarted: (ad) => console.log('Video started'),
486
- onVideoCompleted: (ad) => console.log('Video completed'),
487
- onClosed: (ad) => console.log('Rewarded ad closed'),
488
- onRevenuePaid: (ad) => trackRevenue(ad),
489
- });
490
-
491
- useEffect(() => {
492
- rewarded.load();
493
- return () => rewarded.destroy();
494
- }, []);
495
-
496
- return (
497
- <Button
498
- title="Watch Ad for Extra Life"
499
- onPress={() => rewarded.show()}
500
- disabled={!rewarded.isReady}
501
- />
502
- );
503
- }
504
- ```
326
+ | Method | Callback Parameter |
327
+ |--------|--------------------|
328
+ | `addAdLoadedEventListener(fn)` | `CloudXAdInfo` |
329
+ | `addAdLoadFailedEventListener(fn)` | `CloudXAdLoadFailedInfo` |
330
+ | `addAdDisplayedEventListener(fn)` | `CloudXAdInfo` |
331
+ | `addAdFailedToDisplayEventListener(fn)` | `CloudXAdDisplayFailedInfo` |
332
+ | `addAdClickedEventListener(fn)` | `CloudXAdInfo` |
333
+ | `addAdHiddenEventListener(fn)` | `CloudXAdInfo` |
334
+ | `addAdReceivedRewardEventListener(fn)` | `CloudXAdRewardInfo` |
335
+ | `addAdRevenuePaidListener(fn)` | `CloudXAdInfo` |
505
336
 
506
- ### Imperative API
337
+ ## React Hooks
507
338
 
508
- ```javascript
509
- // Create rewarded ad
510
- await CloudXSDK.createRewarded({
511
- placement: 'rewarded-placement',
512
- adId: 'rewarded-1',
513
- });
339
+ The SDK provides React hooks for declarative ad management that handle event subscriptions and cleanup automatically.
514
340
 
515
- // Load rewarded ad
516
- await CloudXSDK.loadRewarded({ adId: 'rewarded-1' });
341
+ ### useCloudXInterstitial
517
342
 
518
- // Check if ready
519
- const isReady = await CloudXSDK.isRewardedReady({ adId: 'rewarded-1' });
343
+ ```typescript
344
+ import { useCloudXInterstitial } from 'cloudx-react-native';
520
345
 
521
- // Show rewarded ad
522
- if (isReady) {
523
- await CloudXSDK.showRewarded({ adId: 'rewarded-1' });
524
- }
346
+ function GameScreen() {
347
+ const { isLoaded, isLoading, error, load, show, destroy } =
348
+ useCloudXInterstitial('level_complete');
525
349
 
526
- // Listen for reward event
527
- const listener = CloudXSDK.addEventListener(
528
- CloudXEventTypes.REWARD_EARNED,
529
- (event) => {
530
- if (event.ad.adId === 'rewarded-1') {
531
- console.log('User earned reward!');
532
- grantReward();
533
- }
534
- }
535
- );
536
-
537
- // Clean up
538
- listener.remove();
539
- await CloudXSDK.destroyAd({ adId: 'rewarded-1' });
540
- ```
350
+ useEffect(() => {
351
+ load();
352
+ }, [load]);
541
353
 
542
- ---
543
-
544
- ## Native Ads
545
-
546
- ### Using React Hook (Recommended)
547
-
548
- ```jsx
549
- import { useCloudXNative } from 'cloudx-react-native';
550
-
551
- function FeedItemAd({ index }) {
552
- const nativeAd = useCloudXNative({
553
- placement: 'feed-native',
554
- adId: `native-${index}`,
555
-
556
- onLoaded: (ad) => {
557
- console.log('Native ad loaded:', ad.assets);
558
- },
559
- onFailedToLoad: (error) => console.error('Failed:', error),
560
- onImpression: (ad) => trackImpression(ad),
561
- onClicked: (ad) => console.log('Native ad clicked'),
562
- onRevenuePaid: (ad) => trackRevenue(ad),
563
- });
564
-
565
- useEffect(() => {
566
- nativeAd.load();
567
- return () => nativeAd.destroy();
568
- }, []);
569
-
570
- if (!nativeAd.isLoaded || !nativeAd.assets) {
571
- return null;
572
- }
573
-
574
- return (
575
- <View style={styles.nativeAd}>
576
- {nativeAd.assets.iconUrl && (
577
- <Image source={{ uri: nativeAd.assets.iconUrl }} style={styles.icon} />
578
- )}
579
- <View style={styles.content}>
580
- <Text style={styles.title}>{nativeAd.assets.title}</Text>
581
- <Text style={styles.body}>{nativeAd.assets.body}</Text>
582
- {nativeAd.assets.callToAction && (
583
- <TouchableOpacity
584
- style={styles.cta}
585
- onPress={() => nativeAd.click()}
586
- >
587
- <Text style={styles.ctaText}>{nativeAd.assets.callToAction}</Text>
588
- </TouchableOpacity>
589
- )}
590
- </View>
591
- <Text style={styles.adBadge}>Ad</Text>
592
- </View>
593
- );
354
+ return (
355
+ <Button
356
+ title={isLoading ? 'Loading...' : 'Show Ad'}
357
+ onPress={() => show()}
358
+ disabled={!isLoaded}
359
+ />
360
+ );
594
361
  }
595
362
  ```
596
363
 
597
- ### Imperative API
364
+ Returns `CloudXInterstitialHookResult`:
365
+ - `isLoaded: boolean` — ad is ready to show
366
+ - `isLoading: boolean` — load in progress
367
+ - `error: string | null` — last error message
368
+ - `load()` — start loading
369
+ - `show(placement?, customData?)` — show the loaded ad
370
+ - `destroy()` — destroy and reset state
598
371
 
599
- ```javascript
600
- // Create native ad
601
- await CloudXSDK.createNative({
602
- placement: 'native-placement',
603
- adId: 'native-1',
604
- });
372
+ ### useCloudXRewarded
605
373
 
606
- // Load native ad
607
- await CloudXSDK.loadNative({ adId: 'native-1' });
608
-
609
- // Get native ad assets
610
- const assets = await CloudXSDK.getNativeAdAssets({ adId: 'native-1' });
611
- // assets = {
612
- // title: string,
613
- // body: string,
614
- // callToAction: string,
615
- // iconUrl: string,
616
- // imageUrl: string,
617
- // starRating: number,
618
- // advertiser: string,
619
- // }
620
-
621
- // Register view for impression tracking
622
- await CloudXSDK.registerNativeAdView({ adId: 'native-1' });
623
-
624
- // Track click
625
- await CloudXSDK.trackNativeAdClick({ adId: 'native-1' });
626
-
627
- // Destroy
628
- await CloudXSDK.destroyAd({ adId: 'native-1' });
629
- ```
374
+ ```typescript
375
+ import { useCloudXRewarded } from 'cloudx-react-native';
630
376
 
631
- ---
632
-
633
- ## MREC Ads
634
-
635
- MREC (Medium Rectangle) ads are 300x250 banner ads commonly used in content feeds.
636
-
637
- ### Using Component
638
-
639
- ```jsx
640
- import { CloudXBannerView, BannerSizes } from 'cloudx-react-native';
641
-
642
- function ContentFeed() {
643
- return (
644
- <ScrollView>
645
- <Article />
646
- <Article />
647
-
648
- {/* MREC ad between content */}
649
- <CloudXBannerView
650
- placement="feed-mrec"
651
- adId="mrec-1"
652
- bannerSize={BannerSizes.MREC}
653
- autoRefresh={true}
654
- onAdLoaded={(event) => console.log('MREC loaded')}
655
- onRevenuePaid={(event) => trackRevenue(event.ad)}
656
- style={{ width: 300, height: 250, alignSelf: 'center' }}
657
- />
658
-
659
- <Article />
660
- <Article />
661
- </ScrollView>
662
- );
377
+ function RewardScreen() {
378
+ const { isLoaded, isLoading, error, rewardEarned, load, show } =
379
+ useCloudXRewarded('rewarded_coins');
380
+
381
+ useEffect(() => {
382
+ load();
383
+ }, [load]);
384
+
385
+ useEffect(() => {
386
+ if (rewardEarned) {
387
+ grantCoinsToUser();
388
+ }
389
+ }, [rewardEarned]);
390
+
391
+ return (
392
+ <Button
393
+ title="Watch Ad for Coins"
394
+ onPress={() => show()}
395
+ disabled={!isLoaded}
396
+ />
397
+ );
663
398
  }
664
399
  ```
665
400
 
666
- ---
667
-
668
- ## Event Handling
669
-
670
- ### Event Types
671
-
672
- ```javascript
673
- import { CloudXEventTypes } from 'cloudx-react-native';
674
-
675
- // Banner Events
676
- CloudXEventTypes.BANNER_LOADED
677
- CloudXEventTypes.BANNER_FAILED_TO_LOAD
678
- CloudXEventTypes.BANNER_SHOWN
679
- CloudXEventTypes.BANNER_FAILED_TO_SHOW
680
- CloudXEventTypes.BANNER_HIDDEN
681
- CloudXEventTypes.BANNER_CLICKED
682
- CloudXEventTypes.BANNER_IMPRESSION
683
- CloudXEventTypes.BANNER_EXPANDED
684
- CloudXEventTypes.BANNER_COLLAPSED
685
- CloudXEventTypes.BANNER_REVENUE_PAID
686
-
687
- // Interstitial Events
688
- CloudXEventTypes.INTERSTITIAL_LOADED
689
- CloudXEventTypes.INTERSTITIAL_FAILED_TO_LOAD
690
- CloudXEventTypes.INTERSTITIAL_SHOWN
691
- CloudXEventTypes.INTERSTITIAL_FAILED_TO_SHOW
692
- CloudXEventTypes.INTERSTITIAL_CLOSED
693
- CloudXEventTypes.INTERSTITIAL_CLICKED
694
- CloudXEventTypes.INTERSTITIAL_IMPRESSION
695
- CloudXEventTypes.INTERSTITIAL_CLOSED_BY_USER
696
- CloudXEventTypes.INTERSTITIAL_REVENUE_PAID
697
-
698
- // Rewarded Events
699
- CloudXEventTypes.REWARDED_LOADED
700
- CloudXEventTypes.REWARDED_FAILED_TO_LOAD
701
- CloudXEventTypes.REWARDED_SHOWN
702
- CloudXEventTypes.REWARDED_FAILED_TO_SHOW
703
- CloudXEventTypes.REWARDED_CLOSED
704
- CloudXEventTypes.REWARDED_CLICKED
705
- CloudXEventTypes.REWARDED_IMPRESSION
706
- CloudXEventTypes.REWARDED_CLOSED_BY_USER
707
- CloudXEventTypes.REWARDED_REVENUE_PAID
708
- CloudXEventTypes.REWARD_EARNED
709
- CloudXEventTypes.REWARDED_VIDEO_STARTED
710
- CloudXEventTypes.REWARDED_VIDEO_COMPLETED
711
-
712
- // Native Events
713
- CloudXEventTypes.NATIVE_LOADED
714
- CloudXEventTypes.NATIVE_FAILED_TO_LOAD
715
- CloudXEventTypes.NATIVE_SHOWN
716
- CloudXEventTypes.NATIVE_CLICKED
717
- CloudXEventTypes.NATIVE_IMPRESSION
718
- CloudXEventTypes.NATIVE_REVENUE_PAID
719
- ```
720
-
721
- ### Using Event Emitter
401
+ Returns `CloudXRewardedHookResult`:
402
+ - `isLoaded: boolean` — ad is ready to show
403
+ - `isLoading: boolean` — load in progress
404
+ - `error: string | null` — last error message
405
+ - `rewardEarned: boolean` — user completed the ad and earned a reward
406
+ - `load()` — start loading
407
+ - `show(placement?, customData?)` — show the loaded ad
408
+ - `destroy()` — destroy and reset state
722
409
 
723
- ```javascript
724
- import CloudXSDK, { CloudXEventTypes } from 'cloudx-react-native';
410
+ ### useCloudXBanner
725
411
 
726
- // Add listener
727
- const listener = CloudXSDK.addEventListener(
728
- CloudXEventTypes.INTERSTITIAL_LOADED,
729
- (event) => {
730
- console.log('Ad loaded:', event.ad.adId);
731
- console.log('Placement:', event.ad.placementName);
732
- }
733
- );
412
+ ```typescript
413
+ import { useCloudXBanner, CloudXBannerAd, CloudXAdPosition } from 'cloudx-react-native';
734
414
 
735
- // Remove specific listener
736
- listener.remove();
415
+ function HomeScreen() {
416
+ const { isLoaded, error } = useCloudXBanner('home_banner');
737
417
 
738
- // Remove all listeners for an event
739
- CloudXSDK.removeAllListeners(CloudXEventTypes.INTERSTITIAL_LOADED);
418
+ useEffect(() => {
419
+ CloudXBannerAd.createAd('home_banner', CloudXAdPosition.BOTTOM_CENTER);
420
+ CloudXBannerAd.showAd('home_banner');
421
+ return () => CloudXBannerAd.destroyAd('home_banner');
422
+ }, []);
740
423
 
741
- // Remove all listeners
742
- CloudXSDK.removeAllListeners();
424
+ return <Text>{isLoaded ? 'Banner showing' : 'Loading banner...'}</Text>;
425
+ }
743
426
  ```
744
427
 
745
- ### Event Payload
428
+ Returns `CloudXBannerHookResult`:
429
+ - `isLoaded: boolean` — banner has loaded an ad
430
+ - `error: string | null` — last error message
746
431
 
747
- All events receive a payload with the following structure:
432
+ ## Types Reference
748
433
 
749
- ```typescript
750
- interface CloudXAdEvent {
751
- ad?: CloudXAd;
752
- error?: string;
753
- timestamp: number;
754
- }
434
+ ### CloudXAdInfo
755
435
 
756
- interface CloudXAd {
757
- adId: string;
758
- placementName: string;
759
- adType: 'banner' | 'interstitial' | 'rewarded' | 'native' | 'mrec';
760
- revenue?: number;
761
- currency?: string;
762
- network?: string;
763
- lineItemId?: string;
764
- }
436
+ Received by most ad event callbacks:
437
+
438
+ ```typescript
439
+ type CloudXAdInfo = {
440
+ adUnitId: string;
441
+ adFormat: string; // "BANNER", "MREC", "INTERSTITIAL", "REWARDED"
442
+ networkName: string;
443
+ networkPlacement?: string | null;
444
+ placement?: string | null;
445
+ revenue: number; // USD
446
+ };
765
447
  ```
766
448
 
767
- ### Using with React
449
+ ### CloudXAdLoadFailedInfo
768
450
 
769
- ```jsx
770
- import { useEffect } from 'react';
771
- import CloudXSDK, { CloudXEventTypes } from 'cloudx-react-native';
451
+ Received by `addAdLoadFailedEventListener`:
772
452
 
773
- function MyComponent() {
774
- useEffect(() => {
775
- const listener = CloudXSDK.addEventListener(
776
- CloudXEventTypes.INTERSTITIAL_LOADED,
777
- handleInterstitialLoaded
778
- );
453
+ ```typescript
454
+ type CloudXAdLoadFailedInfo = {
455
+ adUnitId: string;
456
+ code: CloudXErrorCode;
457
+ message?: string | null;
458
+ };
459
+ ```
779
460
 
780
- return () => {
781
- listener.remove(); // Cleanup on unmount
782
- };
783
- }, []);
461
+ ### CloudXAdDisplayFailedInfo
784
462
 
785
- const handleInterstitialLoaded = (event) => {
786
- console.log('Interstitial ready:', event.ad);
787
- };
463
+ Received by `addAdFailedToDisplayEventListener`:
788
464
 
789
- return <View>...</View>;
790
- }
465
+ ```typescript
466
+ type CloudXAdDisplayFailedInfo = CloudXAdInfo & {
467
+ code: CloudXErrorCode;
468
+ message?: string | null;
469
+ };
791
470
  ```
792
471
 
793
- ---
472
+ ### CloudXAdRewardInfo
794
473
 
795
- ## Error Handling
474
+ Received by `addAdReceivedRewardEventListener`:
796
475
 
797
- ### Error Codes
798
-
799
- ```javascript
800
- // Common error codes
801
- const ErrorCodes = {
802
- NO_FILL: 'NO_FILL', // No ad available
803
- TIMEOUT: 'TIMEOUT', // Request timed out
804
- NETWORK_ERROR: 'NETWORK_ERROR', // Network issue
805
- INVALID_PLACEMENT: 'INVALID_PLACEMENT', // Placement not configured
806
- SDK_NOT_INITIALIZED: 'SDK_NOT_INITIALIZED', // Must initialize first
807
- AD_NOT_READY: 'AD_NOT_READY', // Ad not loaded yet
808
- AD_ALREADY_SHOWN: 'AD_ALREADY_SHOWN', // Ad already displayed
809
- INVALID_AD_ID: 'INVALID_AD_ID', // Ad ID not found
476
+ ```typescript
477
+ type CloudXAdRewardInfo = CloudXAdInfo & {
478
+ rewardLabel?: string | null;
479
+ rewardAmount: number;
810
480
  };
811
481
  ```
812
482
 
813
- ### Handling Errors
814
-
815
- ```javascript
816
- // Try-catch for async methods
817
- try {
818
- await CloudXSDK.loadInterstitial({ adId: 'interstitial-1' });
819
- } catch (error) {
820
- if (error.code === 'NO_FILL') {
821
- console.log('No ad available, continue without ad');
822
- } else if (error.code === 'NETWORK_ERROR') {
823
- console.log('Network error, retry later');
824
- setTimeout(() => retry(), 5000);
825
- } else {
826
- console.error('Unexpected error:', error);
827
- }
828
- }
483
+ ### CloudXAdPosition
829
484
 
830
- // Error events
831
- CloudXSDK.addEventListener(
832
- CloudXEventTypes.INTERSTITIAL_FAILED_TO_LOAD,
833
- (event) => {
834
- console.error('Failed to load ad:', event.error);
835
-
836
- // Handle specific errors
837
- switch (event.error) {
838
- case 'NO_FILL':
839
- // Show alternative content
840
- break;
841
- case 'TIMEOUT':
842
- // Retry with longer timeout
843
- break;
844
- default:
845
- // Generic error handling
846
- }
847
- }
848
- );
849
- ```
485
+ Position constants for programmatic banner and MREC placement:
850
486
 
851
- ### Best Practices
852
-
853
- ```javascript
854
- async function showInterstitialSafely(adId: string) {
855
- try {
856
- // Check if SDK is initialized
857
- const initialized = await CloudXSDK.isInitialized();
858
- if (!initialized) {
859
- throw new Error('SDK not initialized');
860
- }
861
-
862
- // Check if ad is ready
863
- const isReady = await CloudXSDK.isInterstitialReady({ adId });
864
- if (!isReady) {
865
- console.log('Ad not ready, loading...');
866
- await CloudXSDK.loadInterstitial({ adId });
867
- // Wait for load event before showing
868
- return;
869
- }
870
-
871
- // Show the ad
872
- await CloudXSDK.showInterstitial({ adId });
873
- } catch (error) {
874
- console.error('Error showing interstitial:', error);
875
- // Continue app flow without ad
876
- }
487
+ ```typescript
488
+ enum CloudXAdPosition {
489
+ TOP_LEFT, TOP_CENTER, TOP_RIGHT,
490
+ CENTER_LEFT, CENTERED, CENTER_RIGHT,
491
+ BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
877
492
  }
878
493
  ```
879
494
 
880
- ---
495
+ ## Advanced Features
881
496
 
882
- ## Advanced Usage
497
+ ### Error Handling
883
498
 
884
- ### Multiple Ad Instances
499
+ All error callbacks receive an object with `code` and `message` properties:
885
500
 
886
- ```javascript
887
- // Create multiple instances of the same placement
888
- await CloudXSDK.createInterstitial({
889
- placement: 'level-complete',
890
- adId: 'level-1-interstitial',
891
- });
501
+ | Range | Category | Common Codes |
502
+ |-------|----------|--------------|
503
+ | 0 | General | `internalError` |
504
+ | 100-199 | Network | `networkError`, `networkTimeout`, `networkNoConnection` |
505
+ | 200-299 | Initialization | `notInitialized`, `sdkDisabled`, `invalidAppKey` |
506
+ | 300-399 | Ad Loading | `noFill`, `invalidAdUnit`, `adsDisabled` |
507
+ | 400-499 | Display | `adNotReady`, `adAlreadyShowing` |
508
+ | 600-699 | Adapter | `adapterNoFill`, `adapterTimeout` |
892
509
 
893
- await CloudXSDK.createInterstitial({
894
- placement: 'level-complete',
895
- adId: 'level-2-interstitial',
896
- });
510
+ See `CloudXErrorCode` export for the full list of error codes.
897
511
 
898
- // Each instance is managed independently
899
- await CloudXSDK.loadInterstitial({ adId: 'level-1-interstitial' });
900
- await CloudXSDK.loadInterstitial({ adId: 'level-2-interstitial' });
901
- ```
512
+ ### Revenue Tracking
902
513
 
903
- ### Preloading Ads
904
-
905
- ```javascript
906
- // Preload ads early for better UX
907
- async function preloadAds() {
908
- // Preload interstitial
909
- await CloudXSDK.createInterstitial({
910
- placement: 'game-over',
911
- adId: 'preloaded-interstitial',
912
- });
913
- await CloudXSDK.loadInterstitial({ adId: 'preloaded-interstitial' });
914
-
915
- // Preload rewarded
916
- await CloudXSDK.createRewarded({
917
- placement: 'extra-life',
918
- adId: 'preloaded-rewarded',
919
- });
920
- await CloudXSDK.loadRewarded({ adId: 'preloaded-rewarded' });
921
- }
514
+ All ad formats provide revenue callbacks. The `CloudXAdInfo` object includes `revenue` (USD) and `networkName`:
922
515
 
923
- // Call during app initialization or loading screens
924
- useEffect(() => {
925
- preloadAds();
926
- }, []);
516
+ ```typescript
517
+ CloudXInterstitialAd.addAdRevenuePaidListener((adInfo) => {
518
+ trackRevenue(adInfo.revenue, adInfo.networkName, adInfo.adUnitId);
519
+ });
927
520
  ```
928
521
 
929
- ### Ad Frequency Capping
930
-
931
- ```javascript
932
- // Implement your own frequency capping
933
- class AdFrequencyCapper {
934
- constructor(maxAdsPerHour = 5) {
935
- this.maxAdsPerHour = maxAdsPerHour;
936
- this.adTimestamps = [];
937
- }
938
-
939
- canShowAd() {
940
- const oneHourAgo = Date.now() - 60 * 60 * 1000;
941
- this.adTimestamps = this.adTimestamps.filter(ts => ts > oneHourAgo);
942
- return this.adTimestamps.length < this.maxAdsPerHour;
943
- }
944
-
945
- recordAdShown() {
946
- this.adTimestamps.push(Date.now());
947
- }
948
- }
522
+ ### User Targeting
949
523
 
950
- const frequencyCapper = new AdFrequencyCapper(5);
524
+ ```typescript
525
+ import { CloudX } from 'cloudx-react-native';
951
526
 
952
- async function showInterstitialWithCapping(adId: string) {
953
- if (!frequencyCapper.canShowAd()) {
954
- console.log('Ad frequency cap reached');
955
- return;
956
- }
527
+ // Set hashed user ID
528
+ CloudX.setHashedUserID('hashed-user-id');
957
529
 
958
- try {
959
- await CloudXSDK.showInterstitial({ adId });
960
- frequencyCapper.recordAdShown();
961
- } catch (error) {
962
- console.error('Failed to show ad:', error);
963
- }
964
- }
965
- ```
530
+ // Set custom key-value pairs
531
+ CloudX.setUserKeyValue('age_group', '25-34');
532
+ CloudX.setAppKeyValue('app_version', '1.0.0');
966
533
 
967
- ### Revenue Tracking
968
-
969
- ```javascript
970
- // Track revenue from all ad types
971
- CloudXSDK.addEventListener(
972
- CloudXEventTypes.INTERSTITIAL_REVENUE_PAID,
973
- (event) => trackRevenue(event.ad)
974
- );
975
-
976
- CloudXSDK.addEventListener(
977
- CloudXEventTypes.REWARDED_REVENUE_PAID,
978
- (event) => trackRevenue(event.ad)
979
- );
980
-
981
- CloudXSDK.addEventListener(
982
- CloudXEventTypes.BANNER_REVENUE_PAID,
983
- (event) => trackRevenue(event.ad)
984
- );
985
-
986
- function trackRevenue(ad: CloudXAd) {
987
- if (ad.revenue && ad.currency) {
988
- // Send to analytics
989
- Analytics.logRevenue({
990
- amount: ad.revenue,
991
- currency: ad.currency,
992
- adNetwork: ad.network,
993
- adType: ad.adType,
994
- placement: ad.placementName,
995
- });
996
-
997
- console.log(
998
- `💰 Revenue: ${ad.currency} ${ad.revenue} from ${ad.network}`
999
- );
1000
- }
1001
- }
534
+ // Clear all custom key-values
535
+ CloudX.clearAllKeyValues();
1002
536
  ```
1003
537
 
1004
- ---
1005
-
1006
- ## React Hooks API
1007
-
1008
- ### useCloudXInterstitial
538
+ ### App Tracking Transparency (iOS)
1009
539
 
1010
540
  ```typescript
1011
- interface UseInterstitialOptions {
1012
- placement: string;
1013
- adId: string;
1014
- onLoaded?: (ad: CloudXAd) => void;
1015
- onFailedToLoad?: (error: string) => void;
1016
- onShown?: (ad: CloudXAd) => void;
1017
- onFailedToShow?: (error: string) => void;
1018
- onClosed?: (ad: CloudXAd) => void;
1019
- onClicked?: (ad: CloudXAd) => void;
1020
- onImpression?: (ad: CloudXAd) => void;
1021
- onRevenuePaid?: (ad: CloudXAd) => void;
1022
- autoLoad?: boolean; // Default: false
1023
- }
541
+ import { requestTrackingAuthorization, getTrackingAuthorizationStatus, CloudXATTStatus } from 'cloudx-react-native';
1024
542
 
1025
- interface UseInterstitialResult {
1026
- isReady: boolean;
1027
- isLoading: boolean;
1028
- isShowing: boolean;
1029
- error: string | null;
1030
- load: () => Promise<void>;
1031
- show: () => Promise<void>;
1032
- destroy: () => Promise<void>;
543
+ const status = await requestTrackingAuthorization();
544
+ if (status === CloudXATTStatus.AUTHORIZED) {
545
+ console.log('Tracking authorized');
1033
546
  }
1034
-
1035
- const interstitial = useCloudXInterstitial(options);
1036
547
  ```
1037
548
 
1038
- ### useCloudXRewarded
549
+ > **Note:** Call `requestTrackingAuthorization()` before `CloudX.initialize()` for best ad targeting results.
1039
550
 
1040
- ```typescript
1041
- interface UseRewardedOptions extends UseInterstitialOptions {
1042
- onRewardEarned?: (ad: CloudXAd) => void;
1043
- onVideoStarted?: (ad: CloudXAd) => void;
1044
- onVideoCompleted?: (ad: CloudXAd) => void;
1045
- }
551
+ ATT status values: `AUTHORIZED`, `DENIED`, `RESTRICTED`, `NOT_DETERMINED`, `NOT_REQUIRED`.
1046
552
 
1047
- interface UseRewardedResult extends UseInterstitialResult {
1048
- // Same as interstitial
1049
- }
553
+ On Android or iOS < 14, `requestTrackingAuthorization()` returns `NOT_REQUIRED`.
1050
554
 
1051
- const rewarded = useCloudXRewarded(options);
1052
- ```
555
+ ### Test Mode
1053
556
 
1054
- ### useCloudXBanner
557
+ Test mode is **server-controlled** via device whitelisting:
1055
558
 
1056
- ```typescript
1057
- interface UseBannerOptions {
1058
- placement: string;
1059
- adId: string;
1060
- bannerSize?: BannerSize;
1061
- autoRefresh?: boolean;
1062
- refreshInterval?: number;
1063
- onLoaded?: (ad: CloudXAd) => void;
1064
- onFailedToLoad?: (error: string) => void;
1065
- onShown?: (ad: CloudXAd) => void;
1066
- onImpression?: (ad: CloudXAd) => void;
1067
- onClicked?: (ad: CloudXAd) => void;
1068
- onRevenuePaid?: (ad: CloudXAd) => void;
1069
- }
1070
-
1071
- interface UseBannerResult {
1072
- isLoaded: boolean;
1073
- isVisible: boolean;
1074
- error: string | null;
1075
- render: (props?: ViewProps) => React.ReactElement;
1076
- show: () => Promise<void>;
1077
- hide: () => Promise<void>;
1078
- destroy: () => Promise<void>;
1079
- }
559
+ 1. Initialize the SDK with verbose logging enabled
560
+ 2. Find your device advertising ID in the console logs
561
+ 3. Add the device to your whitelist on the CloudX dashboard
1080
562
 
1081
- const banner = useCloudXBanner(options);
1082
- ```
1083
-
1084
- ### useCloudXNative
563
+ ### Debug Logging
1085
564
 
1086
565
  ```typescript
1087
- interface UseNativeOptions {
1088
- placement: string;
1089
- adId: string;
1090
- onLoaded?: (ad: CloudXAd) => void;
1091
- onFailedToLoad?: (error: string) => void;
1092
- onImpression?: (ad: CloudXAd) => void;
1093
- onClicked?: (ad: CloudXAd) => void;
1094
- onRevenuePaid?: (ad: CloudXAd) => void;
1095
- }
566
+ import { CloudX, CloudXLogLevel } from 'cloudx-react-native';
1096
567
 
1097
- interface UseNativeResult {
1098
- isLoaded: boolean;
1099
- assets: NativeAdAssets | null;
1100
- error: string | null;
1101
- load: () => Promise<void>;
1102
- click: () => Promise<void>;
1103
- destroy: () => Promise<void>;
1104
- }
568
+ // Enable verbose logging (call before initialize)
569
+ CloudX.setMinLogLevel(CloudXLogLevel.VERBOSE);
1105
570
 
1106
- const nativeAd = useCloudXNative(options);
571
+ // Available levels: VERBOSE, DEBUG, INFO, WARN, ERROR, NONE
1107
572
  ```
1108
573
 
1109
- ---
1110
-
1111
- ## TypeScript Support
574
+ ### Visual Debugging
1112
575
 
1113
- The SDK is fully typed with TypeScript definitions included.
576
+ Enable visual debugging overlays to see ad unit boundaries and network info:
1114
577
 
1115
578
  ```typescript
1116
- import CloudXSDK, {
1117
- CloudXAd,
1118
- CloudXAdEvent,
1119
- CloudXEventTypes,
1120
- BannerSizes,
1121
- CloudXBannerView,
1122
- useCloudXInterstitial,
1123
- useCloudXRewarded,
1124
- useCloudXBanner,
1125
- useCloudXNative,
1126
- } from 'cloudx-react-native';
1127
-
1128
- // All types are exported and fully documented
579
+ CloudX.setVisualDebuggingEnabled(true);
1129
580
  ```
1130
581
 
1131
- ---
1132
-
1133
582
  ## Platform Support
1134
583
 
1135
584
  | Platform | Status | Minimum Version |
1136
585
  |----------|--------|-----------------|
1137
- | iOS | ✅ Supported | iOS 14.0+ |
1138
- | Android | 🚧 Coming Soon | API 21+ (Android 5.0+) |
586
+ | iOS | Supported | iOS 13.0+ |
587
+ | Android | Supported | API 23+ |
1139
588
 
1140
589
  ### Requirements
1141
590
 
1142
- #### iOS
1143
- - iOS 14.0 or higher
1144
- - CocoaPods
1145
- - Xcode 13.0+
1146
-
1147
- #### Android
1148
- - Android API 21 (Android 5.0) or higher
1149
- - Gradle 8.0+
1150
- - Kotlin 1.8+
1151
-
1152
- #### React Native
1153
591
  - React Native 0.70+
1154
592
  - React 18.0+
1155
- - TypeScript 4.5+ (optional but recommended)
593
+ - TypeScript 4.5+ (recommended)
594
+ - Xcode 14.0+ / CocoaPods (iOS)
595
+ - Gradle 8.0+ / Kotlin 1.8+ (Android)
1156
596
 
1157
- ---
597
+ ### Native SDK Versions (2.0.0)
1158
598
 
1159
- ## Troubleshooting
1160
-
1161
- ### SDK Not Initializing
1162
-
1163
- ```javascript
1164
- // Make sure to await initialization with explicit testMode
1165
- const result = await CloudXSDK.initialize({
1166
- appKey: 'YOUR_APP_KEY',
1167
- testMode: false, // Explicit for production
1168
- });
1169
- if (!result.success) {
1170
- console.error('Initialization failed:', result.message);
1171
- }
1172
-
1173
- // Check iOS setup
1174
- // 1. Verify CloudXCore pod is installed
1175
- // 2. Run `pod install` in ios/ directory
1176
- // 3. Check Info.plist has required permissions
1177
- ```
1178
-
1179
- ### Ads Not Loading
1180
-
1181
- ```javascript
1182
- // 1. Check SDK is initialized
1183
- const initialized = await CloudXSDK.isInitialized();
1184
-
1185
- // 2. Enable logging to see detailed errors
1186
- await CloudXSDK.setLoggingEnabled(true);
1187
-
1188
- // 3. Check placement is configured in CloudX dashboard
599
+ | Platform | Dependency | Version |
600
+ |----------|-----------|---------|
601
+ | iOS | CloudXCore | ~> 2.2.0-beta |
602
+ | Android | io.cloudx:sdk | 2.0.0 |
1189
603
 
1190
- // 4. Verify network connectivity
1191
-
1192
- // 5. Check for error events
1193
- CloudXSDK.addEventListener(
1194
- CloudXEventTypes.INTERSTITIAL_FAILED_TO_LOAD,
1195
- (event) => console.error('Load error:', event.error)
1196
- );
1197
- ```
604
+ ## Troubleshooting
1198
605
 
1199
- ### Memory Leaks
1200
-
1201
- ```javascript
1202
- // Always destroy ads when done
1203
- useEffect(() => {
1204
- return () => {
1205
- CloudXSDK.destroyAd({ adId: 'my-ad' });
1206
- };
1207
- }, []);
1208
-
1209
- // Remove event listeners
1210
- useEffect(() => {
1211
- const listener = CloudXSDK.addEventListener(...);
1212
- return () => listener.remove();
1213
- }, []);
1214
- ```
606
+ ### React Native 0.84.0 — TurboModuleRegistry crash
1215
607
 
1216
- ---
608
+ React Native 0.84.0 has a known issue where `TurboModuleRegistry.getEnforcing(...)` fails with:
1217
609
 
1218
- ## Examples
610
+ > `TurboModuleRegistry.getEnforcing(...): 'PlatformConstants' could not be found. Verify that a module by this name is registered in the native binary.`
1219
611
 
1220
- Complete example application is available in the [example/](example/) directory.
612
+ This is a React Native framework bug, not a CloudX SDK issue. It manifests as a red screen crash on app launch:
1221
613
 
1222
- ```bash
1223
- # Run example app
1224
- cd example
1225
- npm install
1226
- cd ios && pod install && cd ..
1227
- npm run ios
1228
- ```
614
+ ![RN 0.84.0 TurboModule crash](docs/images/rn-084-turbomodule-crash.png)
1229
615
 
1230
- ---
616
+ **Workaround:** Use React Native 0.83.x or wait for the fix in a later 0.84.x patch release. The CloudX SDK is fully compatible with RN 0.70 through 0.83.
1231
617
 
1232
618
  ## Documentation
1233
619
 
1234
- - **[SDK Audit](SDK_AUDIT.md)**: Detailed comparison with Flutter SDK and implementation roadmap
1235
- - **[API Reference](https://docs.cloudx.io/react-native)**: Complete API documentation
1236
- - **[iOS Integration Guide](https://docs.cloudx.io/ios)**: CloudX iOS SDK documentation
1237
-
1238
- ---
620
+ - **[Integration Guide](https://docs.cloudx.io/en/react-native/integration)**: Complete integration documentation
621
+ - **[Changelog](https://docs.cloudx.io/en/react-native/changelog)**: Release history
1239
622
 
1240
623
  ## Support
1241
624
 
1242
- For technical support and questions:
1243
-
1244
- - 📧 **Email**: support@cloudx.io
1245
- - 🐛 **Issues**: [GitHub Issues](https://github.com/cloudx-io/cloudx-react-native/issues)
1246
- - 📚 **Docs**: [docs.cloudx.io](https://docs.cloudx.io)
625
+ For support, contact mobile@cloudx.io
1247
626
 
1248
- ---
627
+ - Email: mobile@cloudx.io
628
+ - Issues: [GitHub Issues](https://github.com/cloudx-io/cloudx-react-native/issues)
1249
629
 
1250
630
  ## License
1251
631
 
1252
- This project is licensed under the Elastic License 2.0 - see the [LICENSE](LICENSE) file for details.
1253
-
1254
- ---
1255
-
1256
- ## Changelog
1257
-
1258
- See [RELEASES](https://github.com/cloudx-io/cloudx-react-native/releases) for detailed changelog and version history.
632
+ This project is licensed under the Elastic License 2.0 — see the [LICENSE](LICENSE) file for details.