Conflicts resolved for both sides: - cli/lib/plist.ts, cli/lib/zip.ts: one implementation each. plist reads XML (text or bytes, attributes tolerated) and binary plists; ads scan now reads bytes, so a binary Info.plist works too. zip gains unzip() for the Play report exports on top of zipEntries / zipRead. - apple upload waits with testflight wait's loop (waitForBuild) instead of its own copy; BUILD_DONE removed. - config, credentials (profiles, keystore, ASC_VENDOR_NUMBER, now also a profile key), command table, MCP tools, credentials template, README, CHANGELOG: union. - MCP: --write stays forbidden; the three pull tools are the listed local-file exception (LOCAL_WRITE_TOOLS), so scan --write remains unreachable. - Adapters and API coverage tables regenerated.
66 lines
5.7 KiB
Markdown
66 lines
5.7 KiB
Markdown
---
|
|
name: store-analytics
|
|
description: Take store analytics snapshots for a mobile app or game (App Store impressions, product page views, downloads and conversion through the Analytics Reports API; Google Play store listing visitors, acquisitions and installs from the Play reports bucket) and compare them with listing, screenshot and experiment changes from git; download App Store sales / finance reports and Play earnings / sales reports with a summary per product and currency. Use when the user asks whether a listing change, new screenshots or a store experiment worked, wants install / conversion numbers, sets up store reporting, or wants sales, proceeds or earnings numbers.
|
|
---
|
|
|
|
# Store analytics
|
|
|
|
CLI: `storebound analytics setup | snapshot | compare`. MCP: `analytics_snapshot`, `analytics_compare` (offline),
|
|
`analytics_setup`. Read-only on both stores except `setup` (creates the App Store report request). Snapshots go to
|
|
`.storebound/analytics/<date>.json` (gitignored; they are your business numbers).
|
|
|
|
## What is possible (and what is not)
|
|
- **App Store**: the Analytics Reports API. An Admin key creates one ONGOING report request (`storebound analytics
|
|
setup`); the first reports come 1-2 days later, then daily, and Apple keeps instances for 35 days, so take a
|
|
snapshot at least monthly (weekly is better). A request left unread for a long time stops
|
|
(`stoppedDueToInactivity`); `setup` makes a new one. storebound reads "App Store Discovery and Engagement" (Event
|
|
Impression / Page view, Counts and Unique Counts) and "App Store Downloads" (First-time Download, Redownload; updates
|
|
are left out), checks each segment's md5 checksum and keeps, per day, the newest processing of that day.
|
|
Conversion = (first-time downloads + redownloads) / unique impressions. Source:
|
|
https://developer.apple.com/documentation/appstoreconnectapi/downloading-analytics-reports
|
|
- **Google Play**: there is **no API** for store listing statistics (the Play Developer Reporting API only has
|
|
vitals). Play Console writes monthly CSV exports into your own Cloud Storage bucket; storebound reads them with
|
|
the service account. Setup: Play Console > Download reports > Statistics > **Copy Cloud Storage URI** and put the
|
|
bucket into `play.reportsBucket` (`pubsite_prod_rev_<number>`); the service account needs "View app information and
|
|
download bulk reports" (Play Console Help answer 6135870). Files appear with a few days' delay; the current month's
|
|
file grows daily. Conversion = store listing acquisitions / store listing visitors.
|
|
- **Not possible through any API**: Play store listing experiment results and App Store Product Page Optimization
|
|
results (read them in the consoles; `storebound apple ppo status` shows the App Store test state), Play
|
|
"Explore" search terms beyond the traffic source file.
|
|
|
|
## Flow
|
|
1. Once: `storebound analytics setup` (App Store) and `play.reportsBucket` (Play).
|
|
2. Weekly: `storebound analytics snapshot` (default the last 28 days; `--dry` prints totals only).
|
|
3. Change the listing as usual and commit it (`store/appstore.md`, `store/listing.md`, `store/shots/...`, the config).
|
|
One change at a time, with a clear commit subject ("new first screenshot: boss fight"), makes the comparison
|
|
readable.
|
|
4. `storebound analytics compare` (or `--md` for a report): for every commit that touched the store files, daily
|
|
impressions (App Store) or visitors (Play) and conversion in the 7 days before vs the 7 days from the change
|
|
(`--days 14` for small apps).
|
|
|
|
## Sales and finance reports
|
|
`storebound reports <apple-sales | apple-finance | play-earnings | play-sales>` downloads one report into
|
|
`.storebound/reports/` (gitignored: these files hold per-order rows and buyer locations) and prints a summary per
|
|
product and currency plus `<name>.summary.csv` (or `--csv <file>`); totals are never added across currencies. `--dry`
|
|
shows the request only. MCP: `reports`.
|
|
- **App Store**: `apple-sales [--type SALES] [--frequency DAILY|WEEKLY|MONTHLY|YEARLY] [--date ...]` (Sales and Trends;
|
|
other types: PRE_ORDER, SUBSCRIPTION, SUBSCRIPTION_EVENT, SUBSCRIBER, SUBSCRIPTION_OFFER_CODE_REDEMPTION,
|
|
WIN_BACK_ELIGIBILITY, each with Apple's fixed frequency and version) and `apple-finance --month YYYY-MM` (Apple
|
|
fiscal month; consolidated region ZZ, `--detail` for the Financial Detail report, region Z1). Needs a **team** API
|
|
key (not an individual key) with access to reports, and the vendor number (App Store Connect > Payments and
|
|
Financial Reports) as `ASC_VENDOR_NUMBER` in the environment, a credential profile (`--account`) or
|
|
`.storebound/credentials.json`, never in the config.
|
|
A 404 means "no report for that date" (no sales, or not out yet: daily reports come the next day).
|
|
- **Google Play**: `play-earnings --month YYYY-MM` / `play-sales --month YYYY-MM` read
|
|
`earnings/earnings_YYYYMM*.zip` and `sales/salesreport_YYYYMM*.zip` from `play.reportsBucket` and unzip them. The
|
|
service account needs "View financial data" in Play Console (Users and permissions). Earnings arrive early in the
|
|
next month; estimated sales update daily.
|
|
- Money numbers are the owner's: never paste them into issues, commits or public text.
|
|
|
|
## Read it honestly
|
|
- Small numbers swing: under a few hundred page views a week, a 20 % change is noise. Say so.
|
|
- Seasonality, featuring, ads campaigns, a rating drop and price changes move the same numbers. Look at the same
|
|
weekday span and mention other things that changed in that window.
|
|
- A before / after comparison is not an experiment. For a real answer use the store tests: Play store listing
|
|
experiments (Console) and App Store Product Page Optimization (`storebound apple ppo`, store-screenshots skill).
|
|
- Never present estimates as facts to the owner, and never put these numbers into public text (listings, replies).
|