Files
pluriwave/openspec/changes/iap-freemium-unlock/specs/ad-display/spec.md
T
FreeTLab aa0b242374 feat(iap): add freemium unlock via one-time in-app purchase
Adds a permanent, non-consumable premium unlock (EstadoEntitlement +
PuertoCompras/ServicioComprasPlayBilling) that removes ads and unlocks
alarm vacations, alarms past a 5-alarm free cap, recording start, and
full Android Auto browsing. The phone equalizer stays free for everyone.

- Entitlement is prefs-backed (compra_premium_v1), fail-open, and
  resolvable headlessly via esPremiumPersistido() for the Android Auto
  audio handler, which registers before runApp.
- Android Auto reduced mode keeps the real root folder labels for free
  users; browsing into any of them (and playFromMediaId/playFromSearch/
  skipToNext/skipToPrevious) is blocked at the getChildren/servicio_audio
  choke points, with a locked "Función Premium" item as the backstop.
  Current-station play/pause/stop stays untouched. A free -> premium
  transition actively invalidates the head unit's cached browse tree.
- Ads (top banner + capped interstitial before adding a station or an
  alarm) are gated behind entitlement via ServicioAnuncios, using
  official Google test ad unit IDs pending AdMob provisioning.
- Alarm cap UX shows an explanatory message with a secondary unlock
  action rather than a bare paywall jump; existing data is grandfathered.
- 4 new localization keys translated across all 13 supported locales.

Co-located tests use strict TDD (RED test before implementation) for
every new pure-logic unit; full existing suite passes unchanged.
2026-08-10 20:37:07 +02:00

3.3 KiB

Ad Display Specification

Purpose

Define where and when google_mobile_ads renders for free-tier users only: a persistent top banner, plus a capped interstitial before two specific add actions. Ads MUST be entirely absent for premium users.

Requirements

Requirement: Persistent Top Banner, Never Overlapping Content

Free-tier users MUST see a persistent banner anchored at the TOP of the app (not bottom), laid out so it reserves its own space and never overlaps, covers, or displaces existing UI on any of the 5 tabs. Premium users MUST see no banner and no reserved space for it.

Scenario: Free user on any tab

  • GIVEN a free-tier user
  • WHEN they view any of the 5 tabs
  • THEN the top banner is visible and all existing content remains fully visible and reachable, none hidden behind it

Scenario: Premium user

  • GIVEN a premium user
  • WHEN they view any tab
  • THEN no banner and no reserved banner space is shown

Requirement: Interstitial Before Manual Station Add And Before Alarm Add

For free-tier users, a full-screen interstitial MUST show before completing exactly two actions: adding a station manually, and adding an alarm. It MUST fire on the action's natural transition (e.g. on confirm/save), never mid-form, and MUST NOT show for premium users.

Scenario: Free user adds a station manually

  • GIVEN a free-tier user completes the "add station manually" form
  • WHEN they confirm the add
  • THEN a full-screen interstitial shows once before/around that transition

Scenario: Free user adds an alarm

  • GIVEN a free-tier user under the 5-alarm cap completes the alarm-creation form
  • WHEN they save the new alarm
  • THEN a full-screen interstitial shows once before/around that transition

Scenario: Premium user performs either action

  • GIVEN a premium user
  • WHEN they add a station manually or add an alarm
  • THEN no interstitial shows

Requirement: Interstitial Frequency Cap

The system MUST enforce a session-scoped frequency cap on interstitials so that repeated adds in one session do not chain interstitials back-to-back on every single attempt.

Scenario: Rapid consecutive adds in one session

  • GIVEN a free-tier user adds several stations or alarms in quick succession within the same session
  • WHEN each add completes
  • THEN not every single add triggers a fresh interstitial — the frequency cap suppresses some per its configured spacing/count rule

Requirement: Interstitial Never Stacks With The Alarm-Cap Message

If an alarm-add attempt would trigger both the interstitial and the 5-alarm-cap message in the same tap, the alarm-cap message MUST take precedence and the interstitial MUST be suppressed for that attempt.

Scenario: Cap hit and interstitial would-be trigger collide

  • GIVEN a free-tier user already has 5 alarms
  • WHEN they tap "add" for a 6th alarm
  • THEN only the alarm-cap explanatory message appears, and no interstitial is shown for that same tap

Requirement: Ads Vanish Immediately On Purchase

Both the top banner and interstitial triggers MUST stop immediately upon successful purchase or restore, with no app restart required.

Scenario: Mid-session purchase

  • GIVEN a free-tier user with the banner visible completes a purchase
  • WHEN the purchase confirms
  • THEN the banner disappears immediately and subsequent adds trigger no interstitial, without restarting the app