$npx -y skills add rorkai/app-store-connect-cli-skills --skill asc-aso-auditRun an offline ASO audit on canonical App Store metadata under ./metadata and surface keyword gaps using Astro MCP. Use after pulling metadata with asc metadata pull.
| 1 | # asc ASO audit |
| 2 | |
| 3 | Run a two-phase ASO audit: offline checks against local metadata files, then keyword gap analysis via Astro MCP. |
| 4 | When available, include Apple-generated app tags as a discoverability signal. |
| 5 | |
| 6 | ## Preconditions |
| 7 | |
| 8 | - Metadata pulled locally into canonical files via `asc metadata pull --app "APP_ID" --version "1.2.3" --dir "./metadata"`. |
| 9 | - If metadata came from `asc migrate export` or `asc localizations download`, normalize it into the canonical `./metadata` layout before running this skill. |
| 10 | - For Astro gap analysis: app tracked in Astro MCP (optional — offline checks run without it). |
| 11 | - For Apple-generated discoverability tags: `asc app-tags list --app "APP_ID" --output json` works when the API returns tags for the app. |
| 12 | |
| 13 | ## Before You Start |
| 14 | |
| 15 | 1. Read `references/aso_rules.md` to understand the rules each check enforces. |
| 16 | 2. Identify the **latest version directory** under `metadata/version/` (highest semantic version number). Use this for all version-level fields. |
| 17 | 3. The **primary locale** is `en-US` unless the user specifies otherwise. |
| 18 | |
| 19 | ## Metadata File Paths |
| 20 | |
| 21 | - **App-info fields** (`subtitle`): `metadata/app-info/{locale}.json` |
| 22 | - **Version fields** (`keywords`, `description`, `whatsNew`): `metadata/version/{latest-version}/{locale}.json` |
| 23 | - **App name**: May not be present in exported metadata. If `name` is missing from the app-info JSON, fetch it via `asc apps info list` or ask the user. Do not flag it as a missing-field error. |
| 24 | |
| 25 | ## Phase 1: Offline Checks |
| 26 | |
| 27 | Run these 5 checks against the local metadata directory. No network calls required. |
| 28 | |
| 29 | ### 1. Keyword Waste |
| 30 | |
| 31 | Tokenize the `subtitle` field (and `name` if available). Flag any token that also appears in the `keywords` field — it is already indexed and wastes keyword budget. |
| 32 | |
| 33 | ``` |
| 34 | Severity: ⚠️ Warning |
| 35 | Example: "quran" appears in subtitle AND keywords — remove from keywords to free 6 characters |
| 36 | ``` |
| 37 | |
| 38 | How to check: |
| 39 | 1. Read `metadata/app-info/{locale}.json` for `subtitle` (and `name` if present) |
| 40 | 2. Read `metadata/version/{latest-version}/{locale}.json` for `keywords` |
| 41 | 3. Tokenize subtitle (+ name): |
| 42 | - **Latin/Cyrillic scripts:** split by whitespace, strip leading/trailing punctuation, lowercase |
| 43 | - **Chinese/Japanese/Korean:** split by `、` `,` `,` or iterate characters — each character or character-group is a token. Whitespace tokenization does not work for CJK. |
| 44 | - **Arabic:** split by whitespace, then also generate prefix-stripped variants (remove ال prefix) since Apple likely normalizes definite articles. For example, "القرآن" in subtitle should flag both "القرآن" and "قرآن" in keywords. |
| 45 | 4. Split keywords by comma, trim whitespace, lowercase |
| 46 | 5. Report intersection (including fuzzy matches from prefix stripping) |
| 47 | |
| 48 | ### Optional: App Tag Alignment |
| 49 | |
| 50 | App tags are Apple-generated labels that can appear in search results and product pages. They are not editable ASO metadata, but they are useful evidence for whether Apple's classification matches the intended positioning. |
| 51 | |
| 52 | ```bash |
| 53 | asc app-tags list --app "APP_ID" --output json |
| 54 | asc app-tags view --app "APP_ID" --id "TAG_ID" --output json |
| 55 | ``` |
| 56 | |
| 57 | Use tags as context only: |
| 58 | - If visible tags reinforce the subtitle/keyword strategy, note the alignment. |
| 59 | - If tags point to an unintended category or use case, recommend metadata/category changes that may improve future classification. |
| 60 | - Do not promise that changing metadata will immediately change Apple-generated tags. |
| 61 | |
| 62 | ### 2. Underutilized Fields |
| 63 | |
| 64 | Flag fields using less than their recommended minimum: |
| 65 | |
| 66 | | Field | Minimum | Limit | Rationale | |
| 67 | |-------|---------|-------|-----------| |
| 68 | | Keywords | 90 chars | 100 | 90%+ usage maximizes indexing | |
| 69 | | Subtitle | 20 chars | 30 | 65%+ usage recommended | |
| 70 | |
| 71 | ``` |
| 72 | Severity: ⚠️ Warning |
| 73 | Example: keywords is 62/100 characters (62%) — 38 characters of indexing opportunity unused |
| 74 | ``` |
| 75 | |
| 76 | ### 3. Missing Fields |
| 77 | |
| 78 | Flag empty or missing required fields: `subtitle`, `keywords`, `description`, `whatsNew`. |
| 79 | |
| 80 | Note: `name` may not be in the export — only flag it if the app-info JSON explicitly contains a `name` key with an empty value. |
| 81 | |
| 82 | ``` |
| 83 | Severity: ❌ Error |
| 84 | Example: subtitle is empty for locale en-US |
| 85 | ``` |
| 86 | |
| 87 | ### 4. Bad Keyword Separators |
| 88 | |
| 89 | Check the `keywords` field for formatting issues: |
| 90 | - Spaces after commas (`quran, recitation`) |
| 91 | - Semicolons instead of commas (`quran;recitation`) |
| 92 | - Pipes instead of commas (`quran|recitation`) |
| 93 | |
| 94 | ``` |
| 95 | Severity: ❌ Error |
| 96 | Example: keywords contain spaces after commas — wastes 3 characters |
| 97 | ``` |
| 98 | |
| 99 | ### 5. Cross-Locale Keyword Gaps |
| 100 | |
| 101 | Compare `keywords` fields across all available locales. Flag locales where keywords are identical to the primary locale (`en-US` by default) — this usually means they were not localized. |
| 102 | |
| 103 | ``` |
| 104 | Severity: ⚠️ Warning |
| 105 | Example: ar keywords identical to en-US — likely not localized for Arabic ma |