seoskills.sh
Catalog/App Store Optimization/ASO Keyword Field Optimizer

ASO Keyword Field Optimizer

Tokenizes an iOS app's title, subtitle, and 100-character keyword field, strips cross-field and stop-word waste, and gr…

Updated

New

Use this skill

$ npx skills add seoskills.sh/aso-keyword-field-optimizer
Repository
seoskills.sh
GitHub stars
License
MIT

About this skill

ASO Keyword Field Optimizer is a App Store Optimization skill for AI agents, published in the seoskills.sh catalog. Reach for it when your work involves keyword and listing optimization for the App Store and Google Play. Install it with one command and it runs inside your own agent, so the work happens in your workflow, not a separate SEO tool.

SKILL.md

ASO Keyword Field Optimizer

AGENT ROLE: Autonomous iOS metadata optimizer. Tokenize the listing, remove indexing waste, pack the 100-char keyword field per locale without cross-field or cross-localization duplication, and emit the JSON in references/output.schema.json.

OBJECTIVE

Maximize the number of unique indexable words (and the search-phrase combinations Apple forms from them) across an app's title, subtitle, and hidden keyword field, for each localization, subject to the hard 100-character keyword-field limit and Apple's indexing rules (stop words ignored, duplicates wasted, words auto-combined across fields and localizations serving the same storefront).

INPUTS

  • metadata (REQUIRED): local JSON with app_id and locales[], each {locale, priority, title, subtitle, current_keywords, candidates[]}; every candidate is {term, volume?, difficulty?}.
  • country (OPTIONAL, default us): storefront used for --enrich volume lookups.
  • enrich (OPTIONAL flag): look up missing volume/difficulty via the ASO keyword API.
  • max_lookups (OPTIONAL, default 60): cap on billed enrichment calls across all locales.

AUTHENTICATION (ASO Keyword Data API)

  1. Offline tokenization/packing needs NO key; run it directly from --metadata.
  2. --enrich REQUIRES env ASO_API_KEY. IF --enrich is set and ASO_API_KEY is unset THEN STOP error.code="AUTH_MISSING_ASO_KEY".
  3. Enrichment endpoint: GET https://api.asokeyword.io/v1/keywords?term={term}&country={country} with header Authorization: Bearer {ASO_API_KEY}, returning {volume, difficulty}.

EXPECTED TOOL CALLS

  • Run scripts/keyword_field_optimizer.py --metadata listing.json [--enrich --country us --max-lookups 60].
  • Offline: zero network calls. With --enrich: at most one lookup per candidate lacking a volume, capped by --max-lookups.

PROCEDURE (deterministic)

STEP 1 — TOKENIZE each locale's title + subtitle into a covered set (lowercase, non-alphanumeric split, naive singularization, stop words removed). These words are already indexed; repeating them anywhere is waste. STEP 2 — BUILD the candidate token pool from candidates[] plus the current keyword field (so existing terms are not silently lost). Assign each token the best opportunity = volume / (difficulty + 10) of any term it appears in; unknown-volume tokens keep opportunity=null. STEP 3 — RANK tokens by opportunity desc, then first-seen order. STEP 4 — PACK per locale in priority order (1 first). For each ranked token DROP it with a reason IF it is a stop word (stopword), already in title/subtitle (in_title_subtitle), or already placed in an earlier locale (duplicate_across_locale); ELSE place it IF len(field) + len(token) + 1 ≤ 100, joining with commas and NO spaces; ELSE DROP over_budget. STEP 5 — DEDUPE across localizations via a shared placed-set, so the second and third localizations extend coverage instead of repeating it. STEP 6 — PROJECT coverage: indexable = covered ∪ placed; estimate combinations as n + C(n,2) (unigrams + unordered bigrams); report per-locale and listing-wide combinations_gained.

RATE LIMITS & ERROR HANDLING

  • Enrichment 429 → backoff 2^attempt (max 5) then treat that term as unknown-volume and continue.
  • 5xx/timeout retry ≤3 then treat as unknown-volume.
  • Concurrency ≤ 1 (serial lookups, time.sleep(0.2) pacing); enrichment calls capped by --max_lookups as a cost guard.

MISSING / INSUFFICIENT DATA

  • IF no candidate has volume data anywhere (and --enrich produced none) THEN status="insufficient": tokens are still packed, but by input order, and a warning states ranking is not opportunity-driven — NEVER invent volumes.
  • Brand/title words are reported in brand_tokens_excluded and never placed into the keyword field (already indexed by the title).
  • The keyword field is always emitted with no spaces after commas; a locale whose field would exceed 100 chars is impossible by construction and is surfaced as a warning if it ever occurs.

OUTPUT

One JSON object per references/output.schema.json. No prose.

FILES

  • scripts/keyword_field_optimizer.py — tokenizer, cross-field/locale dedupe, greedy 100-char packer, coverage projection.
  • references/output.schema.json — output contract.

Not using the CLI? Copy the SKILL.md and paste it straight into ChatGPT, Claude, or any agent.

Embed a badge

seoskills.sh install badge