feat(admob): add next-gen interstitial ad tracking - #3985
Merged
Conversation
This was referenced Aug 17, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## next-gen-admob-sdk #3985 +/- ##
===================================================
Coverage 82.99% 82.99%
===================================================
Files 437 437
Lines 17893 17893
Branches 2684 2684
===================================================
Hits 14851 14851
Misses 2148 2148
Partials 894 894 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
polmiro
force-pushed
the
add-next-gen-admob-event-tracking
branch
2 times, most recently
from
August 18, 2026 13:38
2e4006f to
2dec429
Compare
polmiro
force-pushed
the
add-next-gen-admob-event-tracking
branch
from
August 18, 2026 15:01
2dec429 to
2e4006f
Compare
polmiro
force-pushed
the
add-next-gen-admob-interstitial
branch
from
August 18, 2026 15:08
7bc7fc7 to
df7a7a7
Compare
This was referenced Aug 19, 2026
polmiro
marked this pull request as ready for review
August 19, 2026 10:02
This was referenced Aug 19, 2026
polmiro
force-pushed
the
add-next-gen-admob-event-tracking
branch
from
August 19, 2026 11:33
b1c6581 to
138ff80
Compare
An error occurred while trying to automatically change base from
add-next-gen-admob-event-tracking
to
next-gen-admob-sdk
August 19, 2026 11:51
polmiro
force-pushed
the
add-next-gen-admob-interstitial
branch
from
August 19, 2026 12:12
c0042ff to
8320171
Compare
polmiro
changed the base branch from
add-next-gen-admob-event-tracking
to
next-gen-admob-sdk
August 19, 2026 12:15
polmiro
force-pushed
the
add-next-gen-admob-interstitial
branch
2 times, most recently
from
August 19, 2026 15:55
bba2dc8 to
f5c23a1
Compare
polmiro
added a commit
that referenced
this pull request
Aug 19, 2026
…ide (#4034) ### Motivation Two related bits of drift in the next-gen module. **Log messages were inline literals.** The rest of the SDK keeps them in a strings object — `purchases` has fifteen under `com.revenuecat.purchases.strings`, and `feature/galaxy` has `GalaxyStrings`. The two AdMob adapters are the exception, and legacy only half follows it: `RewardVerificationStrings` holds a single constant while six other call sites inline their text. **The placement override is copy-pasted per format.** Every full-screen format resolves a show-time override the same way — cast `adEventCallback` to the tracking wrapper, assign `placement`, warn when the cast fails. There are six copies across five branches (`InterstitialAdExtensions.kt` #3985, `RewardedAdExtensions.kt` #4011, `RewardedInterstitialAdExtensions.kt` #4012, `AppOpenAdExtensions.kt` #4013, and two in `RewardVerificationExtensions.kt` #4017), and the warning text already differs between them. Nothing pulls those copies back together. Because they live in **separate files**, git merges every one cleanly when those branches land here, and the divergent wording survives silently — there is no conflict to catch it. Worth noting the legacy adapter already routes its four formats through a single `applyPlacementOverride`. Next-gen dropped that shape; this restores it rather than inventing something new, and keeps the same name. ### Description Two commits: 1. **`AdMobNextGenStrings`** — holds the module's three log messages (the not-configured warning, the tracking-failure message, and the new placement-override warning). Existing `TrackIfConfigured` call sites route through it. 2. **`AdEventCallback?.applyPlacementOverride(placement)`** — holds the cast condition and the warning. All six call sites collapse to one line: ```kotlin adEventCallback.applyPlacementOverride(placement) ``` The receiver is the shared `AdEventCallback` supertype rather than each format's callback interface — every format callback (`RewardedAdEventCallback`, `InterstitialAdEventCallback`, `AppOpenAdEventCallback`, `RewardedInterstitialAdEventCallback`) extends it, and the per-format cast was never load-bearing: an ad's `adEventCallback` can only ever hold its own format's wrapper. The KDoc also records that passing `null` clears the load-time placement, which was previously documented only per-format. ### Adoption The helper is intentionally unused here — the extensions that call it live on the format branches, not on this base. Once this merges, each format PR swaps its inline block for the one-liner as it rebases. Verified that an unused `internal` function passes `detektAll` on this branch, so this lands green on its own. `TrackIfConfigured.kt` is byte-identical across all ten format/preload/SSV branches, so moving its strings conflicts with none of them. ### Validation - `./gradlew :feature:admob-next-gen:testDefaultsDebugUnitTest` - `./gradlew detektAll` - `./scripts/api-check.sh` — no public API change; both additions are `internal` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Internal refactor of logging and duplicated placement logic with no public API or runtime behavior change beyond unified warning text. > > **Overview** > Introduces **`AdMobNextGenStrings`** with three shared log messages (Purchases not configured, tracking failure, placement override ignored) and routes **`trackIfConfigured`** through them instead of inline literals. > > Adds **`AdEventCallback?.applyPlacementOverride(placement)`** so show-time placement override logic (cast to `TrackingAdEventCallback`, assign placement, warn on failure) lives in one place, aligned with the legacy AdMob adapter. The helper is **`internal`** and not wired from format extension files on this branch; those branches are expected to replace duplicated blocks with a single call after merge. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d9a56d2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
AlvaroBrey
reviewed
Aug 20, 2026
Public API changes in feature:admob-next-gen (7 new declarations)+ public final class AdTrackerAdMobExtensionsKt
+ method @KotlinOnly @com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI @kotlin.jvm.JvmSynthetic public static void loadAndTrackInterstitialAd(com.revenuecat.purchases.ads.events.AdT…
+ method @KotlinOnly @com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI @kotlin.jvm.JvmSynthetic public static suspend Object? loadAndTrackInterstitialAd(com.revenuecat.purchases.ads…
+ method @KotlinOnly @com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI @kotlin.jvm.JvmSynthetic public static void loadAndTrackInterstitialAdFromResponse(com.revenuecat.purchases.ad…
+ public final class InterstitialAdExtensionsKt
+ method @KotlinOnly @com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI @kotlin.jvm.JvmSynthetic public static void setTrackingAdEventCallback(com.google.android.libraries.ads.mobile…
+ method @KotlinOnly @com.revenuecat.purchases.ExperimentalPreviewRevenueCatPurchasesAPI @kotlin.jvm.JvmSynthetic public static void show(com.google.android.libraries.ads.mobile.sdk.interstitial.Inte…Generated by 🚫 Danger |
The flow tests asserted callback wiring and delegation but never installed a Purchases singleton, so trackIfConfigured short-circuited on every path and the load-time tracking arguments went unchecked. The wrapper classes are covered in TrackingAdEventCallbackTest, but nothing pinned what the banner and interstitial entry points hand to TrackingAdLoadCallback: swapping AdFormat.BANNER for INTERSTITIAL, dropping the placement, or not reading adUnitId off the request all kept the suite green.
The warning named the least likely cause. It fires whenever the ad was not loaded through loadAndTrack, which is usually because the ad was loaded with Google's own API rather than because someone reassigned adEventCallback, so it sent readers looking for a reassignment that never happened. The KDoc also only promised that the show-time placement takes precedence. It did not say that passing null clears the placement recorded at load time, which is easy to hit because the parameter has no default and the SDK's own show is the only way to keep the load-time value.
The base branch now holds applyPlacementOverride, so drop this format's copy of the cast, the assignment and the warning in favour of the shared one. That leaves a single definition of the message rather than one per format.
polmiro
force-pushed
the
add-next-gen-admob-interstitial
branch
from
August 20, 2026 13:45
d26145a to
eabdf12
Compare
AlvaroBrey
approved these changes
Aug 24, 2026
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Expose Google Mobile Ads Next-Gen interstitial loading and event tracking through a public RevenueCat API.
This PR consumes the load- and event-tracking building blocks from #3955 and #3957 and wires them into the first format-specific integration.
Description
AdTracker.loadAndTrackInterstitialAdAPIs for request-based loading through Google's Next-GenAdRequestAPI.loadAndTrackInterstitialAdFromResponsefor server-to-server ad responses, with an explicit ad unit ID for attribution.InterstitialAd.show(activity, placement)for overriding the tracking placement when the display location is only known at show time.setTrackingAdEventCallbackso applications can replace their callback without removing RevenueCat's wrapper.Tracking behavior
The load-time placement is used for load events and as the default for subsequent lifecycle events. A placement passed to
showtakes precedence for display, click, and revenue events.Full-screen display is tracked from
onAdShowedFullScreenContent; impressions are not also counted as displays. RevenueCat tracking runs before application callbacks.Assigning
adEventCallbackdirectly after a tracked load replaces RevenueCat's wrapper. Applications should provide the callback while loading or usesetTrackingAdEventCallback.If
show(activity, placement)is called after the callback was manually replaced, the ad is still shown but the placement override is ignored and a warning is logged.Note
Medium Risk
New analytics surface on ad load/show paths; incorrect callback replacement or placement override could skew attribution, but changes are additive with documented guardrails.
Overview
Adds public RevenueCat tracking for Google Mobile Ads Next-Gen interstitial ads: load helpers on
AdTracker, show-time placement override, and safe callback replacement without dropping the tracking wrapper.Load paths: callback-based
loadAndTrackInterstitialAd(request and server-to-serverloadAndTrackInterstitialAdFromResponsewith explicitadUnitId), plus a suspending overload that returns Google's unchangedAdLoadResult. Successful loads install lifecycle/paid tracking before the app callback or return; failures still emit RevenueCat load-failure events with optionalplacement.Show & callbacks:
InterstitialAd.show(activity, placement)overrides placement for display/click/revenue events;setTrackingAdEventCallbackupdates the forwarded delegate when the RC wrapper is present. README,api.txt, and tests document the experimental API and wiring.Reviewed by Cursor Bugbot for commit e6402b9. Bugbot is set up for automated code reviews on this repo. Configure here.