In May 2025 Shopify's admin replaced the printed Financial Summary with an on-screen Finances summary.
So I built a page that reproduces it from the Admin GraphQL API. Matching Shopify's figures turned out to be mostly a question of definitions and dates, not arithmetic.
Money and signs
Every amount comes back as shopMoney.amount, a string. scalars/Decimal describes it as "A signed decimal number, which supports arbitrary precision and is serialized as a string."
I never add those strings as floats. I parse each one into integer minor units, sum integers, and only format at the end. The precision comes from Intl: 2 for USD, 0 for JPY, 3 for KWD.
The second rule is about signs. Every reduction is stored as a negative number: discounts, returns, shipping discounts, reversed tax, refunded payments. Then every formula adds its parts. Net sales is gross sales + discounts + returns.
Every figure has its own date
Each figure is posted to the day of the event that produced it, read in the store's time zone from Shop.ianaTimezone:
| Event | Dated by | Fallback |
|---|---|---|
| Sale | Order.processedAt |
createdAt |
| Refund (return, cancellation, refunded shipping, tax, duties, adjustment) | Refund.processedAt |
Refund.createdAt |
| Units removed with no refund | Order.cancelledAt |
the sale's date |
| Payment | OrderTransaction.processedAt |
createdAt |
An order sold before the range still brings its refunds and payments inside it.
Gross sales, discounts and returns
Shopify's Finances report defines gross sales as "product selling price x ordered quantity. Gross sales does not include discounts, sales reversals, taxes, shipping, or fees."
I sum LineItem.originalTotalSet over product lines, on the sale date. The reference says it is "the total price of the line item when the order was created. This value doesn't include discounts."
Discounts, in the same report, are "product discount + the product's proportional share of a cart-wide discount." I take them from each product line's discountAllocations. Whether they always carry the line's share of an order-level discount is not confirmed.
Returns are where the names drift. The Finances report calls the line Sales reversals: "The value of goods returned by a customer." The Sales report is wider: "All order adjustments that result in negative monetary value. Sales reversals include the value of returned products, as well as order cancellations, edits, adjustments to shipping, taxes, fees, and discounts."
For each refund line I take minus RefundLineItem.subtotalSet, dated at Refund.processedAt. restockType splits it in two. CANCEL is "The refund line item was canceled. Use this when restocking unfulfilled line items." Those lines go to cancellations, and the rest to returned goods.
One deliberate difference: Close of Day keeps shipping, tax and fee reversals in their own lines, under Shipping, Taxes and Additional fees. So its Returns can be smaller than Shopify's Sales reversals, while Total sales is the same either way.
Net sales then follows the Finances report: "gross sales - discounts - sales reversals. Net sales does not include shipping charges or taxes."
Prices that include tax
When Order.taxesIncluded is true, each line's tax is taken out of its discounted total to give net. Gross is scaled by the same ratio, and the discount is gross minus net.
Shopify's page on this says "Setting up your prices to include taxes doesn't affect your tax reporting." It does not say how gross sales is computed. So the scaling is my assumption, and it is on the list of things I still have to check against a real store.
Taxes, shipping and total sales
Shipping uses the Sales report's formula: "shipping charges - shipping discounts - refunded shipping amounts". Shipping discounts live here, not in Discounts.
Taxes, in the Finances report, are "The taxes associated with a sale or return." It adds: "If a refund is processed for a line item, then only the tax that's associated with that line item is refunded." So I count TaxLine.priceSet on the sale date and subtract RefundLineItem.totalTaxSet and the refunded shipping tax on the refund date.
Total sales is where the pages disagree. The Sales report gives "gross sales - discounts - sales reversals + taxes + duties + shipping charges + fees". The analytics field says "Formula: net sales + additional fees + duties + shipping charges + taxes". The Finances report gave me "gross sales - discounts - sales reversals + taxes + shipping charges + fees." with no duties. I follow the Sales report and include duties.
Not sales: gift cards and tips
The Finances report is direct: "Selling a gift card isn't counted as a sale because it's a liability." Lines with LineItem.isGiftCard never enter gross sales.
Paying with a gift card is the other way round. The Sales report says "It's included in sales reports. The full value of the item is claimed as sales." And the Finances report: "The amount paid by gift card is included in the Payments finance report as a gift card entry." Sales are built from the order's lines and never look at how the order was paid.
Tips are reported as "The total value of tips received". I keep them out of gross and total sales. That is inferred, not quoted: a tip line has no product, and the report shows tips on their own cards.
Payments are a different question
The Finances report groups payments by "Payment method" and shows gross payments, refunds and net payments. Gross payments is "The amount paid by the transactions before refunds." Net payments is "total amount paid - the total amount refunded".
I read Order.transactions, keep only status SUCCESS with test false, date each one by OrderTransaction.processedAt, and group by gateway. The gateway label on the page is formattedGateway. SALE and CAPTURE add to collected, REFUND adds a negative amount to refunded, and authorizations and voids are skipped. Net is collected plus refunded.
What I could not settle
- Whether Shopify dates a sale by
Order.processedAtin the store's IANA time zone. The pages say only "for the day that they were made". - Whether the Payments report dates a payment by
OrderTransaction.processedAt. - Whether
RefundLineItem.subtotalSetis after the line's discounts, and includes tax when prices include tax. Its description is only "The subtotal price of a refunded line item". - Whether an order adjustment on a refund carries its own sign, and whether Shopify's total sales includes it.
Where to find all of it
The full table, with every quote and its source page, is at https://daybook.bananafest-destiny.com/definitions.
The page itself is Close of Day, https://daybook.bananafest-destiny.com/ : a one-page day or month summary that prints. It is $9 a month after a 14-day free trial, billed by Shopify. It is not yet on the Shopify App Store.
Top comments (0)