App Store Optimization skill for Codex
Every indexed character earning its place. Codex researches keywords by relevance, popularity and difficulty, then spreads them across the App Store name, subtitle and keyword field without repeats, and writes Play titles and descriptions that respect Google's metadata policy. It plans screenshot captions frame by frame, edits fastlane metadata files, checks every field against its limit, and measures one change at a time with store experiments.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- app-store-optimization Installs to ~/.agents/skills/app-store-optimization/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install app-store-optimization The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project app-store-optimization Installs to .agents/skills/app-store-optimization/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/app-store-optimization.zipunzip -o app-store-optimization.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) app-store-optimization PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $app-store-optimization, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Optimises App Store and Google Play listings for search and conversion - keyword research, app name, subtitle and 100-character keyword field, Play title and short description, screenshots and preview video, localisation, ratings prompts, custom product pages, Product Page Optimization and store listing experiments. Edits fastlane deliver and supply metadata files and checks every field against character limits. Use when asked to improve app store ranking, rewrite store metadata, plan screenshots, localise a listing, or raise store conversion rate.
Use it when
- An app ranks poorly for terms its users search for
- Store metadata or screenshots need rewriting before a release
- A listing must be localised for new storefronts
- You want to set up custom product pages or store listing experiments
Use something else when
- You need the in-app UI or onboarding redesigned: use mobile-ui-patterns
- You are optimising a website for Google search: use on-page-seo
How to check the result
Every fastlane metadata file passes the limit check, iOS indexed fields share no repeated words, and target keyword ranks and store conversion are compared to baseline after two and four weeks.
The mistake it prevents
Repeating the same words across the app name, subtitle and keyword field, which wastes the scarce indexed characters Apple already combines.
ASO is done well when every indexed field carries distinct, high-relevance keywords without repetition or stuffing, screenshots sell the outcome in the first two frames, the listing is localised for the storefronts that matter, and changes are measured one at a time with the stores’ own experiment tools.
Inspect first
- Find where metadata lives. Many repos keep it as files for fastlane:
ls fastlane/metadata 2>/dev/null # iOS: fastlane deliver
ls fastlane/metadata/android 2>/dev/null # Android: fastlane supply
rg -n "deliver|supply|upload_to_app_store|upload_to_play_store" fastlane/Fastfile
Otherwise metadata is only in App Store Connect / Play Console; ask the user to paste
current values or export them.
2. Collect baselines: impressions, product page views, conversion rate (App Store Connect
App Analytics; Play Console Store performance), top search terms, ratings average and
count, top competitor apps.
3. Read AGENTS.md for release process; metadata uploads usually ride with a release.
Field limits and what is indexed
| Field | App Store | Google Play |
|---|---|---|
| Name / title | 30 chars, indexed (strongest) | 30 chars, indexed (strongest) |
| Subtitle / short description | Subtitle 30 chars, indexed | Short description 80 chars, indexed |
| Keyword field | 100 chars, comma-separated, hidden, indexed | None |
| Promotional text | 170 chars, not indexed, editable without a new version | - |
| Description | 4,000 chars, not indexed for search | Full description 4,000 chars, indexed |
| In-app purchase names | Indexed | Indexed (lesser) |
| Screenshots | Up to 10 per device size | 2-8 per device type |
| Preview video | Up to 3 app previews, 15-30 s | YouTube video link |
| Custom pages | Custom product pages (up to 70 since late 2025; keywords can be assigned to them) | Custom store listings by country, campaign or audience |
| Experiments | Product Page Optimization: up to 3 treatments | Store listing experiments |
App Store name, subtitle and keywords change only with a new app version submission. Promotional text and Play listings can change any time.
Keyword research
- Brainstorm seed terms from: what users do with the app (verbs), the problem, category words, competitor names in reviews (never use competitor trademarks in metadata), and terms from your own reviews (“budget”, “split bills”).
- Score each term on relevance (would a searcher be happy to find this app?), popularity (Apple Ads popularity, or a tool such as AppTweak, Sensor Tower, Appfigures, MobileAction, Astro) and difficulty (strength of the top 10 results).
- Prefer relevant mid-popularity terms the app can rank for over head terms dominated by giants; new apps rarely rank for one-word head terms.
- Check the actual search results on a device for the top 10 candidates.
App Store field strategy
- Name: brand + the single most valuable keyword phrase:
Pennywise: Budget Planner. - Subtitle: a benefit that adds new keywords, not repeats:
Track spending & split bills. - Keyword field:
- Commas, no spaces:
expense,tracker,money,savings,receipts,family,shared,goals. - Never repeat words already in name or subtitle; Apple combines words across fields.
- Singular or plural, not both, for most terms; no category name, no “app”, no competitor brands.
- Use all 100 characters.
- Commas, no spaces:
- Description: written for conversion (not ranking): first 3 lines matter because the rest is collapsed.
- Localisations: each storefront can index additional localisations (the US store, for example, also reads some other locales’ metadata). Check Apple’s current mapping and use secondary locales for extra keywords where it is legitimate.
Google Play field strategy
- Title: brand + core keyword, 30 chars.
- Short description: benefit-led, includes 1-2 core keywords naturally.
- Full description: indexed; mention core terms naturally a few times across structured sections. Google treats unnatural repetition as spam.
- Play’s metadata policy bans terms like “best”, “#1”, “top”, “free”, “new” or prices and promotions in the title, icon and developer name, as well as emoji and ALL CAPS styling. Rejections and suspensions follow.
Screenshots and video
- The first two or three screenshots appear in search results; they decide most installs.
- Each frame: one benefit caption (3-7 words, large type) over a real UI screenshot. Order frames by what convinces, not by app navigation order.
- First frame: the core outcome. Include social proof (award, rating) only if true and current.
- Localise captions, not just text fields.
- Preview video: show the app in use in the first 3 seconds; it autoplays muted, so add captions.
- Export at the exact required sizes from App Store Connect / Play Console help; wrong sizes are rejected on upload.
Ratings and reviews
- Ask at a moment of success (task completed, streak reached), never on first launch or after an error.
- iOS:
requestReview(SwiftUI@Environment(\.requestReview)or StoreKit); the system shows the prompt at most 3 times in 365 days per user, and may show nothing. - Android: Play In-App Review API (
ReviewManager.requestReviewFlow()thenlaunchReviewFlow()); quota is enforced by Play and not exposed. - Never incentivise or gate reviews (“rate 5 stars to get the bonus level”); both stores forbid it.
- Reply to negative reviews with specifics and a fix; replies are public.
Editing metadata as files
fastlane layout (one folder per locale):
fastlane/metadata/en-US/name.txt
fastlane/metadata/en-US/subtitle.txt
fastlane/metadata/en-US/keywords.txt
fastlane/metadata/en-US/promotional_text.txt
fastlane/metadata/en-US/description.txt
fastlane/metadata/android/en-US/title.txt
fastlane/metadata/android/en-US/short_description.txt
fastlane/metadata/android/en-US/full_description.txt
Check limits before any upload:
python3 - <<'PY'
import pathlib
limits = {"name.txt": 30, "subtitle.txt": 30, "keywords.txt": 100, "promotional_text.txt": 170,
"description.txt": 4000, "title.txt": 30, "short_description.txt": 80, "full_description.txt": 4000}
bad = 0
for p in pathlib.Path("fastlane/metadata").rglob("*.txt"):
if p.name in limits:
n = len(p.read_text(encoding="utf-8").strip())
if n > limits[p.name]:
bad += 1
print(f"OVER {p} {n}/{limits[p.name]}")
print("ok" if not bad else f"{bad} field(s) over limit")
PY
Also check for words duplicated between name.txt, subtitle.txt and keywords.txt
per locale. Uploading metadata (fastlane deliver, fastlane supply) changes the live
store listing or a submission: run it only after the user approves the final text, and
note it needs network and store credentials.
Measuring changes
- Change one lever at a time (icon, first screenshot, subtitle) and note the date.
- Use Product Page Optimization / store listing experiments for creative changes; run until the console reports a result with enough confidence, typically 1-3 weeks.
- For keyword changes, track rankings for the target terms for 2-4 weeks after release, and impressions from App Store search.
- Conversion rate = installs / product page views (or store listing visitors); compare same-source traffic only.
Gotchas
- Repeating the brand or keywords across name, subtitle and keyword field wastes space.
- Keyword stuffing in the Play full description triggers policy action.
- Using a competitor’s brand in metadata gets the update rejected.
- Screenshots showing features behind a paywall without saying so cause bad reviews.
- Changing icon, screenshots and subtitle in one release makes the result unreadable.
Verification
- Limit script passes for every locale; no duplicated words across iOS indexed fields.
- Preview the listing in App Store Connect / Play Console on a phone-sized view.
- After release: target keyword ranks and conversion rate compared to baseline at 2 and 4 weeks.
Output template
## ASO update: <app> (<platforms>, <locales>)
**Baseline:** page views, conversion rate, rating, top terms
**Target keywords:** table (term, relevance, popularity, difficulty, field)
**iOS:** name / subtitle / keywords (chars used) / promo text
**Android:** title / short description / full description outline
**Screenshots:** frame-by-frame captions
**Experiment plan:** lever, start date, success metric
**Awaiting approval:** metadata upload, release submission What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "App Store Optimization"
short_description: "Every indexed character earning its place"
default_prompt: "$app-store-optimization Rewrite our App Store name, subtitle and keyword field to rank for budgeting terms" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.