admanagekit-mcp-server 1.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 (74) hide show
  1. package/content/README.md +851 -0
  2. package/content/docs/AD_FREQUENCY_CONTROL.md +450 -0
  3. package/content/docs/AD_LOADING_STRATEGIES.md +369 -0
  4. package/content/docs/API_REFERENCE.md +734 -0
  5. package/content/docs/APP_PURCHASE_GUIDE.md +704 -0
  6. package/content/docs/BANNER_AD_IMPROVEMENTS.md +325 -0
  7. package/content/docs/COMPOSE_INTEGRATION.md +477 -0
  8. package/content/docs/CONFIGURATION_USAGE.md +168 -0
  9. package/content/docs/INTERSTITIAL_BUILDER_GUIDE.md +518 -0
  10. package/content/docs/JAVA_USAGE_GUIDE.md +785 -0
  11. package/content/docs/LOADING_STRATEGY_EXAMPLES.md +463 -0
  12. package/content/docs/NATIVE_AD_MANAGER_ENHANCEMENTS.md +347 -0
  13. package/content/docs/NATIVE_AD_PRELOADING.md +467 -0
  14. package/content/docs/NATIVE_TEMPLATE_VIEW.md +413 -0
  15. package/content/docs/app-open-ads.md +412 -0
  16. package/content/docs/interstitial-ads.md +269 -0
  17. package/content/docs/native-ads-caching.md +182 -0
  18. package/content/docs/release-notes/RELEASE_NOTES_v2.1.0.md +156 -0
  19. package/content/docs/release-notes/RELEASE_NOTES_v2.2.0.md +248 -0
  20. package/content/docs/release-notes/RELEASE_NOTES_v2.3.0.md +280 -0
  21. package/content/docs/release-notes/RELEASE_NOTES_v2.5.0.md +73 -0
  22. package/content/docs/release-notes/RELEASE_NOTES_v2.6.0.md +265 -0
  23. package/content/docs/release-notes/RELEASE_NOTES_v2.7.0.md +168 -0
  24. package/content/docs/release-notes/RELEASE_NOTES_v2.8.0.md +153 -0
  25. package/content/docs/release-notes/RELEASE_NOTES_v2.9.0.md +479 -0
  26. package/content/docs/release-notes/RELEASE_NOTES_v3.0.0.md +343 -0
  27. package/content/docs/release-notes/RELEASE_NOTES_v3.1.0.md +131 -0
  28. package/content/docs/release-notes/RELEASE_NOTES_v3.3.0.md +252 -0
  29. package/content/docs/release-notes/RELEASE_NOTES_v3.3.2.md +215 -0
  30. package/content/docs/release-notes/RELEASE_NOTES_v3.3.3.md +116 -0
  31. package/content/docs/release-notes/RELEASE_NOTES_v3.3.4.md +142 -0
  32. package/content/docs/release-notes/RELEASE_NOTES_v3.3.5.md +94 -0
  33. package/content/docs/rewarded-ads.md +623 -0
  34. package/content/wiki/Ad-Loading-Strategies.md +209 -0
  35. package/content/wiki/App-Open-Ads.md +189 -0
  36. package/content/wiki/Banner-Ads.md +133 -0
  37. package/content/wiki/Billing-Integration.md +69 -0
  38. package/content/wiki/Configuration.md +252 -0
  39. package/content/wiki/Consumable-Products.md +166 -0
  40. package/content/wiki/Home.md +144 -0
  41. package/content/wiki/Interstitial-Ads.md +313 -0
  42. package/content/wiki/Jetpack-Compose.md +270 -0
  43. package/content/wiki/NativeAdManager.md +220 -0
  44. package/content/wiki/Purchase-Categories.md +94 -0
  45. package/content/wiki/Rewarded-Ads.md +420 -0
  46. package/content/wiki/Subscription-Upgrades.md +278 -0
  47. package/content/wiki/Subscriptions.md +368 -0
  48. package/content/wiki/_Footer.md +3 -0
  49. package/content/wiki/_Sidebar.md +18 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.js +6 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/server.d.ts +1 -0
  54. package/dist/server.js +18 -0
  55. package/dist/server.js.map +1 -0
  56. package/dist/tools/code-generation.d.ts +2 -0
  57. package/dist/tools/code-generation.js +264 -0
  58. package/dist/tools/code-generation.js.map +1 -0
  59. package/dist/tools/documentation.d.ts +2 -0
  60. package/dist/tools/documentation.js +202 -0
  61. package/dist/tools/documentation.js.map +1 -0
  62. package/dist/types.d.ts +18 -0
  63. package/dist/types.js +83 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/utils/doc-loader.d.ts +17 -0
  66. package/dist/utils/doc-loader.js +245 -0
  67. package/dist/utils/doc-loader.js.map +1 -0
  68. package/dist/utils/search.d.ts +2 -0
  69. package/dist/utils/search.js +62 -0
  70. package/dist/utils/search.js.map +1 -0
  71. package/dist/utils/templates.d.ts +60 -0
  72. package/dist/utils/templates.js +793 -0
  73. package/dist/utils/templates.js.map +1 -0
  74. package/package.json +51 -0
@@ -0,0 +1,343 @@
1
+ # Release Notes - v3.0.0
2
+
3
+ ## Highlights
4
+
5
+ - **Ad Pool System**: Load multiple interstitial ad units into a pool for maximum show rate
6
+ - **Smart Splash Ads**: New `showOrWaitForAd()` method handles all splash screen scenarios automatically
7
+ - **App Open Ad Prefetching**: Prefetch ads before external intents for instant display on return
8
+ - **Cross-Ad-Unit Fallback**: Native ads can fall back to any cached ad when specific unit unavailable
9
+ - **New Template**: `MEDIUM_HORIZONTAL` - 55/45 media-content horizontal split layout
10
+ - **Modern Window APIs**: Replaced deprecated `systemUiVisibility` with `WindowInsetsController`
11
+ - **Enhanced Firebase Analytics**: Session-level tracking for fill rate, show rate, and ad impressions
12
+
13
+ ---
14
+
15
+ ## New Features
16
+
17
+ ### AdManager - Ad Pool System
18
+
19
+ Load multiple interstitial ad units into a pool. When showing, returns ANY available ad - maximizing show rate:
20
+
21
+ ```kotlin
22
+ // Load multiple ad units for redundancy
23
+ AdManager.getInstance().loadMultipleAdUnits(context, "high_ecpm", "medium_ecpm", "fallback")
24
+
25
+ // Or load individually
26
+ AdManager.getInstance().loadInterstitialAd(context, "unit_a")
27
+ AdManager.getInstance().loadInterstitialAd(context, "unit_b")
28
+
29
+ // Show ANY available ad from the pool
30
+ AdManager.getInstance().showInterstitialIfReady(activity, callback)
31
+
32
+ // Pool utilities
33
+ AdManager.getInstance().getPoolSize() // Number of ready ads
34
+ AdManager.getInstance().getReadyAdUnits() // Set of ad unit IDs with ready ads
35
+ AdManager.getInstance().isReady("unit_a") // Check specific unit
36
+ AdManager.getInstance().clearAdPool() // Clear all ads (e.g., on purchase)
37
+ ```
38
+
39
+ **Key behaviors:**
40
+ - Each ad unit loads independently (no blocking)
41
+ - Duplicate load requests for same unit are automatically skipped
42
+ - Auto-reloads the specific unit that was shown
43
+ - Thread-safe with `ConcurrentHashMap`
44
+
45
+ ### AdManager - Smart Splash Ads
46
+
47
+ New `showOrWaitForAd()` method handles all splash screen scenarios in a single call:
48
+
49
+ ```kotlin
50
+ // In your SplashActivity
51
+ private fun showSplashAd() {
52
+ AdManager.getInstance().showOrWaitForAd(
53
+ activity = this,
54
+ callback = object : AdManagerCallback() {
55
+ override fun onNextAction() {
56
+ navigateToMainActivity()
57
+ }
58
+ },
59
+ timeoutMillis = 10_000,
60
+ showDialogIfLoading = true
61
+ )
62
+ }
63
+ ```
64
+
65
+ **Automatic behavior:**
66
+ | Scenario | What happens |
67
+ |----------|--------------|
68
+ | Ad is READY | Shows immediately |
69
+ | Ad is LOADING | Waits with optional dialog, shows when ready or times out |
70
+ | Neither | Loads fresh ad with loading dialog |
71
+
72
+ **Recommended splash flow:**
73
+ ```kotlin
74
+ // Option 1: Preload in Application, smart show on splash
75
+ class MyApp : Application() {
76
+ override fun onCreate() {
77
+ AdManager.getInstance().loadInterstitialAd(this, adUnitId)
78
+ }
79
+ }
80
+
81
+ class SplashActivity : AppCompatActivity() {
82
+ override fun onCreate(savedInstanceState: Bundle?) {
83
+ // Ad may already be loaded from Application
84
+ AdManager.getInstance().showOrWaitForAd(this, callback, 10_000)
85
+ }
86
+ }
87
+
88
+ // Option 2: Load and show on splash (all-in-one)
89
+ class SplashActivity : AppCompatActivity() {
90
+ override fun onCreate(savedInstanceState: Bundle?) {
91
+ // Works even with no preloading
92
+ AdManager.getInstance().showOrWaitForAd(this, callback, 10_000)
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### AppOpenManager - Ad Prefetching
98
+
99
+ Prefetch app open ads before launching external intents:
100
+
101
+ ```kotlin
102
+ // Before launching camera, browser, etc.
103
+ appOpenManager.prefetchNextAd { started ->
104
+ if (started) Log.d("ADS", "Prefetch started")
105
+ }
106
+ startActivityForResult(cameraIntent, REQUEST_CODE)
107
+
108
+ // When user returns:
109
+ // - If ad is ready: shows instantly (no welcome dialog)
110
+ // - If still loading: welcome dialog waits for it
111
+
112
+ // Check loading state
113
+ if (appOpenManager.isAdLoading()) {
114
+ // Ad is being fetched
115
+ }
116
+ ```
117
+
118
+ ### NativeAdManager - Cross-Ad-Unit Fallback
119
+
120
+ When enabled, native ads can fall back to ANY cached ad from ANY ad unit:
121
+
122
+ ```kotlin
123
+ // Enable in config
124
+ AdManageKitConfig.enableCrossAdUnitFallback = true
125
+
126
+ // Now getCachedNativeAd will:
127
+ // 1. Try exact ad unit match
128
+ // 2. Try same base ad unit variants
129
+ // 3. Try ANY cached ad from any unit (if enableCrossAdUnitFallback = true)
130
+ val ad = NativeAdManager.getCachedNativeAd(adUnitId, enableFallbackToAnyAd = true)
131
+ ```
132
+
133
+ ### Enhanced Firebase Analytics
134
+
135
+ Session-level tracking for comprehensive ad performance metrics:
136
+
137
+ ```kotlin
138
+ // Get current session stats
139
+ val stats = AdManager.getInstance().getAdStats()
140
+ // Returns: session_requests, session_fills, session_impressions,
141
+ // fill_rate_percent, show_rate_percent, pool_size, ready_units
142
+
143
+ // Reset for new session
144
+ AdManager.getInstance().resetAdStats()
145
+ ```
146
+
147
+ **Logged events:**
148
+ | Event | Description |
149
+ |-------|-------------|
150
+ | `ad_request` | When ad load is initiated |
151
+ | `ad_fill` | When ad loads successfully |
152
+ | `ad_impression_detailed` | When ad is shown (with fill/show rates) |
153
+ | `ad_not_shown` | When ad couldn't be shown |
154
+
155
+ **User properties updated:**
156
+ - `total_ad_requests`, `total_ad_fills`, `total_ads_shown`
157
+ - `ad_fill_rate`, `ad_show_rate`
158
+
159
+ ---
160
+
161
+ ## API Changes
162
+
163
+ ### AdManager - New Methods
164
+
165
+ | Method | Description |
166
+ |--------|-------------|
167
+ | `loadMultipleAdUnits(context, adUnitIds)` | Load multiple ad units into pool |
168
+ | `loadMultipleAdUnits(context, vararg adUnitIds)` | Vararg version |
169
+ | `showOrWaitForAd(activity, callback, timeout, showDialog)` | Smart splash ad showing |
170
+ | `getPoolSize()` | Number of ready ads in pool |
171
+ | `getReadyAdUnits()` | Set of ad unit IDs with ready ads |
172
+ | `isReady(adUnitId)` | Check if specific unit has ad ready |
173
+ | `clearAdPool()` | Remove all ads from pool |
174
+ | `getAdStats()` | Get session ad statistics |
175
+ | `resetAdStats()` | Reset session statistics |
176
+ | `preloadAd(context, adUnitId)` | Proactively preload an ad |
177
+ | `resetAdThrottling()` | Reset display counters and intervals |
178
+ | `enableAggressiveAdLoading()` | Set 5s interval for max show rate |
179
+ | `getLastAdShowTime()` | Timestamp of last ad show |
180
+ | `getTimeSinceLastAd()` | Milliseconds since last ad |
181
+ | `isLoading()` | Check if any ad is loading |
182
+
183
+ ### AppOpenManager - New Methods
184
+
185
+ | Method | Description |
186
+ |--------|-------------|
187
+ | `prefetchNextAd(onPrefetchStarted)` | Prefetch ad before external intent |
188
+ | `isAdLoading()` | Check if ad is currently loading |
189
+
190
+ ### AdManageKitConfig - New Properties
191
+
192
+ | Property | Type | Default | Description |
193
+ |----------|------|---------|-------------|
194
+ | `enableCrossAdUnitFallback` | Boolean | `false` | Allow native ad fallback across ad units |
195
+
196
+ ---
197
+
198
+ ## Improvements
199
+
200
+ ### Modern Window APIs
201
+
202
+ Replaced deprecated `systemUiVisibility` with `WindowInsetsController` for Android 11+ compatibility:
203
+
204
+ ```kotlin
205
+ // Old (deprecated)
206
+ decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or ...
207
+
208
+ // New (v3.0.0)
209
+ WindowCompat.setDecorFitsSystemWindows(window, false)
210
+ WindowCompat.getInsetsController(window, decorView).apply {
211
+ hide(WindowInsetsCompat.Type.systemBars())
212
+ systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
213
+ }
214
+ ```
215
+
216
+ ### Duplicate Load Prevention
217
+
218
+ `loadInterstitialAd()` now prevents duplicate requests:
219
+ - Skips if ad unit is already loading
220
+ - Skips if ad unit already has ad in pool
221
+ - Logs debug events for tracking
222
+
223
+ ### Improved Timeout Handling
224
+
225
+ `loadInterstitialAdForSplash()` timeout now:
226
+ - Resets `isAdLoading` flag to allow new requests
227
+ - Still saves ad if it arrives after timeout (not wasted)
228
+ - Prevents blocking of subsequent load calls
229
+
230
+ ### Thread-Safe Ad Pool
231
+
232
+ Ad pool uses `ConcurrentHashMap` for thread safety:
233
+ - Safe concurrent access from multiple threads
234
+ - `loadingAdUnits` tracks in-flight requests
235
+ - No race conditions on load/show
236
+
237
+ ---
238
+
239
+ ## Migration Guide
240
+
241
+ ### From 2.9.0 to 3.0.0
242
+
243
+ v3.0.0 is **fully backward compatible**. All existing code continues to work.
244
+
245
+ #### Recommended: Adopt Smart Splash Ads
246
+
247
+ Replace separate load + show calls with single `showOrWaitForAd()`:
248
+
249
+ ```kotlin
250
+ // Before (v2.9.0) - Two-step approach
251
+ AdManager.getInstance().loadInterstitialAdForSplash(this, adUnitId, 10_000, object : AdManagerCallback() {
252
+ override fun onNextAction() {
253
+ if (!AdManager.getInstance().isDisplayingAd()) {
254
+ AdManager.getInstance().forceShowInterstitial(this@SplashActivity, callback)
255
+ }
256
+ }
257
+ })
258
+
259
+ // After (v3.0.0) - Single smart call
260
+ AdManager.getInstance().showOrWaitForAd(
261
+ activity = this,
262
+ callback = object : AdManagerCallback() {
263
+ override fun onNextAction() { navigateNext() }
264
+ },
265
+ timeoutMillis = 10_000
266
+ )
267
+ ```
268
+
269
+ #### Recommended: Use Ad Pool for Higher Show Rate
270
+
271
+ ```kotlin
272
+ // Before (single ad unit)
273
+ AdManager.getInstance().loadInterstitialAd(context, "single_unit")
274
+
275
+ // After (multiple ad units for redundancy)
276
+ AdManager.getInstance().loadMultipleAdUnits(context, "high_ecpm", "medium_ecpm", "fallback")
277
+ ```
278
+
279
+ #### Optional: Enable Cross-Ad-Unit Fallback
280
+
281
+ ```kotlin
282
+ // In Application.onCreate()
283
+ AdManageKitConfig.enableCrossAdUnitFallback = true
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Installation
289
+
290
+ ```groovy
291
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit:v3.0.0'
292
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-billing:v3.0.0'
293
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-core:v3.0.0'
294
+ implementation 'com.github.i2hammad.AdManageKit:ad-manage-kit-compose:v3.0.0'
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Full Changelog
300
+
301
+ ### AdManager Enhancements
302
+
303
+ - Added ad pool system with `ConcurrentHashMap` for storing multiple ad units
304
+ - Added `loadMultipleAdUnits()` for loading multiple ad units at once
305
+ - Added `showOrWaitForAd()` smart method for splash screens
306
+ - Added duplicate load prevention (skips if already loading or in pool)
307
+ - Added session-level Firebase analytics (requests, fills, impressions, rates)
308
+ - Added `getAdStats()` and `resetAdStats()` for analytics access
309
+ - Added pool utility methods: `getPoolSize()`, `getReadyAdUnits()`, `clearAdPool()`
310
+ - Added `preloadAd()`, `resetAdThrottling()`, `enableAggressiveAdLoading()`
311
+ - Added `getLastAdShowTime()`, `getTimeSinceLastAd()`, `isLoading()`
312
+ - Improved `loadInterstitialAdForSplash()` timeout handling (resets loading flag)
313
+ - Updated loading dialog to use modern `WindowInsetsController` API
314
+ - Auto-reload now reloads the specific ad unit that was shown
315
+
316
+ ### AppOpenManager Enhancements
317
+
318
+ - Added `prefetchNextAd()` for prefetching before external intents
319
+ - Added `isAdLoading()` to check loading state
320
+ - Changed `currentActivityRef: WeakReference<Activity>` to direct reference for reliability
321
+ - Updated welcome dialog to use modern `WindowInsetsController` API
322
+
323
+ ### NativeAdManager Enhancements
324
+
325
+ - Added cross-ad-unit fallback when `enableCrossAdUnitFallback` is true
326
+ - Added documentation for destructive read pattern (ad removed from cache on retrieve)
327
+ - Improved fallback priority: same base unit variants → cross ad unit
328
+
329
+ ### NativeTemplateView Enhancements
330
+
331
+ - Added `MEDIUM_HORIZONTAL` template: 55% media (left) / 45% content (right) horizontal split
332
+ - Total templates now: 24 (18 standard + 6 video)
333
+
334
+ ### Config Enhancements
335
+
336
+ - Added `enableCrossAdUnitFallback` property to `AdManageKitConfig`
337
+
338
+ ### Technical Improvements
339
+
340
+ - Replaced deprecated `systemUiVisibility` with `WindowInsetsController` throughout
341
+ - Added `WindowCompat.setDecorFitsSystemWindows()` for edge-to-edge display
342
+ - Thread-safe ad pool with `ConcurrentHashMap` and `ConcurrentHashMap.newKeySet()`
343
+ - Improved logging with pool size and ad unit tracking
@@ -0,0 +1,131 @@
1
+ # Release Notes - v3.1.0
2
+
3
+ ## Highlights
4
+
5
+ - **FRESH_WITH_CACHE_FALLBACK Fix**: Successfully loaded ads are now properly cached for future fallback scenarios
6
+ - **New Template**: `MEDIUM_HORIZONTAL` - 55/45 media-content horizontal split layout
7
+ - **Test Activity**: Video ad toggle and updated template documentation
8
+
9
+ ---
10
+
11
+ ## New Features
12
+
13
+ ### FRESH_WITH_CACHE_FALLBACK Strategy - Now Caches Successfully Loaded Ads
14
+
15
+ The `FRESH_WITH_CACHE_FALLBACK` strategy now works as documented. Successfully loaded fresh ads are automatically cached for future fallback use.
16
+
17
+ **Before v3.1.0:** Fresh ads were displayed but NOT cached, making fallback ineffective over time.
18
+
19
+ **After v3.1.0:** Fresh ads are displayed AND cached, building up the cache for better fallback availability.
20
+
21
+ ```kotlin
22
+ // Perfect for RecyclerView scenarios
23
+ AdManageKitConfig.nativeLoadingStrategy = AdLoadingStrategy.FRESH_WITH_CACHE_FALLBACK
24
+
25
+ // How it works now:
26
+ // 1. Try to load fresh ad from network
27
+ // 2. If SUCCESS → Display ad AND cache it for future fallback
28
+ // 3. If FAIL → Fall back to cached ad (if available)
29
+ // 4. Result: Over time, cache builds up with successful loads
30
+ ```
31
+
32
+ ### New Native Template: MEDIUM_HORIZONTAL
33
+
34
+ A new horizontal split layout with 55% media on the left and 45% content on the right.
35
+
36
+ ```xml
37
+ <com.i2hammad.admanagekit.admob.NativeTemplateView
38
+ android:layout_width="match_parent"
39
+ android:layout_height="wrap_content"
40
+ app:adTemplate="medium_horizontal" />
41
+ ```
42
+
43
+ ```kotlin
44
+ nativeTemplateView.setTemplate(NativeAdTemplate.MEDIUM_HORIZONTAL)
45
+ ```
46
+
47
+ **Layout Structure:**
48
+ - Left side: MediaView (55% width, 140dp height)
49
+ - Right side: Ad badge, app icon, headline, body, CTA button (45% width)
50
+
51
+ **Total Templates:** 24 (18 standard + 6 video)
52
+
53
+ ---
54
+
55
+ ## Improvements
56
+
57
+ ### NativeTemplateTestActivity
58
+
59
+ - **Video Ad Toggle**: Switch between standard native ad (`2247696110`) and video native ad (`1044960115`) test units
60
+ - **Updated Notes**: Reflects all 24 available templates with accurate counts
61
+
62
+ ---
63
+
64
+ ## Full Changelog
65
+
66
+ ### NativeTemplateView Enhancements
67
+
68
+ - Added `MEDIUM_HORIZONTAL` template with horizontal 55/45 split layout
69
+ - Added `loadingStrategy` parameter to internal `loadNewAdInternal()` method
70
+ - Fresh ads are now cached when using `FRESH_WITH_CACHE_FALLBACK` strategy
71
+
72
+ ### NativeAdIntegrationManager
73
+
74
+ - Updated comment in `createFreshWithCacheFallbackCallback` to accurately describe caching behavior
75
+
76
+ ### Test Activity
77
+
78
+ - Added `SwitchMaterial` for toggling between standard and video ad units
79
+ - Added `tvAdUnitInfo` to display current ad unit type
80
+ - Updated template count from 17 to 24 in layout notes
81
+
82
+ ### Attrs
83
+
84
+ - Added `medium_horizontal` enum value (16)
85
+ - Shifted `spotlight` and video template values accordingly
86
+
87
+ ---
88
+
89
+ ## Migration Guide
90
+
91
+ Version 3.1.0 is **fully backward compatible**. No migration required.
92
+
93
+ ### Recommended: Use FRESH_WITH_CACHE_FALLBACK for RecyclerView
94
+
95
+ If you're showing native ads in a RecyclerView, consider using `FRESH_WITH_CACHE_FALLBACK`:
96
+
97
+ ```kotlin
98
+ // Global configuration
99
+ AdManageKitConfig.nativeLoadingStrategy = AdLoadingStrategy.FRESH_WITH_CACHE_FALLBACK
100
+
101
+ // Or per-call
102
+ nativeTemplateView.loadNativeAd(
103
+ activity = this,
104
+ adUnitId = "ca-app-pub-xxx/yyy",
105
+ adCallback = callback,
106
+ loadingStrategy = AdLoadingStrategy.FRESH_WITH_CACHE_FALLBACK
107
+ )
108
+ ```
109
+
110
+ **Benefits:**
111
+ - Each item binding tries to get a fresh ad (better revenue)
112
+ - If network fails, cached ad appears immediately (no empty space)
113
+ - Successfully loaded ads build up the cache over time
114
+
115
+ ---
116
+
117
+ ## Dependencies
118
+
119
+ No dependency changes from v3.0.0.
120
+
121
+ ---
122
+
123
+ ## Bug Fixes
124
+
125
+ - **Fixed**: `FRESH_WITH_CACHE_FALLBACK` strategy not caching successfully loaded ads
126
+
127
+ ---
128
+
129
+ ## Known Issues
130
+
131
+ None.