| name | sales-daily-report |
| description | Generate the App Store sales & downloads daily report for all live apps. Use when the user asks for a sales report, a revenue/downloads summary, daily numbers across their apps, or "่ทๆฅๆฅ". |
Sales & Downloads Daily Report
Run one sales & download report covering every live app, output as markdown.
Step 0 โ Prerequisites (credentials must be configured)
Every step in this skill calls App Store Connect APIs. Before any other step, run:
python3 scripts/appmate_config.py check
If exit code โ 0, STOP. Do not invoke any other part of this skill, do not run scripts/sales_report.py. Tell the user AppMate credentials are not configured, show the precheck output verbatim, and tell them to invoke the appmate-setup skill. The downstream script also enforces this gate (exits 2 with the same message), but the explicit precheck saves you from spinning up the full 65-day fetch.
One-line summary
Pull ~65 days of daily reports from App Store Connect โ aggregate across 5 time dimensions โ totals + Top-3 apps + share + percentage change โ markdown report.
Input / Output / Trigger
| Item | Content |
|---|
| Trigger | python3 scripts/sales_report.py (0 args, 0 user intervention) |
| Input | data/apps_full.json (live-app list) + data/sales_cache.json (historical daily reports) |
| Output | stdout markdown + data/report.md file + Claude pastes the full markdown back into the conversation |
User intervention points
Zero. Fully automatic. The script generates the report โ the file lands โ Claude must paste the complete report into the conversation reply. It must not just say "saved to report.md" or post only a summary. The file is a side product; the conversation reply is the primary delivery.
The 5 time dimensions (fixed order, do not reorder)
| Dimension | Current range | Compared to |
|---|
| Yesterday | DATA_TODAY (most recent day with data) | the day before |
| Last 7 days | DATA_TODAY back 7 days | the prior 7 days |
| Last 30 days | DATA_TODAY back 30 days | the prior 30 days |
| This week | this Monday โ DATA_TODAY | (shows "Data not yet published by Apple" if this week's data is not in yet) |
| This month | the 1st โ DATA_TODAY | the entire previous month (not the same day range) |
Workflow (the script does this automatically in one pass)
- Load
data/sales_cache.json โ missing dates are fetched from ASC /v1/salesReports; gzipped TSV is decoded and cached; failed dates are recorded as _error and retried next run; empty caches for the last 3 days are auto-refreshed (Apple data can be delayed).
- Anchor DATA_TODAY โ scan backward from today for the first date that actually has data (Apple's daily report usually lags 1-2 days).
- Aggregate by day โ parse each TSV row (Title / Country Code / Units / Developer Proceeds ร FX โ USD); classify downloads by Product Type Identifier; merge IAP rows into their parent app via Parent Identifier (SKU).
- Slice + sum across the 5 dimensions, compute delta โ per dimension: total revenue + total downloads + previous-period percentage change + Top-3 (by revenue / by downloads).
- Render markdown per the template below.
Report template (v1 โ follow exactly)
Rendered in the same language the user has been using in this conversation. Default to English; if the user has been writing in Chinese / Japanese / Spanish / etc., translate the template headers, labels and prose accordingly. App / SKU / country names stay in their original form. The script itself emits English strings โ translate them on the fly when rendering back into the conversation reply if the user's language is not English.
Top one-liner (required)
**Yesterday ({MM-DD}) revenue ${X}** ยท this week ${X} ยท this month ${X}
If Apple has not published a range's data yet, that slot shows N/A and the per-dimension block prints > โณ Data not yet published by Apple.
Totals block (5 dimensions, fixed order)
## ๐งฎ Totals
### {dimension} ({range-compact})
- ๐ฐ Revenue: **{current revenue}** ยท {โโ N%}
1. **{revenue}** ({share}%) ยท {โโ N%} ยท {app name}
2. **{revenue}** ({share}%) ยท {โโ N%} ยท {app name}
3. **{revenue}** ({share}%) ยท {โโ N%} ยท {app name}
- ๐ฅ Downloads: **{current downloads}** ยท {โโ N%}
1. **{downloads}** ({share}%) ยท {โโ N%} ยท {app name}
2. **{downloads}** ({share}%) ยท {โโ N%} ยท {app name}
3. **{downloads}** ({share}%) ยท {โโ N%} ยท {app name}
Footer note (required)
> โ Revenue is multi-currency, converted to USD via approximate FX (not finance-grade). Apple daily reports lag 1โ2 days.
> This month compares against the **entire previous month**; last 7/30 days compare against the 7/30 days before that.
10 inviolable rules
- Headings stay in a single language โ match the user's conversation language; don't mix languages within a heading.
- No bar charts โ change is shown only as
โโ N%.
- No "current X vs previous Y" โ dates go only in the H3 heading parentheses.
- No "previous N" โ show only the current value plus the percentage change.
- Keep indentation โ the Top-3 list uses 4-space indentation, nested under the downloads/revenue bullet.
- Value first, app name last โ
{rank}. **{value}** ({share}) ยท {change} ยท {app name}.
- Revenue before downloads.
- App names keep their full original form, not truncated.
- Fixed emoji set: ๐ title / ๐ time / ๐
date / ๐ฑ app / ๐งฎ totals / ๐ฐ revenue / ๐ฅ downloads / โณ data not in / โ note.
- Must paste back into the conversation โ after running the script, Claude must paste the complete markdown report into the reply; "report.md generated" alone or a summary alone is not allowed.
Data handling details
- Revenue: each row's
Units ร Developer Proceeds, converted to USD via a static 40+ currency FX table. This is an estimate (not accounting-grade โ finance reconciliation uses /v1/financeReports), but cross-app relative comparison is reliable.
- IAP merging: an IAP row's
Title is the IAP product name; Parent Identifier is the parent app's SKU. IAP units go to iap_units; IAP revenue is folded into the app's revenue_usd.
- Download classification (by
Product Type Identifier): 1* / F1 / FI1 count as installs; 7* updates do not count; IA* IAP/subscription rows count toward revenue and iap_units but not downloads.
- Sorting: Top-3 is descending by current downloads / revenue within each dimension.
CLI
python3 scripts/sales_report.py
No arguments. All logic runs automatically.
Known limits
- Apple's daily sales reports lag 1-2 days (the script auto-anchors to the most recent day with data).
- Revenue is converted via a static FX table (not a reconciliation value).
- "This week" shows "data not in" early in the week before data arrives.
- Multi-currency refunds (negative Units) are subtracted automatically but not highlighted separately.
Connection to other workflows
- Upstream dependency: the
appmate-setup skill's ASC API credentials.
- Downstream: if an app's downloads/revenue drop sharply โ trigger
aso-daily-report to investigate the ASO side, or aso-optimize to redo the metadata.