ads_kit 0.1.1
ads_kit: ^0.1.1 copied to clipboard
Mediation-platform-independent ad abstraction: AdProvider contract, AdManager, frequency capping, health monitoring and remote-config-driven provider selection.
ads_kit #
A mediation-platform-independent ad abstraction for Flutter apps. Your app
code depends only on ads_kit — never on a mediation SDK directly — so
swapping ad providers is a remote-config value, not a store release.
Provider implementations live in their own packages (e.g.
ads_kit_levelplay for Unity
LevelPlay, ads_kit_max for AppLovin MAX)
and translate their SDK's types into this package's vocabulary. No ad-SDK
type ever crosses into ads_kit's public API.
What you get #
AdProvider— the contract every mediation package implements: init/dispose, preload, readiness, fullscreen shows, banner widget, and a singleAdEventstream.AdManager— the one entry point the app talks to. Reads Firebase Remote Config, resolves the active provider, falls back throughfallback_providerdown to a built-in no-op provider ("no ads" always beats "wrong ads"), preloads enabled formats, and recovers back to the configured provider on a cooldown after an automatic fallback.FrequencyGuard— mandatory interstitial pacing (cold-start grace, minimum interval, session cap, per-country disable) to keep policy risk down.HealthMonitor— consecutive-failure tracking that triggers the fallback chain. No-fill is treated as inventory, never as provider failure.- Typed events —
AdEventLoaded/Shown/Dismissed/RewardEarned/...and a normalizedAdRevenueper impression, comparable across providers. - Consent plumbing —
AdConsent(GDPR/CCPA/COPPA/ATT) applied at init and updatable mid-session viaAdManager.updateConsent.
Usage #
// main.dart — register whichever provider packages this app ships with.
AdManager.register('levelplay', () => LevelPlayAdProvider());
await AdManager.boot(
consent: myResolvedConsent,
providerExtras: {
'levelplay': {
'app_key_android': '...',
'app_key_ios': '...',
'rewarded_ad_unit_id_android': '...',
'rewarded_ad_unit_id_ios': '...',
},
},
);
// Anywhere else in the app:
final result = await AdManager.I.showRewarded();
// Fullscreen show futures resolve when the ad is *dismissed* — safe to
// continue your flow (navigate, grant rewards) the moment they complete.
_android/_ios key suffixes resolve to the running platform, so one
shared config serves both.
Remote config #
One Firebase Remote Config string parameter, ads_config, holding JSON.
Every field is optional; missing or malformed input degrades to safe
defaults, and no config at all means no ads:
{
"active_provider": "levelplay",
"fallback_provider": "noop",
"formats_enabled": ["rewarded"],
"interstitial_min_interval_sec": 60,
"interstitial_max_per_session": 3,
"cold_start_grace_sec": 30,
"health_failure_threshold": 3,
"recovery_cooldown_sec": 300,
"recovery_max_attempts": 3,
"providers": {
"levelplay": {"app_key_android": "...", "app_key_ios": "..."}
}
}
Flipping providers without a release: change active_provider, or call
AdManager.switchProvider('max') directly.
Writing a provider package #
Implement AdProvider, translate every SDK type at the boundary, and emit
AdEventFailed for every load/show failure — the health monitor counts
those events as its only signal. See the
repository for two complete
reference implementations and the full design notes.