Onboarding live apps without owner questions for what the stores and the code prove: storebound onboard imports the live products and subscriptions with USD / base prices (catalog diff clean), contact values, the App Review contact and demo account (credentials.json, masked), sign-in for review from Apple's review detail and auth code, and the account deletion page from the app's site; App Store keywords count characters (live fields up to 265 bytes accepted); validate accepts the 6.5-inch iPhone set and Play's default-language graphics fallback; Play Reporting API off gives the project's enable link and apps list falls back to local apps; accounts default <profile>; store-only apps (apps add --store --app-id) shown read-only in the desktop (pitfalls 43-52)
This commit is contained in:
parent
d2ce185441
commit
e5f148e534
55 changed files with 1648 additions and 158 deletions
|
|
@ -105,7 +105,7 @@ answers the compliance facts no file proves, all in one batch at the start.
|
|||
- Screenshot sizes: 6.9" 1320 x 2868 (`APP_IPHONE_67`) is required; 6.5" 1284 x 2778 (`APP_IPHONE_65`) recommended.
|
||||
PNG without alpha. Up to 10 per set. Apple processes uploads async; failures show as FAILED later.
|
||||
- App Store icon (1024) must have **no alpha channel** (`storebound icons` writes rgb24).
|
||||
- Limits: name 30, subtitle 30, promotional text 170, keywords 100 bytes (UTF-8, no spaces after commas),
|
||||
- Limits: name 30, subtitle 30, promotional text 170, keywords 100 characters (not bytes; no spaces after commas),
|
||||
description 4000. No "What's New" on a first version.
|
||||
- Guideline 5.1.1: the privacy policy link must be inside the app too (Settings > Privacy), not only in the listing.
|
||||
- `xcodebuild` with Capacitor needs a UTF-8 locale (`export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8`).
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ true; never use competitor or other apps' or games' names, "best / #1", or unrel
|
|||
`APPLE_ADS_*` credentials are set (`ads apple status` works), Apple Ads keyword suggestions. For each: relevance
|
||||
(in your own text +1, in competitor names +1), competition (top apps with the word in their name, "3/16"),
|
||||
popularity (Apple Ads' relative 0-100 score; "unknown" otherwise). Show the owner the proposed field (old -> new,
|
||||
bytes) and the left-out words with the reason. Only after a yes: `storebound aso suggest --locale en-US --write`
|
||||
characters) and the left-out words with the reason. Only after a yes: `storebound aso suggest --locale en-US --write`
|
||||
(terminal); it writes the field with a draft line above it. The owner reviews, deletes the line, runs
|
||||
`check --aso`. Never put words in that do not describe the app, other apps' names or brands.
|
||||
8. Review: `storebound aso audit` (MCP: `aso_audit`, offline) puts it together: keyword field findings, free keyword
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Local files only: nothing is sent to a store until the owner pushes with `apple
|
|||
Google Play title 30, short description 80, full description 4000. Shorten, never cut mid-word.
|
||||
- **Keywords are researched, not translated:** the words people in that market search for, comma separated,
|
||||
no spaces after commas, no duplicates, no words already in the name or subtitle (they are indexed anyway), no
|
||||
competitor or trademark names, 100 characters (bytes for CJK) used well (aso-basics).
|
||||
competitor or trademark names, 100 characters (characters in every script, not bytes) used well (aso-basics).
|
||||
- Subtitle and short description: the benefit in plain words, no "best / #1 / free", no prices, no other platforms.
|
||||
- Arabic and Hebrew stay RTL; Chinese / Japanese / Korean need no spaces in keywords.
|
||||
4. Optional provider hook (the owner's choice): `--translate "<command>"` runs the command once per field with the
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ Before pushing local texts over a console edit, pull the live ones and read the
|
|||
Both print the diff against `store/appstore.md` / `store/listing.md` and write only with `--write` (MCP:
|
||||
`apple_listing_pull` / `play_listing_pull` with dry_run false). New locales are appended as sections; a Play section
|
||||
shared by several codes is only changed when the store has the same text for all of them.
|
||||
- An app that was live before storebound: `storebound onboard` (then `--write`) imports the live products and
|
||||
subscriptions with their USD / base prices, contact values, the App Review contact and demo account, sign-in for
|
||||
review and the account deletion page; then `storebound catalog diff` is clean. Ask the owner only the questions it
|
||||
lists at the end.
|
||||
- `storebound catalog pull [--write]`: IAP and subscription titles / descriptions (Play: benefits) against the config.
|
||||
`storebound.config.ts` is never rewritten: `--write` saves `.storebound/pull/catalog.json` as a proposal; merge the
|
||||
listings into the config yourself (the agent), then `storebound check`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: store-pitfalls
|
||||
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - first: do the work, don't ask the owner for every step; store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins, duplicates from retries and re-runs, search ranks that are only a trend, no Play search API, Play's Create app form (no API, opener and submit share a name, Free is final), App Privacy purposes over-mapped (Play advertising is Third-Party Advertising only), an unknown console page, a signed-in console read as a sign-in page, console forms driven agent-first, stale Capacitor web assets, a declined flow step logged ok. Read it before any store task, and when a store command does something you did not expect.
|
||||
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - first: do the work, don't ask the owner for every step; store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in characters (not bytes), Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins, duplicates from retries and re-runs, search ranks that are only a trend, no Play search API, Play's Create app form (no API, opener and submit share a name, Free is final), App Privacy purposes over-mapped (Play advertising is Third-Party Advertising only), an unknown console page, a signed-in console read as a sign-in page, console forms driven agent-first, stale Capacitor web assets, a declined flow step logged ok. Read it before any store task, and when a store command does something you did not expect.
|
||||
---
|
||||
|
||||
# Store pitfalls
|
||||
|
|
@ -41,11 +41,8 @@ testers) and answers, in ONE batch at the start, only the facts no file proves (
|
|||
keep `app.name` for Play and the brand. Do not pick the suffix yourself.
|
||||
- **Guard:** `apple.name` overrides the App Store name.
|
||||
|
||||
## 4. Keyword field "too long" at fewer than 100 characters
|
||||
- **Symptom:** App Store Connect rejects keywords that look short enough, mostly in Turkish, German, CJK.
|
||||
- **Cause:** the 100 limit counts UTF-8 bytes, not characters ("ş" is 2 bytes, a CJK character 3).
|
||||
- **Do:** shorten by bytes; drop words, not commas.
|
||||
- **Guard:** `storebound check` counts bytes for keywords.
|
||||
## 4. Keyword field length (superseded by 43)
|
||||
- The limit is 100 characters, not UTF-8 bytes (see 43). Count characters; drop whole words, not commas.
|
||||
|
||||
## 5. Data safety says "email collected" for an app that never asks for one
|
||||
- **Symptom:** the proposal marks email (or phone) as collected because the app has accounts.
|
||||
|
|
@ -564,3 +561,68 @@ that fails without the fix (see CONTRIBUTING.md).
|
|||
- **Guard:** `tests/asc-query-guard.test.ts` (every App Store Connect GET with a query in `cli/` against the spec and
|
||||
`APPLE_LIVE_REJECTED`), the fake App Store Connect's 400 for such parameters, `unknownGroupMessage`;
|
||||
`tests/idempotency.test.ts` (distribute), `tests/testflight.test.ts`.
|
||||
|
||||
## 43. Keyword field: 100 characters, not bytes
|
||||
- **Symptom:** `check` / `listing check` / `check --aso` called live keyword fields too long ("105 bytes > 100") that App
|
||||
Store Connect accepted.
|
||||
- **Cause:** App Store Connect counts characters. Live READY_FOR_SALE versions (read 2026-10-13): Thai 95 characters /
|
||||
265 bytes, Russian 91 / 169, Turkish 100 / 105, Polish 99 / 105. Entry 4 (bytes) was wrong.
|
||||
- **Do:** count characters (`[...text].length`); fill up to 100 characters in any script.
|
||||
- **Guard:** every keyword check counts characters (`cli/lib/copy.ts`, `aso.ts`, `listing-translate.ts`,
|
||||
`aso-intel.ts`); tests with Thai, Turkish and Polish fields over 100 bytes.
|
||||
|
||||
## 44. "No 6.7-inch iPhone screenshots" on a live app with the 6.5-inch set
|
||||
- **Symptom:** `validate` blocked every locale of a live app: "en-US: no APP_IPHONE_67 screenshots".
|
||||
- **Cause:** App Store Connect requires the 6.9" set (APP_IPHONE_67) or, when it is missing, the 6.5" set
|
||||
(APP_IPHONE_65), and scales the smaller sizes from it.
|
||||
- **Do:** treat the 6.5" set as meeting the requirement; adding a 6.9" set is a recommendation.
|
||||
- **Guard:** `ACCEPTED_INSTEAD` in `cli/lib/validate-rules.ts` (a warning `screenshots-size`, no blocker).
|
||||
|
||||
## 45. Play graphics missing in extra languages
|
||||
- **Symptom:** `validate --play` listed an icon and a feature graphic blocker for every non-default language.
|
||||
- **Cause:** Play shows the default language's graphics in a language that has none of its own.
|
||||
- **Do:** only the default language's graphics are required; a language with none uses them (a note).
|
||||
- **Guard:** `playRules` (`images-fallback` note per type).
|
||||
|
||||
## 46. Play Developer Reporting API off
|
||||
- **Symptom:** `apps list --store play` and Play vitals failed with a 403 SERVICE_DISABLED.
|
||||
- **Cause:** the Reporting API is not enabled in the service account's Google Cloud project.
|
||||
- **Do:** open the link the finding prints (`…/playdeveloperreporting.googleapis.com?project=<id>`), press Enable,
|
||||
wait a few minutes. Meanwhile `apps list` shows the Play apps of this machine's folders and store-only entries.
|
||||
- **Guard:** `reportingEnableUrl`, `knownPlayPackages` (`cli/apps.ts`), `healthFindings`.
|
||||
|
||||
## 47. Onboarding a live app left its products out ("no USD prices")
|
||||
- **Symptom:** after `init` + `listing pull` the config had no products although the app sells some.
|
||||
- **Cause:** only texts were pulled, never prices; Apple's price schedule can have a base territory other than the USA.
|
||||
- **Do:** `storebound onboard` (then `--write`): products and subscriptions from both stores with usd = the US price,
|
||||
Apple's base territory as an override, one-store items marked with `platforms`. Then `storebound catalog diff`
|
||||
(clean). Store prices are never changed; an item with no USD price anywhere is named with its base price.
|
||||
- **Guard:** `importCatalog` (`cli/lib/onboard.ts`), `tests/onboard.test.ts`.
|
||||
|
||||
## 48. Contact e-mail, website and App Review contact asked of the owner
|
||||
- **Symptom:** onboarding kept `support@example.com` and asked for the website and review contact.
|
||||
- **Cause:** nothing read Play's app details or App Store Connect's review detail.
|
||||
- **Do:** `storebound onboard` reads them; template values are replaced, real ones kept; the review contact goes to
|
||||
`.storebound/credentials.json` (masked in output, the phone never printed).
|
||||
- **Guard:** `contactProposal`, `reviewContactOf`, `maskContact`.
|
||||
|
||||
## 49. Sign-in for review defaulted to yes
|
||||
- **Symptom:** every onboarded app got "sign-in required: add a demo account".
|
||||
- **Do:** decide from Apple's review detail (`demoAccountRequired`; a demo account there is imported, never printed)
|
||||
and from the code's auth signals; ask only when neither proves it.
|
||||
- **Guard:** `signInDecision`.
|
||||
|
||||
## 50. Account deletion URL asked although the site has the page
|
||||
- **Do:** `storebound onboard` tries /delete-account, /account/delete, /delete, /account-deletion and the privacy
|
||||
policy's deletion links; not found is reported as the real gap it is (Play requires the page). Never invent one.
|
||||
- **Guard:** `findDeletionUrl`.
|
||||
|
||||
## 51. No default credential profile except one named "default"
|
||||
- **Do:** `storebound accounts default <profile>` (`--clear`). Order: env > the project's named profile > the
|
||||
project's own keys > this default > the only profile.
|
||||
- **Guard:** `defaultProfile`, `tests/machine.test.ts`.
|
||||
|
||||
## 52. A live app with no local project is missing from the desktop
|
||||
- **Do:** `storebound apps add --store apple --app-id <id> --account <profile>`; the desktop shows it read-only
|
||||
("Store only": status, reviews, analytics). `apps remove apple:<id>` takes it out.
|
||||
- **Guard:** `storeApps` in `~/.storebound/projects.json` (`cli/lib/registry.ts`, `registry.rs`), the boot check.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue