Skip to content

Promote the paid app when no ad fills the slot - #138

Open
andiwand wants to merge 2 commits into
mainfrom
house-ad-fallback
Open

Promote the paid app when no ad fills the slot#138
andiwand wants to merge 2 commits into
mainfrom
house-ad-fallback

Conversation

@andiwand

@andiwand andiwand commented Aug 6, 2026

Copy link
Copy Markdown
Member

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

Headline (short form) Subline
A Support OpenDocument Reader (Support us) Get Pro — no ads, ever
B Read without ads ODR Pro — a one-time purchase
C Open source, kept free (Open source) Pro pays for it — and drops the ads

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 SKStoreProductViewController for 1452061743 — the paid app, which on iOS is at.tomtasche.reader; the same bundle id names the free app on Android.

Testing

Both schemes build, scripts/format.sh --check passes. 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 every viewWillAppear and activates a fresh set of constraints each time, including a hard 50 pt height on bannerView that competes with the bannerViewHeight outlet hideBannerView() sets to 0. Pre-existing, and worth its own PR.

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) <[email protected]>
Claude-Session: https://claude.ai/code/session_018Ens9c7zX2bDxXH8tUL4mG

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread OpenDocumentReader/HouseAdView.swift Outdated
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) <[email protected]>
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) <[email protected]>
Claude-Session: https://claude.ai/code/session_018Ens9c7zX2bDxXH8tUL4mG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant