13 KiB
| name | description |
|---|---|
| review-rejections | Triage and answer an App Store or Google Play rejection, policy warning or strike for a mobile app or game - decide fix / clarify / push back / appeal, write a short Resolution Center reply, and map the message to the usual guidelines (Apple 2.1, 2.3, 3.1.1, 4.2, 4.3, 5.1.1, 5.1.2, privacy label mismatch; Play Data safety mismatch, disruptive ads, Families, strikes and appeals). Use when the user pastes a rejection or policy email, an update is "Rejected" / "Metadata Rejected", or Play Console shows a policy issue. |
Review rejections and policy issues
Read the full message first (App Store Connect > the app > App Review > the submission; Play Console > Policy status / Inbox). Quote the guideline number and the reviewer's exact sentence back to the owner before proposing anything. Never suggest hiding behaviour from reviewers, different builds for review, fake accounts or other manipulative tactics: they turn a rejection into an account termination.
0. Before the next submission: storebound scan
storebound scan (MCP scan, read-only, offline) reads the project itself and lists the rejections the files can
prove, with guideline, evidence (file:line), fix and skill: 2.1(a) demo account and placeholder text, 5.1.1(v) account
deletion, 4.8 Sign in with Apple, 3.1.1 Restore Purchases and outside payment, 3.1.2 subscription info, 5.1.2 ATT,
5.1.1(ii) purpose strings, 5.1.1(i) privacy policy link, privacy manifest (ITMS-91053 / 91061), 2.3.10 other
platforms, 2.3.7 keywords, 2.3.8 "For Kids", 4.2 web wrappers, 2.5.1 UIWebView and private URL schemes, 2.5.5 IPv6,
ATS, export compliance, 1.3 kids ads, 5.6.1 / 3.2.2(x) review prompts, privacy label vs SDKs. On Google Play: target
SDK, delete-account URL, App access, package name, the restricted permissions and their Console declarations
(background location, photo / video, All files access, AccessibilityService, REQUEST_INSTALL_PACKAGES, Health Connect,
full-screen intent, VpnService, foreground services, exact alarms, QUERY_ALL_PACKAGES, SMS / call log), prominent
disclosure and the in-app privacy policy (User Data), Data safety vs the SDKs' disclosures, Families (certified ad SDKs,
AD_ID, location) from play.targetAges, the AD_ID permission, 16 KB page sizes (Unity, React Native, NDK, AGP, prebuilt
.so), the closed-testing requirement of new personal accounts, Play metadata (title length, emoji, caps, claims,
keyword repetition, other apps), interstitials at launch, payments outside Play Billing and brand names in the package
(low "check"). When the project was built locally it also reads the merged manifest under build/intermediates. After
a rejection, run it too: the same cause often hides elsewhere. A finding the owner decided is fine goes
into scan.ignore with the reason (never silence one yourself).
Checked at review, not by scan (check these yourself in the app and the listing): crashes and hangs on the reviewer's device (2.1; store-health),
links that are dead at review time (storebound validate checks the configured URLs), screenshots and description
that do not match the app (2.3, store-screenshots), poor or unfinished UI (4.0), "too simple" and spam / template
apps (4.2, 4.3; portfolio-originality), IAPs that fail in the sandbox (2.1(b), store-iap-setup), privacy policy
content (5.1.1(i), privacy-policy), local law (5.2). Play: whether a restricted permission serves the core purpose
(the declaration and its video decide), the wording and timing of a prominent disclosure, ad placements in Unity /
Flutter / React Native code, the Health apps declaration, alignment inside prebuilt .so files.
1. Triage (pick one, say why)
| route | when | what you do |
|---|---|---|
| Fix | the reviewer is right (crash, missing restore button, wrong label) | change the app / metadata, resubmit, reply what changed |
| Clarify | the feature exists but the reviewer did not find it, or misread it | reply with exact steps / a video link; no new build if nothing changed |
| Push back | the guideline does not apply, with a concrete reason | short factual reply quoting the guideline text; offer a call |
| Appeal | a clarification was rejected and you still believe it complies | Apple: App Review Board appeal form; Play: the appeal form linked from the notice |
Start with Fix or Clarify; Push back only with evidence; Appeal last. Always ask the owner before sending anything.
Apple: resubmit a fixed build (Invalid Binary, crash, ...)
The rejected submission stays open with UNRESOLVED_ISSUES and keeps its items (the version, REJECTED, and its
in-app purchases). Resubmit that same submission; never create a second one next to it (Apple then answers 409
ITEM_PART_OF_ANOTHER_SUBMISSION).
- Upload the fixed build and note its number (
storebound apple upload,apple encryptionif it asks). storebound apple status: the submission with UNRESOLVED_ISSUES, its items and their states.storebound apple resubmit --build <n>(dry run without--yes): the plan table shows the build to attach, the submission reused, every item in it already or added, which REJECTED items are marked resolved, and the submit. An app with a macOS (tvOS, visionOS) version too: it picks the platform whose version was rejected, and asks for--platform ios|macos|...when both were (pitfall 79).- The owner's yes, then
storebound apple resubmit --build <n> --yes: build n is attached by its number, missing items go in, the REJECTED version item is marked resolved (PATCH reviewSubmissionItems/{id}resolved: true), then it submits. Apple answers every submit with "Version is not ready to be submitted yet" (and the console's Resubmit button stays disabled) while any item is still REJECTED; the command reads the items again on that answer and stops at once naming the item instead of retrying. A REJECTED in-app purchase or subscription item is marked resolved only with--resolve-iaps, once what App Review asked for is fixed. With nothing left REJECTED, "not ready" is retried with backoff (normal for a few minutes after a build is attached; it gives up after 10 minutes and a re-run continues). An empty draft next to the submission (0 items) cannot be canceled and is harmless: leave it. - Reply in the Resolution Center what changed (template below), then
storebound apple status --wait-review.
2. Reply template (Resolution Center / appeal, under 200 words)
Hello, thank you for the review.
Regarding Guideline <n> (<reviewer's point in one line>):
<What we changed in build <number>> | <Where the feature is: Home > Settings > Restore Purchases>
<One sentence of evidence: screenshot / video link, or the guideline sentence that applies>
<If a new build:> Build <number> is attached to this submission.
Happy to clarify anything else.
Plain, polite, specific; one guideline per paragraph; no blame, no threats, no "other apps do it".
3. Apple guidelines apps and games hit most
- 2.1 App completeness: crash on launch / during review (check the crash log in the message, test the review
device class and OS), placeholder text or art, broken links, IAPs not working in the sandbox (Paid Apps agreement
active? products READY_TO_SUBMIT and in the same submission?), features behind a login without a demo
account (
review-accessskill: demo account in.storebound/credentials.json,storebound apple review-detailssends it). - 2.3 Accurate metadata: screenshots must show the real app (for a game: real gameplay); no prices, no "free" claims for paid items, no other platforms' UI; keywords without competitor names; age rating answers that match the content.
- 2.3.10 Accurate Metadata (other platforms): "Android", "Google Play", "Google Play Games" or another store in
any App Store text, often a What's New copied from notes shared with Play (store-pitfalls 77). Fix: remove the
lines (tag shared notes
[play]/[apple],storebound whats-new apply),storebound checkmust show noother platformblocker, push withapple listing --version x.y.z, reply "removed the references to other platforms" and resubmit. Play's mirror case is the Metadata policy (iOS, App Store, Game Center in Play text). - 2.3.1 Hidden or undocumented features (Play: Deceptive behavior): remote config, feature flags or a remote
paywall the review notes did not mention (
storebound scanruleremote-features, store-pitfalls 74). Fix: say in the notes which SDK changes what remotely; a business-model change needs a new review and a description update. - 3.1.1 In-app purchase: digital goods only through IAP; a visible Restore Purchases for non-consumables; no links to outside payment; loot boxes must show odds.
- 3.1.2 Subscriptions: the purchase screen shows title, length, price per period and what the user gets; links to
the privacy policy and the Terms of Use (EULA) in the app and in the metadata; free trial terms clear. See
store-subscriptions. - 4.2 Minimum functionality: a thin app (one screen, a tutorial-level loop) or a web wrapper. Add depth (for a game: levels, progression, offline play; for an app: native features, offline use, real utility). Explain what the user does in the notes.
- 4.3 Spam: too similar to your own or others' apps (same template, reskins). See
portfolio-originality; merge ideas instead of shipping near-duplicates. Hard to appeal without real differences. - 5.1.1 Data collection: privacy policy link in the listing and inside the app; only collect what you need;
account deletion in-app if you have accounts (5.1.1(v),
account-deletionskill). - 5.1.2 Data use / ATT: the App Tracking Transparency prompt before any tracking SDK reads the IDFA, a purpose string that says why, no incentive or pressure to allow, no tracking when denied.
- Privacy label mismatch: App Privacy must match what the SDKs really collect (ads / analytics SDK docs list it). Update the label in App Store Connect (UI) and Publish; no new build needed for label-only fixes.
4. Google Play
- Data safety mismatch: Play scans the SDKs in your AAB. Fix the form (
storebound play data-safety) to include what the SDKs collect, or remove the SDK; then resubmit from Publishing overview. - Ads policy / disruptive ads: no interstitials at launch, on exit or mid-gameplay; close buttons visible; rewarded ads only opt-in. Ads must not imitate system UI.
- Families: if the target audience includes children, only Families Self-Certified Ads SDKs (answer/9859768;
AppLovin left the program), no advertising ID in child-only apps (remove AD_ID with tools:node="remove"), no location
in child-only apps, a neutral age screen for mixed audiences. If the app is not for children, make sure store art and
the target audience form say so. Set
play.targetAgessostorebound scanchecks it. - Sensitive permissions (background location, photo / video, All files access, AccessibilityService, install packages, Health Connect, full-screen intent, VpnService, SMS / call log, QUERY_ALL_PACKAGES): the rejection names the permission. Either remove it from the merged manifest (an SDK may add it: tools:node="remove") or fill the App content declaration with the core feature and a short video that shows the prominent disclosure and the runtime prompt.
- Prominent disclosure / privacy policy (User Data): an in-app disclosure right before the permission prompt that names the data and its use, an affirmative accept, and a privacy policy linked inside the app and in Play Console.
- 16 KB page sizes: Play Console flags native libraries that are not 16 KB aligned; from 2027-02-01 such updates cannot be released. Update Unity / React Native / NDK / AGP (scan names the version) and rebuild.
- Metadata: title 30 characters or less, no emoji, ALL CAPS, "best / #1 / free / new / sale" in the title, no
keyword stuffing or unrelated keywords, no other apps' names (
aso-basics). - Impersonation: a name, icon or package that suggests another brand; rename (the package cannot change, so a new app may be needed) or show the written permission in the appeal.
- Strikes and suspensions: one policy strike affects the account; repeated strikes can terminate it. Fix first, then appeal from the notice with the change described. Do not upload the same app under a new package to dodge it.
- Rejected updates: the previous version stays live; fix and send changes for review again.
5. After sending
storebound apple status --wait-review(exit 0 approved, 1 rejected, 7 timeout) orstorebound play status.- Write down guideline, cause and fix in the project's docs so the next app does not repeat it.