Changelog
Version history and release notes for the Android SDK.
Version 1.0.0 (September 15, 2026)
1.0.0 is now stable and no longer in beta. Update your dependency to the stable release. Upgrading from 0.x? Follow the migration guide.
Version 1.0.0-beta.1 (August 25, 2026)
First release of the 1.0 line — the 1.0 API is frozen, published as a beta on Maven Central; pin the exact version. The full 0.x → 1.0 upgrade path is in the migration guide.
Highlights
- One unified request surface. The legacy query-string ad path is gone — every fetch now goes through
requestAd/prefetchAd/cancelPrefetchAdwith aKoahAdContext, completing the migration the 0.x line deprecated. - Correct device classification. Every request now sends a real
User-Agent(the device's WebView agent plus aKoah/<version>product token), so requests are attributed to the right OS and device type — which can improve targeting and fill. - Viewability counts foreground time only. The
KoahEvent.AdVieweddwell timer resets when the host app is backgrounded (home button, screen off, or a covering activity) — after resume the ad needs a fresh continuous second on screen — so viewed events fire only for time the ad actually spent in the foreground. Impression tracking is unchanged. - Under-13 ages are rejected.
setAge/setAgeRangeignore under-13 values with a warning, and a previously persisted under-13 value is discarded on upgrade.
Breaking changes
- Removed
Koah.prefetch,Koah.resolveAd, andKoah.cancelPrefetch— useprefetchAd/requestAd/cancelPrefetchAdwith aKoahAdContextandcacheKey. - Removed the legacy
KoahCard/KoahAdoverloads takingquery/queryResponse/messageId/conversationId, and the deprecated overloads takingmodifier/overrideMaxWidth/overrideMaxHeight— use theadContextoverloads withwidth/height: KoahAxisSizeandpadding. - Renamed the
messageIdparameter tocacheKeyon the cache-readingKoahCardoverload and the sample-adKoahCard/KoahAdoverloads — binary-compatible, but source-breaking for callers passing the argument by name.
Version 0.3.0 (August 13, 2026)
Highlights
- Per-axis slot sizing.
KoahCard/KoahAdgainwidthandheightparameters of the newKoahAxisSizetype — each axis can be unbounded (wrap),range(min, max),fixed(dp), orfill(). The SDK offers the server only the format variants that fit the resolved bounds, sends a text-length budget forcard_text_mdso copy is sized to the slot, and an ad that can't fit a bounded axis derenders (KoahEvent.SlotTooSmall) instead of clipping. The oldoverrideMaxWidth/overrideMaxHeightoverloads still work but are deprecated. requestAdnow returns a sealedKoahAdResult—Filled/NoFill/Error— so callers can branch over success, no-fill, and failure, which were previously indistinguishable.- Koah's servers can now pick which small image-card treatment a fill renders: today's image-leading control, a labelled action button, a trailing square image, or a content-first layout with a full-height 1.91:1 creative, inline advertiser identity, one headline, and the existing chevron. The selection arrives with the ad; anything this SDK doesn't recognise renders the control. Every fill keeps rendering today's image-leading control until the selection is turned on server-side, so this release changes nothing on its own. Your integration is unchanged: no new format names appear in the ad's
format, no new content fields were added, and the SDK gains no new dependency, configuration, or setup step. - Demographic targeting: gender and household income. Call
Koah.instance.setGender(KoahGender.FEMALE)andKoah.instance.setIncomeBracket(KoahIncomeBracket.INCOME_50K_TO_100K)(brackets are annual household income in thousands of USD). Values are persisted locally and uploaded for ad targeting. PassUNKNOWNto stop this device storing and re-sending a value — a local clear only; it does not delete a value already sent to Koah. This completes the demographic set alongsidesetAge/setAgeRange.
Breaking changes
- minSdk is now 23 (Android 6.0), up from 21. Apps with
minSdk21/22 must raise it to consume 0.3.0. - The SDK's HTTP stack moved to OkHttp 5 (5.4.0) and the library is built with Kotlin 2.4. No integration change for most apps, but projects pinning OkHttp 4.x transitively will resolve 5.x alongside this SDK.
- Logging is configured with
logLevel: KoahLogLevel(NONE/ERROR/WARNING/INFO/DEBUG) — the booleandebugflag is gone. - The t-shirt size API is gone. The server returns an opaque
format; slot bounds (viaKoahAxisSize) narrow what is offered.KoahAdSize,KoahAdOptions, andsize-taking overloads are removed. - Preview requests are spelled
requestPreviewAd(previewFormat, cacheKey)— therequestAd(previewFormat)overload is removed. - The raw ad-content model is no longer public. The supported path returns
KoahAdResultand renders viaKoahCard/KoahAd; use the new publicKoahSampleAdfamily for previews and fixtures. - Internalized:
KoahEnvironment/KoahEnvironmentManager(setbaseUrldirectly),KoahAdSizeConstraints, and other leaked internals; the unusedKoahEvent.InlineProductNameClickedcase is removed.
Improvements
- Impressions are gated on real visibility. Impressions fire when the card first becomes visible in the viewport (and exactly once per served ad), not on composition — scrolled-off-screen fills no longer count.
- Network hardening. Ad requests and attribute uploads get a uniform retry policy (retry on 500/502/503/504, max 3 attempts, 15s overall deadline, jittered backoff,
Retry-Afterhonored when ≤ 2s) plus per-attempt timeouts; tracking calls stay single-attempt. Every failure degrades silently — ads just don't show — and a plain-httpbaseUrlnow logs a security warning. - Expandable ads are never bricked. The expanded body prefetches on fill, a failed fetch retries once on tap, and if it still fails the card falls back to its CTA. The expanded body also fades at the bottom edge until fully scrolled.
- Small card layout: advertiser identity leads and the ad image trails on the text variant, and
card_image_smstays the image-leading control. - A blank/whitespace
publisherIdnow fails fast at first init (IllegalArgumentException) instead of silently disabling ads; duplicate init calls still warn and no-op.
API changes
⚠️ Removed
- Ad-content model, fixture overloads, and internal primitives leave the public surface — the server-decoded ad-content model is no longer public; the supported path returns
KoahAdResult/state and renders viaKoahCard/components. Breaking. - Remove unused
KoahEvent.InlineProductNameClicked— the case was never emitted, so a consumer'sonEventhandler had a deadwhenbranch. Breaking. - Internalize
KoahAdSizeConstraints— the medium card's render-envelope bounds are enforced internally. Breaking. - Internalize
KoahEnvironment/KoahEnvironmentManager— setbaseUrldirectly. Breaking. - Internalize leaked-public internals — symbols public on Android but internal on the other SDKs are hidden, shrinking the surface to the intended contract. Breaking.
- Remove deprecated legacy ad-state/query APIs — the hooks and query-based entry points superseded by
KoahAdContextare removed (hard, no shim). Breaking. - Withdraw unreleased Category Rail and Photo Stack formats — removed before their first stable release; no released consumer loses API.
⚠️ Changed
- Sizeless opaque format ladder; drop the size/capability API — the server returns an opaque
formatname and slot bounds narrow the offer;KoahAdSize,KoahAdOptions, andsize-taking overloads are gone. Breaking. - Per-axis slot sizing (
KoahAxisSize) —KoahCard/KoahAdgainwidth/heightaxis parameters replacing the max-onlyoverrideMaxWidth/overrideMaxHeightknobs (now deprecated shims). The axis-sizing overloads also drop the rawmodifier: Modifierparameter in favor of a dedicatedpadding: moveModifier.padding(…)topadding = …, express width and height throughwidth/height, and wrap the card in your own composable for anything else you were applying (alignment, semantics). Breaking. - Sealed/discriminated
KoahAdResult(Filled / NoFill / Error) —requestAdreturns a closed three-case set instead of afilledflag; the result'sformatfield is gone. Breaking. - Logging config is a real
KoahLogLevelenum —NONE/ERROR/WARNING/INFO/DEBUGreplaces the booleandebugknob. Breaking. - Rename the preview ad request to
requestPreviewAd— previously folded into arequestAd(previewFormat:)overload. Breaking. - Raise Android
minSdkto 23. Breaking.
Added
- Public
KoahSampleAdfamily for fixture / preview rendering — a hand-constructable mirror of the internal ad-content model for previews, demo galleries, and snapshot fixtures. card_text_mdtext-length budget + clip-driven derender — the client sends a per-slot text budget and derenders (SlotTooSmall) instead of clipping.- Gender and household-income targeting —
setGender/setIncomeBracketupload as their own attribute dimensions alongside age.
Version 0.2.1 (June 23, 2026)
Highlights
- Ad disclaimers. When an ad carries disclaimer text,
KoahCardnow shows an info (ⓘ) affordance after the "Sponsored" label that opens a disclaimer bottom sheet. Surfaced on the model as the new nullableKoahAd.disclaimer; the affordance renders automatically with no integration changes.
Improvements
- Advertiser icons render more gracefully. Icons now show a grey skeleton while loading and fall back to a bundled default advertiser mark when there's no icon URL or the image fails to load, instead of rendering an empty space.
/client/infouploads are debounced. Device info is now uploaded only when it changes since the last successful send (via a new internal client-info manager), instead of on every launch — fewer redundant network calls.
Version 0.2.0 (June 5, 2026)
Highlights
- AdMob mediation plumbing is finalized. This release lands the core internals the new
koah-android-admobcompanion adapter links against, so the adapter can ship for the first time. (0.1.0 introduced the public AdMob mediation story; the adapter itself depends on the request-path changes in this release.)
Improvements
- Reworked the internal ad-request path used by AdMob mediation: ad-context extras are now encoded/decoded through
KoahAdRequestPayload, andKoah.fetchAdMobAdtakes a single request value.
Version 0.1.0 (June 4, 2026)
Highlights
- Pixel-precise ad sizing with
KoahDimensions.requestAd/prefetchAdand the card composables now take explicit slot constraints — passoverrideMaxWidth/overrideMaxHeight(in dp) onKoahCard/KoahAd, or aKoahDimensions(maxWidth, maxHeight)value on the request, to bound an ad to your layout. Each axis is independent; omit both for an unbounded slot. Replaces the coarse t-shirt-size buckets with exact dimensions. - AdMob mediation via the new
koah-android-admobcompanion library. A separatecom.koahlabs:koah-android-admobartifact renders Koah creatives inside Google AdMob native ad slots, so publishers already on AdMob can serve Koah ads through their existing mediation stack.
Improvements
sizedeprecated in favor of dimensions. TheKoahAdSizet-shirt-bucket parameter onrequestAd/prefetchAd/ the card composables, andKoahAdOptions.size, now emit a deprecation warning. Existing call sites keep compiling — migrate tooverrideMaxWidth/overrideMaxHeight(or omit for unbounded).sizewill be removed in a future release.- Unified impression & visibility tracking. Internal visibility bookkeeping now follows the same gating semantics as iOS, Flutter, and React Native, so impression and viewed-event timing for partially-occluded or de-rendered cards is consistent across all SDKs.
Version 0.0.17 (May 29, 2026)
Highlights
- Ad report flow. Tapping the new ellipsis in the medium ad-card header opens an M3
ModalBottomSheet(About this ad→Report this adwith five radio reasons + Submit) that posts toPOST /k/report. No new public API surface and no opt-in — the affordance ships on every standardKoahCard. Sheet auto-adapts to system light/dark via the ambientKoahTheme. - Optional
slotparameter.Koah.instance.requestAd(adContext, size, cacheKey, slot)andprefetchAd(...)now accept an optionalslot: String?that surfaces in matching and reporting. Lets a single page tag multiple distinct ad placements without colliding on the cache key or muddying analytics. previewFormatfor publisher format previews. NewKoah.instance.previewFormat(...)returns a deterministic sample creative for a given format (SMALL/MEDIUM/EXPANDABLE/POLL), so publishers can wire their preview UIs without depending on live fill.- Optional
experimentTag. NewexperimentTag: String?parameter onrequestAd/prefetchAdis forwarded with every ad request, letting publishers split-test creatives or surface variants without piggy-backing on the cache key. - Small card trailing chevron. Compact small-card variant now renders a trailing
›chevron, reinforcing that the whole card is one tap target and matching the web SDK. - Poll CTA with animated reveal. Clickable poll CTA reveals the post-vote state with a word-by-word blur-reveal animation gated on 50% visibility, matching the expandable format's reveal pattern.
Improvements
adTextremoved from publisher-facing fill events. Tracking events no longer leak ad copy to the publisher's analytics surface.
Version 0.0.16 (May 12, 2026)
Highlights
- Unified
requestAdAPI. NewKoah.requestAd(adContext, size, cacheKey),Koah.prefetchAd(adContext, size, cacheKey), andKoah.cancelPrefetchAd(cacheKey), plus a discriminatedKoahAdContext(Conversation/Article/Feed/Static) and aKoahAdResult(filled, fromCache, format)return type. NewKoahCard(adContext = ..., cacheKey = ...)andKoahAd(adContext = ..., cacheKey = ...)overloads route through the same path. Migration: the pre-0.0.16Koah.fetchAd/prefetch/resolveAd/cancelPrefetchentry points and the v1KoahCard/KoahAdoverloads still work but emit deprecation warnings; new code should adopt the unified API. KoahThemestyling API (breaking). Replaces the previous 13-knobKoahCardStylewith a tight 4-knobKoahThemeapplied viaProvideKoahTheme. Knobs:colorScheme(LIGHT/DARK/AUTO),accentColor(defaults to#0D0D0D; on-accent text is auto-contrasted via WCAG luminance),fontFamily(nullinherits from the host app), andcornerRadius(default19.dp).ProvideKoahThemecalls nest, so subtree overrides work naturally.- Borderless
KoahAdcomposable. New chrome-less variant that renders inline in a chat row, comment cell, or any host surface that already provides framing. Same props and event behavior asKoahCard. - Expandable and Poll ad formats. Expandable renders a clipped preview that blur-reveals word-by-word into the full body on tap (gated on 50% visibility). Poll renders an interactive multi-choice prompt with server-tracked option events. Both are returned by the existing
requestAdcall when the server picks them — no client-side opt-in. - Compact small card. New
KoahAdSize.SMALLspec: 14dp padding, ~19dp corners, thin outline, whole-card tap target. - Post-click survey. When the server attaches
on_click_actions: [{ type: "survey" }]to an ad, tapping the CTA shows a survey card (question + pill options + countdown auto-navigate) that crossfades in-place before opening the ad link. Forward-compatible: unknown action types silently no-op.
Improvements
- Strict size matching.
KoahAdOptions.sizeis enforced as a hard match against the server'sad.size. The SDK also declares the formats it can render on every request, so the server stops returning formats this client can't draw. - Production-key debug warning. When
debug = truebut the configuredpublisherIdlooks like a production key, the SDK logs a clear warning on no-fill so integrators don't silently think their staging setup is broken. - Cross-platform
/client/infoparity. Android now sends the same device-info superset as iOS, Flutter, and React Native, so backend personalization decisions are consistent across platforms.
About versions 0.0.10–0.0.15
These versions were published to Maven Central without curated changelog entries. The 0.0.16 entry above is the consolidated changelog covering everything that landed since 0.0.9.
Version 0.0.9 (September 11, 2025)
- Added browser warmup for improved speed when opening ad links in the in-app browser
- Added optional
conversationIDparameter for enhanced tracking and analytics
Version 0.0.8 (September 5, 2025)
- Added new email form fill ad format for lead capture directly within ads
- Introduced
Koah.identify()andKoah.reset()methods for user identification and improved ad targeting - Email auto-fill support for identified users to increase conversion rates
- Added 7 new event types for email lead forms:
EmailLeadFormOpened,EmailLeadCaptured,EmailLeadFormPrematurelyDismissed,EmailLeadValidationFailedEmailAutocompleteLeadFormOpened,EmailAutocompleteLeadCaptured,EmailAutocompleteFormPrematurelyDismissed
- Added
formFieldBorderColorstyling option for customizing form input field borders
Version 0.0.7 (July 17, 2025)
- Updated
KoahEvent.AdServedfrom object to data class withadTextproperty for accessing served ad content - Added new
KoahEvent.AdClickedevent to track user interactions with ads - Improved event handling examples to demonstrate all four event types
Version 0.0.6 (June 19, 2025)
- Breaking Change: Deprecated
onImpressioncallback in favor of newonEventsystem - Added
KoahEventsealed class with four event types:NoAdFill: Emitted when no ad is available to fill the requestAdServed: Emitted when an ad is successfully served and ready to displayImpressionTracked: Emitted when an ad impression has been tracked
- Enhanced event tracking capabilities for better analytics integration
- Backward compatibility maintained for existing
onImpressionimplementations
Was this helpful?