Shopify revenue and refunds, traced to the visit that bought
Make an app with read_orders in Shopify's Dev Dashboard and Sumly reads every paid order and refund: revenue without tax, the Shopify Payments fee, the buyer's country, and the visit each order came from.
Two days later the same person ordered. The order counts for Instagram.
Connected in three steps
A read-only key, pasted once. Sumly does the rest.
-
1
In the Shopify Dev Dashboard (dev.shopify.com, signed in as the store's owner): Create app, name it Sumly. In its version, give it the Admin API scopes read_orders and read_all_orders only, release it and install it on your store.
-
2
Paste the app's Client ID and Client secret from its Settings, with the store's myshopify.com address. Sumly asks Shopify for a token that lasts a day, and asks again when it runs out.
-
3
An older custom app made in the store admin before 2026 works too: give it the same two scopes and paste its shpat_ token instead, leaving the Client ID empty.
-
4
To trace orders to visits, add the theme.liquid snippet shown with Sumly's Shopify integration: it puts the visitor on the cart as the attribute
sumly_visitor_id.
Puts the Sumly visitor on the cart, so the order counts for the visit that brought it.
<script>
// Sumly: remember which visit a Shopify order came from.
addEventListener('load', function () {
var id = window.sumly && window.sumly.visitorId;
if (!id || sessionStorage.getItem('sumly_cart') === id) return;
fetch(window.Shopify && Shopify.routes ? Shopify.routes.root + 'cart/update.js' : '/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ attributes: { sumly_visitor_id: id } })
}).then(function () { sessionStorage.setItem('sumly_cart', id); });
});
</script>
Or let your coding assistant do it
Paste this into Claude Code, Cursor or Codex in your project. It fits the code to how your project is built, asks you for the dashboard steps and leaves the keys to you.
See what it says
Set up Shopify for Sumly in this project.
Sumly (https://sumly.dev) shows revenue next to the visits and app users it came from. The full guide is https://sumly.dev/integrations/shopify; read it if anything below is unclear.
Steps:
1. In the Shopify Dev Dashboard (dev.shopify.com, signed in as the store's owner): Create app, name it Sumly. In its version, give it the Admin API scopes read_orders and read_all_orders only, release it and install it on your store.
2. Paste the app's Client ID and Client secret from its Settings, with the store's myshopify.com address. Sumly asks Shopify for a token that lasts a day, and asks again when it runs out.
3. An older custom app made in the store admin before 2026 works too: give it the same two scopes and paste its shpat_ token instead, leaving the Client ID empty.
4. To trace orders to visits, add the theme.liquid snippet shown with Sumly's Shopify integration: it puts the visitor on the cart as the attribute `sumly_visitor_id`.
theme.liquid: Puts the Sumly visitor on the cart, so the order counts for the visit that brought it.
```
<script>
// Sumly: remember which visit a Shopify order came from.
addEventListener('load', function () {
var id = window.sumly && window.sumly.visitorId;
if (!id || sessionStorage.getItem('sumly_cart') === id) return;
fetch(window.Shopify && Shopify.routes ? Shopify.routes.root + 'cart/update.js' : '/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ attributes: { sumly_visitor_id: id } })
}).then(function () { sessionStorage.setItem('sumly_cart', id); });
});
</script>
```
So each payment shows which visit it came from: Add the snippet below to your theme (Online Store → Themes → Edit code → theme.liquid, before </body>), on a store that has the Sumly script in its head. It puts the visitor on the cart as the attribute sumly_visitor_id; Shopify copies cart attributes onto the order, and Sumly reads them back. In the EU and UK there is a visitor only after they agree.
Keep in mind: Built from Shopify's GraphQL Admin API documentation and tested against responses shaped like it; it has not yet been tried on a live store. Tell us if a number looks off. No MRR: Shopify lets an app read only the subscription contracts it made itself, so subscriptions from Shopify Subscriptions, Recharge or other apps cannot be read. Their orders count as revenue, marked as subscription orders. Fees show only for Shopify Payments; other gateways report none to Shopify. Without read_all_orders, Shopify shows an app only the last 60 days of orders.
How to work:
- Look at how this project is built first, and fit the code to its framework and its way of doing things; the examples above are a starting point, not something to paste as is.
- Steps that happen in a dashboard (Sumly, or Shopify's own) are mine: tell me exactly what to click, then wait for me.
- The Shopify key goes into Sumly (Projects and payments), not into this project: Sumly reads Shopify itself. Your part in the code is only carrying the visitor into checkout, as above.
- Keys the code needs belong in environment variables, never in the code or the repository. Never ask me to paste a secret key into this chat; tell me which variable to set.
- Change only what this needs, show me the changes before you commit, and tell me how to check that it works.
What you see after connecting
Shopify next to every other project and provider, on the same pages.
Refunds
Every paid order without tax, with the buyer's name and country and the Shopify Payments fee, and refunds.
Metrics over time
Net and gross revenue, fees, refunds, customers, plans by product and a CSV export.
With the snippet in place
Revenue by source, campaign and country, and ROI for each cost.
No MRR, as subscription apps keep their contracts to themselves.
Which visit paid
Add the snippet below to your theme (Online Store → Themes → Edit code → theme.liquid, before </body>), on a store that has the Sumly script in its head. It puts the visitor on the cart as the attribute sumly_visitor_id; Shopify copies cart attributes onto the order, and Sumly reads them back. In the EU and UK there is a visitor only after they agree.
How attribution works →Counts toward your plan
Nothing: payments, customers and refunds never count toward your plan. Only the page views and app screens Sumly keeps do. Plans →
The details
What Sumly reads
- Paid orders, without tax, in your store's currency
- Each refund on the day it was made
- The fee Shopify Payments took on each order
- The buyer's name and country, and the cart attribute sumly_visitor_id
When Sumly reads Shopify
- Every 15 minutes. The first read takes three years of orders (with read_all_orders).
- Orders are read by the time they last changed, so a refund of an older order is picked up.
- Sumly asks Shopify for a new token each day with the app's client ID and secret.
- With the optional webhook (Order update), Sumly reads at once when an order changes.
How Shopify money is counted
- Orders
- An order counts when it is paid, partly refunded or refunded, on the day it was processed. Pending, authorized, partly paid, voided and test orders do not.
- Revenue
- The order total less tax, in the store's currency. Shipping stays in; discounts are already off.
- Fees
- What Shopify Payments took on the order's sales and captures. Other gateways show none.
- Refunds
- Each refund on its own day, without its share of tax.
- Subscriptions
- Not read, so no MRR. An order with a selling plan (a subscription app's order) is marked as a subscription order.
- Currency
- The store's currency, turned into euros at the European Central Bank's rate of the day.
Good to know
- Built from Shopify's GraphQL Admin API documentation and tested against responses shaped like it; it has not yet been tried on a live store. Tell us if a number looks off.
- No MRR: Shopify lets an app read only the subscription contracts it made itself, so subscriptions from Shopify Subscriptions, Recharge or other apps cannot be read. Their orders count as revenue, marked as subscription orders.
- Fees show only for Shopify Payments; other gateways report none to Shopify.
- Without read_all_orders, Shopify shows an app only the last 60 days of orders.
Shopify questions
Why the Dev Dashboard and not a custom app in the admin?
Shopify stopped new custom apps in the store admin on 1 January 2026. An app made in the Dev Dashboard and installed on your store is what replaces it. An older custom app keeps working: paste its shpat_ token.
Can Sumly change anything in my store?
No. The app has read_orders and read_all_orders, which only read orders, and Sumly never asks for more.
Why is there no MRR?
Shopify lets an app read only the subscription contracts it made itself. Contracts from Shopify Subscriptions, Recharge and other apps stay with those apps, so their orders count as revenue, not as MRR.
Does the webhook need Shopify's signing key?
No. The address Sumly gives you carries its own secret, and the webhook only tells Sumly to read now; orders are read from the API with your app.
Is this tested on a real store?
Not yet. It follows Shopify's GraphQL Admin API documentation and is tested against responses shaped like it. If a number does not match your store, tell us.
Other integrations
Try it with your own projects
Sign in with Google or a code by e-mail and connect your first project. Free for one project, and 14 days of a paid plan with no card.
Start freeOr look around first: open the live demo.