ποΈ Toggles & Feature Flags
Flip these to test different scenarios. Remote Config values are entered as String in Firebase (booleans are the literal text true/false) and take effect on next app launch. Code flags require a rebuild.
Banner ads β Remote Config
| Toggle | Type | Default | Effect |
|---|---|---|---|
custom_banner_master_is_enabled_ios |
Remote Config (String) | true | Master switch for the custom (house) banner. Default true β custom banner shows whenever AdMob has no ad β slot is never blank. Set to "false" β AdMob-only (slot is blank on no-fill). |
custom_banner_force_only_ios |
Remote Config (String) | false | "true" β show only the custom banner and skip AdMob entirely (house-promo mode). "false"/unset β normal AdMob-first behavior. |
custom_banner_url_<lang>_ioscustom_banner_default_url_ios |
Remote Config (String) | empty | Image URL for the custom banner (per-language, with default fallback). Empty β bundled asset BannerAdsUpgradePro_<lang> ("Upgrade to Pro+"). |
custom_banner_cta_url_<lang>_ioscustom_banner_cta_url_default_ios |
Remote Config (String) | empty | Where tapping the custom banner goes. Empty β opens the in-app Pro paywall. |
Recognized <lang> suffixes: en, id, ar, hi, fr, zh (anything else β en).
Ad units β code flag
| Toggle | Where | Default | Effect |
|---|---|---|---|
LQRAdUnitId.useTestAdUnitIds |
LQRAppConstant.swift |
false | Set to true β every ad unit resolves to Google's official test IDs (guaranteed-fill "Test Ad"). For QA/dev only. β οΈ Never ship true (zero revenue). Simulators serve test ads automatically even when this is false. |
β’ Normal (default): master=true, force_only=false β real AdMob ads where available, custom banner where not (never blank).
β’ House-promo: force_only=
true β only the custom banner, no AdMob.β’ AdMob-only: master=
false β no custom banner (slot blank on no-fill).β’ Force test ads: useTestAdUnitIds=
true (rebuild) β test ads fill everywhere.
π§ How to change a Remote Config toggle (Firebase)
All the Remote Config toggles above are changed in the Firebase Console β no app update needed. Steps:
- Open Firebase Console β pick the LearnQuran / LQ Tajwid project.
- Left sidebar β Run β Remote Config.
- Find the parameter (e.g.
custom_banner_master_is_enabled_ios). If it doesn't exist, click Add parameter and use the exact key name. - Set Data type = String and enter the value as text β for booleans type the literal
trueorfalse(not a Boolean type), for numbers type the digits. - Click Save, then Publish changes (top right). Nothing applies until you Publish.
- On the device: force-quit and relaunch the app to pull the new values. You may need to relaunch twice (one launch fetches, the next applies).
- Fetch throttling β Remote Config caches values (a minimum fetch interval). If a change won't appear, fully delete & reinstall the app to clear the cache, then relaunch.
- Conditions β make sure you edited the value that applies to your test device (the default value, or the matching condition for your platform/audience), not a non-matching condition.
- Before first fetch, the app uses bundled defaults from
remote_config_defaults.plist(e.g.custom_banner_master_is_enabled_ios = true). A published Remote Config value overrides that default after fetch + relaunch.
Don't have Firebase Console access? Ask the dev team to publish the value, or test the same behavior locally via the code defaults / the useTestAdUnitIds flag.
πΊ How to test ads correctly
- Simulator auto-serves AdMob "Test Ad" creatives for the real unit IDs β good for layout/flow, not for real fill.
- Real device, production ads: use TestFlight or a debug build with
useTestAdUnitIds = false. - Don't hammer ads on one device. Rapidly opening many ad screens can get the device ad-limited by AdMob β you'll see
"No ad to show"for a while. It resets on its own (hoursβa day). To avoid this during QA, register your device as a test device or setuseTestAdUnitIds = true. - Real-ad fill is not 100% β AdMob may return "No ad to show" anytime. That's expected; the custom banner covers it (never blank).
β PR #46 β Onboarding redesign + Banner ads + v6.7.17 fixes
feat/onboarding-redesign β main Three areas: the new onboarding intro flow; banner-ads reliability (real AdMob where available, custom fallback that's never blank); and the v6.7.17 bug-fix batch β lesson audio, quiz Back button, iPad play-button size (section C).
Setup
- Fresh install (for onboarding) + an upgrade-over-existing pass.
- Free account (ads) and Pro/Pro+ account (no ads).
- Portrait + landscape; languages EN, ID, AR (RTL), and one of HI/FR/ZH.
A. Onboarding redesign
B. Banner ads
Expected: real AdMob banner where an ad is available; the custom "Upgrade to Pro+" banner where AdMob has no ad. Never blank.
force_only=true β only custom; master=false β AdMob-only; useTestAdUnitIds=true β test ads everywhere.C. Lesson audio & quiz interaction fixes v6.7.17
Fixes for the v6.7.17 QA reports: silent audio in Bacaan (recitation) and Pilihan Ganda (multiple-choice) on advanced lessons, an unresponsive Back button between questions, and an oversized play button on iPad.
β’ Audio is download-gated β the bug only appears once a lesson's content is actually downloaded. Download lessons 12β20 first.
β’ The bug was triggered by Arabic letters in advanced-lesson titles, so also test the app in Arabic and/or Indonesian, not only English.
β’ Use a real device with downloaded content β the simulator can't fetch lesson audio, so these audio cases can't be reproduced there.
Regression
- App launch, lesson list, navigation normal; no crash opening Course Menu.
- Interstitial ads after test/practice still appear (free user).
- Language switch mid-session doesn't break banners or onboarding.
Sign-off
| Area | Pass/Fail | Device / OS | Notes |
|---|---|---|---|
| Onboarding (A1βA6) | |||
| Banners (B1βB7) | |||
| Lesson audio (C1βC4) | |||
| Quiz Back button (C5βC6) | |||
| Play button size (C7βC8) | |||
| Regression |
PR #47 β TBD
Add the test plan for PR #47 here when it opens: scope, setup, test cases, relevant toggles, sign-off.
PR #48 β TBD
Add the test plan for PR #48 here when it opens.