Point AppMates at your app once and every other tool uses it: the rank check, the competitor comparison, the keyword builder. What the public catalogue knows about your listing is below, along with what is left to fix.
Ready to fix what's found? Subtitle, promotional text, the keyword field and real prices need your own App Store Connect data — public data can't show them. Prepare →
Fixes what's wrong before you submit: screenshots that violate a store rule, listing text over a limit, a keyword field wasting characters, a price that was never set deliberately per territory.
Subtitle, promotional text, the keyword field and real per-territory prices are never public — no catalogue lookup can show them, which is why this step exists at all. Importing fills every field on the tabs above and Pricing's current-price column, all at once.
- Generate a key in App Store Connect → Users and Access → Integrations → Team Keys. Give it the App Manager role — enough to read and edit listings, short of full Admin access.
- Save the downloaded
.p8file somewhere outside any git repository — e.g.~/.appstoreconnect/private_keys/— and runchmod 600on it. - Copy
.env.exampleto.envin the CLI's folder and fill in the Key ID, Issuer ID and the path to that file. - Run
appmates asc pull <bundle id> --out listing.json, then paste the file's contents into the box on the right.
Not sure how to do this yourself? Copy this into your coding assistant (Claude Code, Cursor, ...) — it has everything it needs to walk you through it:
Help me connect my AppMates dashboard to my real App Store Connect data: walk me through generating an API key in App Store Connect (Users and Access → Integrations → Team Keys, App Manager role), saving the .p8 file securely outside my repo, filling in the appmates CLI's .env file with the key id, issuer id and private key path, then running "appmates asc pull <my bundle id> --out listing.json" so I can paste the result into the dashboard.
Your private key never leaves your machine. It signs a short-lived
request token locally; only that token goes to Apple, straight from your computer.
This dashboard never talks to Apple and never sees the key — it only reads whatever
you paste into the box above, the same as any other text typed into this page. Full
detail: the CLI's README.md, section "asc — App Store
Connect, optional".
Every rule here reads the file's header, not its pixels, so a few hundred bytes answer locally what a multi-megabyte upload would have answered. That is also more correct: a fully opaque RGBA PNG is still rejected by Apple, so sampling pixels for transparency would give the wrong answer.
Apple indexes your app name, subtitle and the 100-character keyword field as one pool of words, then combines them. A phrase is reachable when each of its words is somewhere in the pool — the phrase itself never has to appear — a word already in your title is already indexed, and every space is overhead. The field is never shown to a user, so none of this is self-correcting.
Text overruns are the second most common cause of a blocked submission after malformed screenshots, and the limits differ per store — the same listing can pass Apple and fail Play. Fields above 90% of their ceiling are flagged too: translations commonly run 15–30% longer than English.
Only checks the store(s) above — uncheck one your app isn't on (Google Play for an iOS-only app, say) so a field that store requires but yours doesn't need stops being flagged. Remembered for next time.
Check multiple locales at once
Paste a {"locales": [...]} document — the same shape
appmates validate-metadata reads on the command line — to check every
localisation of a listing in one pass, instead of one at a time above.
Composed from whatever you've already entered on Screenshots, Keyword field and Listing text — nothing is re-typed here. Fill in any of those tabs and this one updates live, giving one combined go/no-go answer instead of three separate reports to read and reconcile by hand.
Apple and Google let you set a different price per storefront but give no guidance on what to set it to. This turns one price into a starting point per territory — a read-only sanity check to copy into App Store Connect or Play Console yourself. Nothing here ever calls either API.
Answers whether the market is worth entering, before you write any code: leader entrenchment, storefront-by-storefront difficulty, who holds the term and how they present it.
Answers what rank trackers structurally cannot: should I build this at all? They assume a live app — you cannot track the ranking of something that does not exist. This runs before the first line of code.
Every ASO tool asks how hard is this keyword? as though there were one answer. There are 175 storefronts and the answer differs in each — difficulty tracks the language a term is searched in more than the size of the country. That makes it a launch decision: which locale to write first, which language to localise screenshots into.
Deliberately slow: one request per storefront against a free endpoint that rate-limits, spaced politely apart. Cached afterwards.
Who holds a term, what the field does with its screenshots, and the vocabulary everyone agrees on. Dimensions are read from the screenshot URLs themselves — the catalogue encodes the served size — so describing a whole gallery costs no bandwidth.
n/a rather than shown as having none, and they are excluded from the
medians instead of counted as zeros. Only names and descriptions are public —
subtitles and keyword fields are not — so the vocabulary below is a floor on what
rivals target, not the whole of it.
Watches what happens after you ship: your position per keyword over time, and every closed test you have running — App Store or Play.
Every test you're running, App Store or Play, in one place — click one for its invite link and progress. Both stores gate that link the same way: a tester can't open it until you've added them by hand in that store's console first — Play Console's tester list, or App Store Connect's TestFlight testers. Nothing here can do that step for you; it only tracks where each test stands. Still need testers, or an app to test? That's a different page — Get testers / Be a tester is the actual two-sided marketplace, with real people requesting to join. This page is just your own manual log once a test is already underway, no account needed.
Get real closed testers before you ship, and real users for a launch or an update once you have. This is the one part of AppMates that needs an email — every other tool here never has, and never will. Already found testers some other way and just want to track invite links and progress? That's the personal, account-free Testers log under Track — this page is the marketplace itself: post here and real testers request to join.
Test other developers' apps to earn High Fives, then spend them getting your own app tested — browse listings, see who's topping the board, track what you're actively testing. Same account as Get testers, the tester half instead of the owner half — and browsing needs no account at all.
The bundled specification catalogue, with the date each store's rules were last verified against its official documentation. These numbers are generated from one source and drive both this page and the command-line tool.
Requests from the landing page's "Feature your app here" dialog. Approving one is
what puts it on the page — see routes/promo.js and
renderRails in landing.js.
Reported conversations
Flagged from a conversation's ⋯ menu in the Inbox. Nothing here is actioned automatically — this is a queue for you to read and follow up on by hand.
All listings
Every open listing on the marketplace, regardless of who posted it — for removing one directly, without waiting for a report to exist first.