openaso

tools / coverage

coverage

read-only

Metadata keyword coverage

Which search phrases a metadata draft can rank for, computed locally (no network). Apple indexes the title (30 chars), subtitle (30) and hidden keyword field (100) of a localization as ONE combined word pool: an app can rank for any query assembled from words across those fields — "photo" in the title plus "resize" in the keyword field can rank for "resize photo". Title words weigh most, then subtitle, then keyword field; word order and case do not gate what can rank (a phrase kept intact in the title/subtitle is a mild extra signal); repeating a word in a second field adds nothing. Reports per-field character budgets, the combined pool, cross-field duplicates (reclaimable characters), and for each target phrase whether it is covered — verbatim in the title/subtitle, assembled cross-field, or missing words. In the keyword field, commas count toward the 100 characters; redundant characters (spaces around commas, duplicated words, stopwords) are reported in keywordFieldWaste. Weight phrases with {phrase, value} (e.g. value = popularity from the volume tool) and wordValues aggregates each word's total search value across every phrase it combines into — "photo" serves "photo editor", "photo maker" and "take photo" at once. totalValue credits a phrase to all of its words (not additive across words); use unlockValue (absent words whose addition alone covers new phrases) and atRiskValue (pool words whose removal breaks covered phrases) for marginal decisions. Evaluates one localization; storefronts may index extra localizations (e.g. the US storefront also indexes Spanish (Mexico)). Cross-field combinations tend to rank weaker than same-field phrases, so confirm real positions with rank.

input

title *
string
App title draft (30-char limit)
subtitle
string
Subtitle draft (30-char limit)
keywords
string
Hidden keyword field draft, comma-separated (100-char limit; commas count, spaces are waste)
phrases
object[]
Target search phrases to check coverage for; weight with {phrase, value} to aggregate per-word search value in wordValues

example call

tools/call → coverage
{
  "name": "coverage",
  "arguments": {
    "title": "…"
  }
}

output

fields *
object[]
field *
"title" | "subtitle" | "keywords"
text *
string
chars *
integer
limit *
integer
Apple's limit: title 30, subtitle 30, keywords 100
remaining *
integer
characters left; negative = over the limit
overLimit *
boolean
tokens *
string[]
pool *
object[]
combined indexable word pool, attributed to the strongest field containing each word
word *
string
field *
"title" | "subtitle" | "keywords"
strongest field containing the word
stopword *
boolean
filler word Apple's search largely ignores — reclaimable
alsoIn *
("title" | "subtitle" | "keywords")[]
weaker fields repeating the word (reclaimable characters)
duplicates *
object[]
words spent in more than one field — repeating adds no ranking benefit
word *
string
fields *
("title" | "subtitle" | "keywords")[]
phrases *
object[]
phrase *
string
covered *
boolean
every substantive word is available in the combined pool (stopwords assumed ignored; false when the phrase has no substantive match at all)
exactIn *
"title" | "subtitle" | null
whole phrase appears verbatim in this field (never keywords — that field is unordered); a kept-intact phrase is a mild extra relevance signal
crossField *
boolean
covered only by combining substantive words from different fields (ranks, but tends to rank weaker)
words *
object[]
word *
string
match *
"exact" | "plural" | "stopword" | null
"plural" is a suffix heuristic; null when missing
field *
"title" | "subtitle" | "keywords" | null
strongest field supplying the match; null for stopword/missing
missing *
string[]
words in no field — the pool alone cannot produce the phrase (Apple can still rank it via developer name, in-app purchase names or query expansion)
value *
number
the phrase's relative search value (input weight; 1 when unweighted)
keywordFieldWaste *
object | null
keyword-field characters that deleting the waste would actually free (null when no keywords draft was given)
spaces *
integer
whitespace around commas or at the ends — a space that is a word's only separator is char-neutral and not counted
duplicates *
integer
chars of words already in title/subtitle or repeated in the field
stopwords *
integer
chars of filler words
separators *
integer
commas/spaces freed by removing the wasted words
total *
integer
wordValues *
object[]
per-word aggregate search value across all target phrases, sorted by totalValue. A word serves every phrase it can combine into, but a phrase's value is credited in full to EACH of its words — totals are not additive across a word set; budget with unlockValue/atRiskValue
word *
string
inPool *
"title" | "subtitle" | "keywords" | null
strongest field containing — or plural-matching — the word; null if absent
chars *
integer
characters of the word itself; a keyword-field entry additionally costs one separating comma
phrases *
string[]
totalValue *
number
summed value of every target phrase containing the word
unlockValue *
number
absent words: summed value of phrases covered by adding just this word
atRiskValue *
number
in-pool words: summed value of covered phrases that would actually lose coverage if the word were dropped from every field (a surviving plural variant keeps a phrase safe)
note *
string
endpoint https://openaso-806591819206.us-west1.run.app/mcp · auth Authorization: Bearer <key> · get a key