Promote the paid app when no ad fills the slot - #138
Open
andiwand wants to merge 2 commits into
Open
Conversation
The banner slot collapsed whenever a request came back empty. It now shows our own promotion for ODR Pro instead, rotating through three creatives. This is our own view, not an ad: nothing is fetched, no identifier is read, no storage is touched. So it fills the slot on every no-fill path, including the one where the user refused consent and Google serves limited ads or nothing -- a house campaign in AdMob could not cover that case, since it only fills inside a successful ad request. One layout that sheds parts as the slot narrows, because the banner height is fixed by the ad slot and cannot grow: the subline goes below 360pt, the icon below 300pt, and the headline switches to a short form. Both labels truncate rather than wrap, so a long translation shortens instead of breaking the height. Taps open ODR Pro in an SKStoreProductViewController rather than sending the user out to the App Store app. Note the id is the *paid* app, which on iOS is at.tomtasche.reader -- the same bundle id names the free app on Android. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ens9c7zX2bDxXH8tUL4mG
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f4b237462
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
The house_ad_* keys exist only in en.lproj. NSLocalizedString resolves the bundle to the user's locale first and returns the *key* when it is missing there, so every one of the other 16 localizations would have shown "house_ad_support_short" in the banner rather than any readable copy. Passing value: gives each lookup its English text as the fallback, so an untranslated locale reads correctly and a translation still wins once one lands. Reported by Codex on #138. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ens9c7zX2bDxXH8tUL4mG
andiwand
added a commit
that referenced
this pull request
Aug 6, 2026
The privacy_* keys exist only in en.lproj. NSLocalizedString resolves the bundle to the user's locale first and returns the *key* when it is missing there, so the other 16 localizations would have shown "privacy" and "privacy_ad_choices" as the button and menu titles. Passing value: gives each lookup its English text as the fallback. Only the five new keys need it; cancel is already translated. Same defect Codex reported on #138. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ens9c7zX2bDxXH8tUL4mG
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.
The banner slot collapsed whenever an ad request came back empty. It now promotes ODR Pro instead, rotating through three creatives.
Why our own view rather than an AdMob house campaign: nothing is fetched, no identifier is read, no storage is touched — so it fills the slot even where the user refused consent and Google serves limited ads or nothing. A house campaign only fills inside a successful ad request, which is the case that already works.
Creatives
Round-robin via
UserDefaults, advanced once per presentation.Layout
The slot height is fixed by the ad size and cannot grow, so one layout sheds parts as it narrows: subline below 360 pt, icon below 300 pt, headline switches to its short form below 360 pt. Both labels truncate rather than wrap, so a long translation shortens instead of breaking the height. Icon and fonts step up in the 90 pt tablet slot.
Taps open
SKStoreProductViewControllerfor 1452061743 — the paid app, which on iOS isat.tomtasche.reader; the same bundle id names the free app on Android.Testing
Both schemes build,
scripts/format.sh --checkpasses. Not run on a simulator or device — the fallback needs a failed ad request to appear, so the layout at 320/393/728 pt is unverified at runtime.Worth checking when it is: no-fill on a small phone (short headline, no subline), on iPad (90 pt slot), and that a later successful ad hides the promotion again via
bannerViewDidReceiveAd.Noticed but not touched:
setVCconstraints()runs on everyviewWillAppearand activates a fresh set of constraints each time, including a hard 50 pt height onbannerViewthat competes with thebannerViewHeightoutlethideBannerView()sets to 0. Pre-existing, and worth its own PR.