skills/app-store-aso-localization/SKILL.md
App Store Optimization and metadata localization for iOS/macOS apps. Use this skill when working with App Store metadata for any of these tasks: (1) Analyzing current app metadata health (character usage, missing localizations), (2) Keyword research and optimization across locales, (3) Translating and localizing metadata to 38+ languages, (4) Implementing cross-localization strategies to maximize keyword coverage, (5) Bulk updating metadata via App Store Connect API, (6) Competitor ASO analysis and keyword gap identification, (7) Generating optimized titles, subtitles, keywords, and descriptions, (8) Auditing metadata for ASO best practices compliance.
npx skillsauth add onatcipli/skills app-store-aso-localizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Optimize your App Store metadata and localize across 38 languages using ASO best practices and the App Store Connect API.
| Field | Limit | Indexed | Level | Notes | |-------|-------|---------|-------|-------| | App Name | 30 chars | Yes (highest) | App | Brand + primary keyword | | Subtitle | 30 chars | Yes (medium) | App | USP + secondary keywords | | Keywords | 100 chars | Yes (iOS only) | Version | Comma-separated, no spaces | | Promotional Text | 170 chars | No | Version | Can update without review | | Description | 4,000 chars | No (iOS) | Version | Conversion-focused | | What's New | 4,000 chars | No | Version | Release notes |
Important: iOS App Store does NOT index the description for search. Focus keywords in Title → Subtitle → Keywords field only.
| Tier | Auth | Endpoints | Use Case | |------|------|-----------|----------| | Public | None | iTunes Search/Lookup | Competitor research | | Private | JWT | App Store Connect API | Manage your metadata |
For authentication setup, see api-endpoints.md.
Audit your app's metadata for optimization opportunities.
GET /v1/apps/{appId}/appInfos
GET /v1/appInfos/{appInfoId}/appInfoLocalizations
GET /v1/appStoreVersions/{versionId}/appStoreVersionLocalizations
For each locale, calculate usage percentage:
fields = {
"name": {"limit": 30, "value": localization.name},
"subtitle": {"limit": 30, "value": localization.subtitle},
"keywords": {"limit": 100, "value": localization.keywords},
"promotionalText": {"limit": 170, "value": localization.promotionalText},
"description": {"limit": 4000, "value": localization.description}
}
for field, data in fields.items():
usage = len(data["value"]) / data["limit"] * 100
if usage < 90:
flag_underutilized(field, usage)
Compare active localizations against recommended markets:
Priority markets: en-US, en-GB, de-DE, fr-FR, ja, zh-Hans, zh-Hant,
ko, es-ES, es-MX, pt-BR, it, nl, ru, tr, ar
## Metadata Health Report — {App Name}
### Overview
- Active localizations: 12/38
- Character utilization: 78% average
- ASO violations: 3 found
### Character Usage by Locale
| Locale | Name | Subtitle | Keywords | Status |
|--------|------|----------|----------|--------|
| en-US | 28/30 (93%) | 25/30 (83%) | 98/100 (98%) | Good |
| de-DE | 22/30 (73%) | 18/30 (60%) | 72/100 (72%) | Underutilized |
| ja | 15/30 (50%) | 12/30 (40%) | 45/100 (45%) | Poor |
### Missing High-Value Localizations
- zh-Hans (China) — 2nd largest App Store
- ko (Korea) — High spending market
- pt-BR (Brazil) — Growing market
### ASO Violations Found
1. ❌ Keyword "photo" appears in both Title and Keywords (en-US)
2. ❌ Stop word "app" in keywords field (en-GB)
3. ❌ Space after comma in keywords (de-DE)
### Recommendations
1. Add Chinese (Simplified) localization — potential +15% downloads
2. Expand German keywords to use full 100 characters
3. Remove duplicate keywords to add more unique terms
Research and optimize keywords for maximum discoverability.
Gather initial keywords from:
GET https://itunes.apple.com/lookup?id={competitor_id}&country={cc}
For each keyword, evaluate:
| Metric | Description | Source | |--------|-------------|--------| | Search Volume | How often users search this term | ASO tools / estimation | | Difficulty | Competition level (0-100) | Top 10 app ratings | | Relevance | How well it describes your app | Manual assessment | | Current Rank | Your position for this keyword | Track over time |
def score_keyword(volume, difficulty, relevance):
"""
Higher score = better keyword opportunity
Volume: 1-100, Difficulty: 1-100, Relevance: 1-10
"""
opportunity = volume * (1 - difficulty/100)
score = opportunity * relevance
return score
Rules for the 100-character keywords field:
keyword1,keyword2,keyword3## Optimized Keywords — {App Name} (en-US)
### Title (30 chars)
"PhotoEdit Pro - Picture Editor"
Keywords captured: photoedit, pro, picture, editor
### Subtitle (30 chars)
"Filters, Collage & Retouch"
Keywords captured: filters, collage, retouch
### Keywords Field (100 chars)
"camera,enhance,crop,adjust,brightness,contrast,saturation,blur,sharpen,resize,rotate,frame,effects"
Characters used: 97/100
### Total Unique Keywords: 17
See keyword-strategies.md for advanced techniques.
Translate and adapt metadata for international markets.
Prioritize by market opportunity:
| Tier | Locales | Rationale | |------|---------|-----------| | Tier 1 | en-US, en-GB, de-DE, ja, zh-Hans | Largest markets | | Tier 2 | fr-FR, ko, es-ES, pt-BR, it | High growth | | Tier 3 | nl, ru, tr, ar, zh-Hant, sv | Market expansion | | Tier 4 | All remaining | Full coverage |
For each field, translate while respecting limits:
def translate_field(text, source_lang, target_lang, char_limit):
"""
Translate text and ensure it fits within character limit.
"""
translated = ai_translate(text, source_lang, target_lang)
if len(translated) > char_limit:
# Shorten while preserving meaning
translated = ai_shorten(translated, char_limit)
return translated
Keywords require localization, not just translation:
Example: "photo editor" app
❌ Wrong (direct translation):
- German: "fotobearbeitung" (literal translation)
✅ Right (localized):
- German: "bildbearbeitung,fotos,bilder,bearbeiten,filter"
(terms Germans actually search for)
Research local search behavior:
PATCH /v1/appInfoLocalizations/{localizationId}
{
"data": {
"type": "appInfoLocalizations",
"id": "{localizationId}",
"attributes": {
"name": "Localized App Name",
"subtitle": "Localized Subtitle"
}
}
}
PATCH /v1/appStoreVersionLocalizations/{localizationId}
{
"data": {
"type": "appStoreVersionLocalizations",
"id": "{localizationId}",
"attributes": {
"keywords": "localized,keywords,here",
"description": "Localized description...",
"promotionalText": "Localized promo text"
}
}
}
After applying:
Apple indexes keywords from MULTIPLE locales per storefront. Use this to effectively double your keyword coverage.
| Storefront | Primary Locale | Secondary Locale(s) | |------------|---------------|---------------------| | USA | en-US | es-MX | | UK | en-GB | en-US | | Canada | en-CA | fr-CA, en-US | | Australia | en-AU | en-US | | Germany | de-DE | en-US | | France | fr-FR | en-US | | Japan | ja | en-US | | Brazil | pt-BR | en-US | | Mexico | es-MX | en-US | | Spain | es-ES | en-US | | China | zh-Hans | en-US | | Taiwan | zh-Hant | en-US |
For the US App Store (indexes en-US + es-MX):
## US Market — Cross-Localization
### en-US Keywords (100 chars)
"photo,editor,camera,filter,retouch,enhance,crop,adjust,collage"
### es-MX Keywords (100 chars) — ALSO indexed in US!
"fotos,editar,imagen,efectos,marcos,belleza,retrato,selfie,blur"
### Result: 18 unique keywords indexed for US users
(vs 9 if only using en-US)
## Cross-Localization Plan — {App Name}
### Target: US App Store
Primary: en-US | Secondary: es-MX
| en-US Keywords | es-MX Keywords |
|----------------|----------------|
| photo | fotos |
| editor | editar |
| camera | cámara |
| filter | filtros |
| enhance | mejorar |
| collage | collage ❌ (duplicate, remove) |
| retouch | retocar |
| beauty | belleza |
| portrait | retrato |
**Recommendation:** Replace "collage" in es-MX with unique term like "marcos"
See locale-reference.md for complete cross-indexing map.
Apply metadata changes programmatically.
GET /v1/apps/{appId}/appStoreVersions?filter[appStoreState]=READY_FOR_SALE,PREPARE_FOR_SUBMISSION
GET /v1/appStoreVersions/{versionId}/appStoreVersionLocalizations
POST /v1/appStoreVersionLocalizations
{
"data": {
"type": "appStoreVersionLocalizations",
"attributes": {
"locale": "de-DE",
"keywords": "keywords,here",
"description": "German description...",
"promotionalText": "German promo",
"whatsNew": "What's new in German"
},
"relationships": {
"appStoreVersion": {
"data": {
"type": "appStoreVersions",
"id": "{versionId}"
}
}
}
}
}
PATCH /v1/appStoreVersionLocalizations/{localizationId}
{
"data": {
"type": "appStoreVersionLocalizations",
"id": "{localizationId}",
"attributes": {
"keywords": "updated,keywords",
"description": "Updated description..."
}
}
}
PATCH /v1/appInfoLocalizations/{localizationId}
{
"data": {
"type": "appInfoLocalizations",
"id": "{localizationId}",
"attributes": {
"name": "New App Name",
"subtitle": "New Subtitle"
}
}
}
async def bulk_update_localizations(app_id, updates):
"""
updates = {
"de-DE": {"keywords": "...", "description": "..."},
"fr-FR": {"keywords": "...", "description": "..."},
}
"""
version_id = await get_current_version(app_id)
localizations = await get_localizations(version_id)
for locale, changes in updates.items():
loc_id = find_localization_id(localizations, locale)
if loc_id:
await patch_localization(loc_id, changes)
else:
await create_localization(version_id, locale, changes)
# Rate limiting
await asyncio.sleep(0.5)
return {"updated": len(updates)}
Analyze competitor metadata to identify opportunities.
GET https://itunes.apple.com/search?term={category}&media=software&limit=25
Or specify competitor app IDs directly.
For each competitor, across key locales:
locales = ["us", "gb", "de", "fr", "jp", "br"]
for competitor_id in competitors:
for locale in locales:
data = fetch_itunes_lookup(competitor_id, locale)
store_metadata(competitor_id, locale, data)
From competitor metadata, extract likely keywords:
def extract_keywords(app_data):
keywords = set()
# From title (remove brand name)
title_words = app_data["trackName"].lower().split()
keywords.update(title_words)
# From description (top frequency words)
desc_words = extract_top_words(app_data["description"], n=20)
keywords.update(desc_words)
# Filter stop words
keywords = filter_stop_words(keywords)
return keywords
def find_keyword_gaps(your_keywords, competitor_keywords):
"""Find keywords competitors use that you don't."""
gaps = competitor_keywords - your_keywords
return sorted(gaps, key=lambda k: estimate_value(k), reverse=True)
## Competitor ASO Analysis — {Category}
### Competitors Analyzed
1. Competitor A (id: 123456) — 4.8★, 50K ratings
2. Competitor B (id: 789012) — 4.6★, 30K ratings
3. Competitor C (id: 345678) — 4.5★, 25K ratings
### Keyword Coverage Comparison
| Keyword | You | Comp A | Comp B | Comp C | Opportunity |
|---------|-----|--------|--------|--------|-------------|
| photo editor | ✓ | ✓ | ✓ | ✓ | Low (saturated) |
| ai enhance | ✗ | ✓ | ✓ | ✗ | High |
| background remove | ✗ | ✓ | ✓ | ✓ | High |
| collage maker | ✓ | ✗ | ✓ | ✓ | Covered |
| beauty camera | ✗ | ✓ | ✗ | ✓ | Medium |
### Keyword Gaps (High Opportunity)
1. "ai enhance" — Used by 2/3 competitors, you're missing
2. "background remove" — Used by 3/3 competitors
3. "portrait mode" — Growing trend, 2/3 competitors
### Title/Subtitle Patterns
- 3/3 competitors include "Photo" in title
- 2/3 use "Pro" or "Plus" suffix
- All include primary feature in subtitle
### Recommendations
1. Add "ai enhance" to keywords — high competitor usage
2. Consider "background" variations in title/subtitle
3. Test "Pro" suffix for premium positioning
| Task | Method | Endpoint |
|------|--------|----------|
| List app infos | GET | /v1/apps/{id}/appInfos |
| List app info localizations | GET | /v1/appInfos/{id}/appInfoLocalizations |
| Update app info localization | PATCH | /v1/appInfoLocalizations/{id} |
| List version localizations | GET | /v1/appStoreVersions/{id}/appStoreVersionLocalizations |
| Create version localization | POST | /v1/appStoreVersionLocalizations |
| Update version localization | PATCH | /v1/appStoreVersionLocalizations/{id} |
| Delete version localization | DELETE | /v1/appStoreVersionLocalizations/{id} |
| iTunes lookup | GET | itunes.apple.com/lookup?id={id}&country={cc} |
| iTunes search | GET | itunes.apple.com/search?term={q}&media=software |
Before submitting metadata updates:
| File | Purpose | |------|---------| | aso-best-practices.md | Character limits, rules, optimization tips | | locale-reference.md | All 38 locales with cross-indexing map | | api-endpoints.md | App Store Connect API details | | keyword-strategies.md | Advanced keyword research techniques |
tools
A native-first SwiftUI design language for building consistent, premium iOS app UI — a dark-first, image-forward, softly-rounded aesthetic (inspired by apps like Luma) expressed almost entirely through native SwiftUI components. Use this skill for any UI/UX work in a SwiftUI/iOS project: (1) Building new screens, views, or components, (2) Redesigning or restyling existing screens, (3) Refactoring ad-hoc styling into reusable design tokens, (4) Reviewing UI for visual consistency, (5) Implementing dark interfaces with materials/Liquid Glass, navigation stacks, tab views, lists, toolbars, buttons, search, sheets, empty states, hero headers, chips, and avatar groups. The guiding rule is NATIVE FIRST: reach for built-in SwiftUI components and modifiers before writing any custom view, and only build a custom component when the platform genuinely can't express the design. Trigger when the user mentions UI, design, styling, layout, theming, redesign, restyle, refactor the UI, design consistency, or "make it look good/premium/like Luma" in any SwiftUI/iOS project.
tools
App Store screenshot research, competitor analysis, building, and upload tool for iOS/macOS apps. Use this skill when working with App Store screenshots for any of these tasks: (1) Finding and analyzing competitor screenshots in your category, (2) Downloading competitor screenshots locally for reference, (3) Analyzing screenshot strategies (styles, captions, features), (4) Researching ASO keywords for screenshot captions, (5) Planning your screenshot sequence and messaging, (6) Building screenshots using an HTML/CSS export tool, (7) Generating a local preview website to view and compare screenshots, (8) Exporting screenshots at correct dimensions via browser or Puppeteer, (9) Localizing screenshots for multiple App Store locales, (10) Uploading screenshots to App Store Connect via API.
development
App Store review analysis, competitor intelligence, and automated response generation for iOS/macOS apps. Use this skill when working with Apple App Store reviews for any of these tasks: (1) Fetching and analyzing customer reviews for your own apps via the App Store Connect API, (2) Fetching competitor app reviews via the public RSS feed or iTunes Search API, (3) Performing sentiment analysis, theme extraction, or bug/feature-request categorization on reviews, (4) Generating context-aware developer replies to customer reviews, (5) Comparing ratings, review sentiment, or feature gaps across competing apps, (6) Tracking rating trends and review volume over time, (7) Producing executive summaries or actionable insight reports from review data, (8) Searching the App Store for apps by name or category, (9) Setting up app-specific reply configurations through an interactive onboarding interview that auto-detects patterns from existing responses.
development
Price localization intelligence for iOS/macOS apps using purchasing power parity analysis. Use this skill when working with App Store pricing for any of these tasks: (1) Building a "Price Index" by analyzing reference app prices across territories, (2) Comparing your app's pricing against PPP-adjusted benchmarks, (3) Generating localized price recommendations based on economic data, (4) Automating price updates via App Store Connect API, (5) Analyzing competitor pricing strategies across markets, (6) Identifying overpriced/underpriced territories hurting conversions or revenue, (7) Creating pricing health reports with actionable recommendations.