What App Store Connect sales reports actually contain (and what “units” means)
Apple counts first downloads, re-downloads, app updates and in-app purchases in one Units column. Here is how to read a sales report without inflating your download count by a multiple.
One column, four different events
An App Store Connect sales report is a tab-separated file with one row per product, per day, per storefront, and a column called Units. It is tempting to read that column as downloads. It is not downloads.
A first download, a re-download by someone who already owned the app, an app update, and an in-app purchase all arrive as units. The only thing separating them is a column called Product Type Identifier, whose values are short codes like 1, 3, 7 and IAY.
The practical consequence is a multiple, not a rounding error. An app shipping fortnightly updates to an installed base reports several times its real download count, and the excess is mostly a measure of how often the developer shipped. A dashboard that sums Units and calls the result downloads produces a number that is confidently wrong and looks like good news.
The identifiers that matter
Identifier 1 is a free or paid app on iOS, iPadOS, visionOS or watchOS — a genuine first download. 1F is a universal app excluding tvOS, 1T is iPad, F1 is Mac, and the 1E family is custom B2B distribution. These are the only rows that should ever be called a download.
Identifier 3 (and 3F) is a re-download: someone who already owned the app installing it again. It is not a new customer and it earns nothing.
The 7 family — 7, 7F, 7T, F7 — is an update of an installed app. This is usually the largest share of Units and the least interesting one.
IA1, IA1-M, FI1 and IA3 are one-off in-app purchases. IA9 and IA9-M are non-renewing subscriptions; IAY and IAY-M are auto-renewable ones, with IAC a legacy identifier for later subscription years. Recurring and one-time revenue behave nothing alike, so they are worth keeping apart even though both are money.
Apple adds identifiers as it adds platforms, so any mapping needs a rule for codes it has not seen. The safe rule is to leave them visible in an 'other' bucket beside their raw code: an unexplained bucket is a question somebody can answer, while a code guessed into 'download' is a number nobody questions.
In-app purchase rows do not name their app
The second trap is quieter. An in-app purchase row's Apple Identifier is the purchase product's own id, not the app's. The app is named by SKU, in a separate Parent Identifier column.
Key on Apple Identifier and you invent apps that do not exist and file the account's only real revenue under them. That is not hypothetical — it is exactly what the first version of Broctic's ingest did, and it produced three phantom apps in the dashboard before anyone noticed.
The fix is to learn the SKU-to-app mapping from Apple's app list and from every app row parsed, and to keep an unresolvable purchase under its own identifier rather than dropping it. An unattributed sale is a reporting problem you can see; a discarded one is a wrong total you cannot.
The dates are Pacific dates
Sales close at midnight Pacific, and each day's report publishes by 08:00 Pacific the next morning. Every date in the file is a Pacific date.
Computing 'yesterday' in UTC is therefore wrong for eight hours of every day, and the visible symptom is a tool that reports Apple as late when Apple is not, or shows an empty day that has simply not happened yet in Cupertino.
There is a second subtlety in the same area: Apple answers a request for a day with a 404 both when it has not published that day and when there genuinely were no sales. Nothing in the response distinguishes them, so the only honest resolution is the clock — before the publish deadline it is 'not published yet', after it, it is a real zero. Collapsing the two either invents a bad day or hides one.
Money: proceeds, customer spend, and restatement
The report carries what the customer paid and what the developer gets. The gap is Apple's commission — 15% under the Small Business Program and 30% standard — plus sales tax or VAT wherever the customer price includes it, so it should be shown rather than assumed: a constant is wrong for most accounts, and the tax share varies by storefront.
Amounts are in the storefront's currency, so a report for a global app is in a dozen currencies at once. Summing them without a rate produces a precise-looking number that means nothing. Converting at one closing rate for a whole month is also wrong, and does not reconcile; the defensible version is to convert each day at that day's reference rate and to keep the raw per-currency rows so the blend can be taken apart.
Finally, these figures are provisional. Apple restates recent days as payments settle, so a day should be replaced when re-fetched rather than merged — merging keeps both copies of a transaction that simply moved.