📖 Przegląd

Moduł ADS to centralny punkt zarządzania reklamami w bibliotece ADict. Obsługuje mediację między sieciami reklamowymi, telemetrię, debugging i wewnętrzne reklamy (HomeAds).

💡 Formaty reklam Szczegółowa dokumentacja formatów (Banner, Native, Interstitial, Rewarded) znajduje się w sekcji Formaty reklam.

🏗️ Struktura modułu

Struktura ADS
object ADS {
    val AdEvents: AdEvents       // Strumień eventów reklamowych
    val Telemetry: Telemetry     // Metryki i statystyki
    val AdRevenue: AdRevenue     // Śledzenie przychodów z reklam
    val DebugOverlay             // Wizualny debugger
    val HomeAds: HomeAds         // Wewnętrzne reklamy (fallback)
    val AdGate: AdGate           // Dynamiczne blokowanie reklam
    val Mediators                // Konfiguracja mediacji
    val Formats                  // Stałe formatów (BANNER, NATIVE, etc.)
    val Callbacks                // Rejestracja callbacków
    val Strategies               // Stałe strategii mediacji
    val FullscreenPrefetcher     // Wstępne ładowanie fullscreen
}

🚫 AdGate - Blokowanie reklam

Dynamiczne blokowanie reklam na różnych poziomach (globalnie, per strefa, per format).

Podstawowe użycie
// Globalne blokowanie z Remote Config
ADict.ADS.AdGate.setRemoteBlocked(true)

// Globalne blokowanie runtime (np. dla premium)
ADict.ADS.AdGate.setRuntimeBlocked(true)
ADict.ADS.AdGate.setRuntimeBlocked(false)

// Lokalna reguła blokowania
ADict.ADS.AdGate.addLocalRule("block-feed-banner") { req ->
    req.zone == "feed" && req.format == AdGate.Format.BANNER
}

// Usunięcie reguły
ADict.ADS.AdGate.removeLocalRule("block-feed-banner")

// Nasłuchiwanie na stan
lifecycleScope.launch {
    ADict.ADS.AdGate.state.collect { state ->
        Log.d("AdGate", "blocked=${state.blocked}, reasons=${state.reasons}")
    }
}

// Sprawdzenie czy reklama dozwolona
val request = AdGate.AdRequest("feed", AdGate.Format.BANNER, "admob", "unit123")
val allowed = ADict.ADS.AdGate.shouldAllow(request)

Formaty (AdGate.Format)

FormatOpis
BANNERBanner reklamowy
NATIVEReklama natywna
INTERSTITIALReklama pełnoekranowa
REWARDEDReklama z nagrodą

Przyczyny blokady (AdGate.Reason)

ReasonOpis
RemoteConfigBlokada z Firebase Remote Config
RuntimeToggleBlokada runtime (np. premium user)
Local(source)Lokalna reguła z podanym źródłem

💰 AdRevenue - Śledzenie przychodów

Moduł do śledzenia przychodów z reklam z integracją Analytics dla LTV tracking i porównywania performance providerów.

Podstawowe użycie
// Track revenue from ad impression
ADict.ADS.AdRevenue.track(
    zone = "banner_home",
    provider = "admob",
    format = "banner",
    revenueMicros = 1500, // $0.0015
    currency = "USD"
)

// Integration with AdMob OnPaidEventListener
adView.setOnPaidEventListener { adValue ->
    ADict.ADS.AdRevenue.trackAdMob(
        zone = "banner_home",
        format = "banner",
        valueMicros = adValue.valueMicros,
        currencyCode = adValue.currencyCode
    )
}
Statystyki
// Per zone stats
val stats = ADict.ADS.AdRevenue.getStats("banner_home")
println("Total revenue: $${stats?.totalRevenue}")
println("eCPM: $${stats?.ecpm}")
println("Impressions: ${stats?.impressions}")

// Session stats
val sessionRevenue = ADict.ADS.AdRevenue.getSessionRevenue()
val sessionEcpm = ADict.ADS.AdRevenue.getSessionEcpm()

// Lifetime stats
val lifetimeRevenue = ADict.ADS.AdRevenue.getLifetimeRevenue()
val lifetimeEcpm = ADict.ADS.AdRevenue.getLifetimeEcpm()
Porównanie providerów
// Compare providers by eCPM
val ranking = ADict.ADS.AdRevenue.compareProviders("banner_home")
ranking.forEach { (provider, ecpm) ->
    println("$provider: eCPM = $$ecpm")
}

// Get best performing provider
val best = ADict.ADS.AdRevenue.getBestProvider("banner_home")
println("Best provider: $best")
Analytics integration
// Enable automatic Analytics logging
ADict.ADS.AdRevenue.enableAnalyticsIntegration(true)
// All revenue events now logged as "ad_revenue" events

// Manual callback for custom handling
ADict.ADS.AdRevenue.onRevenue { event ->
    customAnalytics.logRevenue(
        event.zone, event.revenueMicros / 1_000_000.0
    )
}

🏠 HomeAds - Wewnętrzne reklamy

HomeAds to system wewnętrznych reklam używanych jako fallback gdy zewnętrzne sieci (np. AdMob) nie dostarczą reklamy.

⚠️ Ważne: zone to nazwa strefy reklamowej, a klucze w mapie ("default", "premium", etc.) to unit keys - warianty reklam w ramach tej strefy.
Rejestracja HomeAds
ADict.ADS.HomeAds.register(
    zone = "feed",                    // Nazwa STREFY
    cfg = HomeAds.ZoneConfig(
        banner = mapOf(
            "default" to listOf(      // UNIT KEY
                HomeAds.Source.Layout(R.layout.homeads_banner_1),
                HomeAds.Source.Layout(R.layout.homeads_banner_2),
                HomeAds.Source.Factory { ctx -> MyCustomBannerView(ctx) }
            ),
            "premium" to listOf(      // Inny UNIT KEY
                HomeAds.Source.Layout(R.layout.homeads_banner_premium)
            )
        ),
        native = mapOf(
            "default" to listOf(
                HomeAds.Source.Layout(R.layout.homeads_native)
            )
        ),
        interstitial = mapOf(
            "default" to listOf(
                HomeAds.Source.Layout(R.layout.homeads_interstitial)
            )
        ),
        rewarded = mapOf(
            "default" to listOf(
                HomeAds.RewardSource(
                    source = HomeAds.Source.Layout(R.layout.homeads_rewarded),
                    type = "coins",
                    amount = 10.0,
                    grantOnClose = true
                )
            )
        )
    ),
    strategy = HomeAds.Strategy.ROUND_ROBIN  // FIRST, RANDOM, ROUND_ROBIN
)

// Wyczyszczenie konfiguracji
ADict.ADS.HomeAds.clear()

Strategie wyboru layoutu

StrategiaOpis
FIRSTZawsze pierwszy layout z listy
RANDOMLosowy wybór z listy
ROUND_ROBINRotacja po kolei

Więcej: Pełna dokumentacja HomeAds

📞 Callbacks - Callbacki reklam

Rejestracja callbacka
ADict.ADS.Callbacks.register("default", object : AdCallback {
    override fun onSuccess(type: String, provider: String, zone: String?, adUnit: String) {
        Log.d("Ad", "Success: $type from $provider")
    }

    override fun onFail(type: String, provider: String, zone: String?, adUnit: String, error: String?) {
        Log.e("Ad", "Fail: $type from $provider - $error")
    }
})

// Wyrejestrowanie
ADict.ADS.Callbacks.unregister("default")

// Wyczyszczenie wszystkich
ADict.ADS.Callbacks.clear()

💾 Fullscreen Prefetcher

Wstępne ładowanie reklam pełnoekranowych dla szybszego wyświetlania.

Prefetch
// Prefetch interstitial
ADict.ADS.FullscreenPrefetcher.prefetchInterstitial(
    context = context,
    zone = "default"
)

// Prefetch rewarded
ADict.ADS.FullscreenPrefetcher.prefetchRewarded(
    context = context,
    zone = "default"
)

// Sprawdzenie czy gotowe
val isReady = ADict.ADS.FullscreenPrefetcher.isInterstitialReady("default")

📚 Więcej

📐

Formaty reklam

Banner, Native, Interstitial, Rewarded - przykłady użycia

🎯

Strategie mediacji

Round-robin, Priority, Random, Weighted, Auction

⚙️

Konfiguracja JSON

Strefy, cap/pacing, quarantine, A/B testing

📊

Telemetria

Strumień eventów, metryki, snapshot

🔧

Debug Overlay

Wizualny debugger reklam

🏠

HomeAds

Wewnętrzne reklamy jako fallback