TL;DR: A Shopify daily sales report Telegram n8n workflow pulls yesterday’s orders from your Shopify Admin API, calculates revenue, order count, AOV, top product, and refund totals, then posts a formatted summary to your Telegram chat every morning at 8 AM. Setup takes about twenty minutes, runs free on self-hosted n8n, and replaces the three dashboards most store owners refresh manually before their first coffee.
What this workflow does
Every morning at the same time, the workflow queries the Shopify Admin API for orders created in the previous 24 hours. It aggregates the raw order data into the numbers a store owner actually reads: gross revenue, net revenue after refunds, number of orders, average order value, best-selling product by units, best-selling product by revenue, and the split between new vs returning customers. Those numbers land in a single Telegram message on your phone before you open your laptop.
Unlike Shopify’s native email reports, this one is on Telegram (so you see it instantly), it includes yesterday only (not a rolling 30-day view), and the format is fully editable. If you want refunds broken down by reason, or a per-staff-member sales total, or a flag when revenue drops below a threshold, you change one node. No subscription, no third-party dashboard.
Why it beats the default Shopify report
Shopify Admin gives you analytics inside the dashboard and an optional daily email summary. Both have real limitations for an operator running more than one store or glancing at numbers on a phone:
The native email arrives at an hour you cannot control, it is missing the refund figure for the same day, and it does not adapt to the timezone of your warehouse if that differs from your store currency. The dashboard is fine at a laptop but heavy on mobile. Third-party apps like Lifetimely or Polaris cost $30 to $120 a month for what is, at its core, a SQL query and a formatted message.
Running this on n8n for Shopify automation gives you the exact numbers you want, on the channel you already check, at the hour you pick, for zero recurring cost. And because the workflow lives in your own n8n instance, adding a second store means duplicating two nodes, not buying a second seat.
What you need before you start
You need a running n8n instance (self-hosted or cloud), a Shopify store where you are the owner or have a staff account with read access to orders and products, and a Telegram account. Budget ten minutes to create a custom Shopify app for API credentials and five minutes to create the Telegram bot. Total prep time is under twenty minutes if you are comfortable copying tokens between browser tabs.
For the Shopify side you will create a custom app inside Shopify Admin and grant it read_orders, read_products, and read_customers scopes. Shopify issues an Admin API access token that n8n uses as a Bearer credential. For Telegram you talk to BotFather, get a bot token, then send your bot a message and grab the chat ID from the getUpdates endpoint.
Node-by-node list
The finished workflow has seven nodes. Here is what each one does and why it exists.
Schedule Trigger: fires once a day at 08:00 in your store timezone. You set the timezone inside n8n settings, not in the node, so every scheduled workflow agrees on time.
Set – Date Window: computes the ISO string for “yesterday 00:00” and “yesterday 23:59:59” in your timezone. Using a dedicated Set node keeps the date math in one place, which matters when daylight saving shifts or when you move the workflow to a new server.
HTTP Request – Shopify Orders: calls GET /admin/api/2024-10/orders.json with status=any, created_at_min, and created_at_max query parameters. Using HTTP Request instead of the Shopify node gives you control over pagination and field selection, which matters for high-volume stores.
Code – Aggregate Metrics: JavaScript that reduces the orders array into the numbers you want in the report. It sums total_price, counts orders.length, divides for AOV, iterates line_items to find the top product by units and revenue, and separates refunded amounts using refunds[].transactions[].amount.
HTTP Request – Refund Totals: optional second call to /admin/api/2024-10/orders.json?financial_status=refunded&processed_at_min=... for refunds processed yesterday on orders created earlier. You merge this into the main totals in the Code node.
Set – Format Message: builds the Telegram message string with markdown. Emojis are optional, but a green circle for revenue up vs red for revenue down makes the message readable at a glance.
Telegram – Send Message: posts to your chat with parse_mode: "Markdown". Disable web page preview in the node options so any store URL in the message does not generate a huge preview card.
Step-by-step build
1. In Shopify Admin, go to Settings, Apps and sales channels, Develop apps, Create an app. Name it “n8n Daily Report”. Under Configuration grant read_orders, read_products, read_customers. Install the app. Copy the Admin API access token that starts with shpat_.
2. In n8n, create a new credential of type “Header Auth”. Name header X-Shopify-Access-Token, value is the token from step 1. Save.
3. Open Telegram, search @BotFather, send /newbot, give it a name, copy the HTTP API token it returns. Send your new bot any message, then open https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates in a browser to grab the chat.id of your chat.
4. Create a new n8n workflow. Add a Schedule Trigger node set to “Every Day at 08:00”.
5. Add a Set node. Create two string fields: fromISO with value ={{ DateTime.now().setZone('Africa/Casablanca').minus({days: 1}).startOf('day').toISO() }} and toISO with value ={{ DateTime.now().setZone('Africa/Casablanca').minus({days: 1}).endOf('day').toISO() }}. Replace the zone with your own.
6. Add an HTTP Request node. Method GET. URL https://YOUR-STORE.myshopify.com/admin/api/2024-10/orders.json. Authentication: Generic, Header Auth, credential from step 2. Query parameters: status=any, created_at_min={{$json.fromISO}}, created_at_max={{$json.toISO}}, limit=250, fields=id,total_price,subtotal_price,currency,line_items,customer,refunds,created_at.
7. Add a Code node. Paste the aggregation script (included in the downloadable JSON template). The script returns one item with fields revenue, orders, aov, topProduct, newCustomers, refunded, net.
8. Add a Set node that builds the message. Example value for a text field: 📊 *Daily Sales — {{$json.date}}*\n\nOrders: *{{$json.orders}}*\nRevenue: *{{$json.currency}} {{$json.revenue}}*\nRefunded: {{$json.currency}} {{$json.refunded}}\nNet: *{{$json.currency}} {{$json.net}}*\nAOV: {{$json.currency}} {{$json.aov}}\n\nTop product: {{$json.topProduct}}\nNew customers: {{$json.newCustomers}}.
9. Add a Telegram node. Operation: Send Message. Chat ID: your ID from step 3. Text: ={{$json.text}}. Additional Fields: Parse Mode Markdown, Disable Web Page Preview true. Save the credential with your bot token.
10. Run the workflow manually with a date window you know contains orders. Verify the Telegram message matches what you see inside Shopify Admin Analytics for the same day. Activate the workflow.
Common mistakes
The timezone trap catches everyone. If your n8n server runs UTC but your store reports in Casablanca or New York time, a naive new Date() call returns yesterday according to the server, not according to your store. Always set the zone explicitly with Luxon inside the Set node, and match it to your Shopify store locale.
Pagination is the second trap. Shopify returns a maximum of 250 orders per call. A store doing more than that in 24 hours needs pagination via the Link header or via cursor-based queries using page_info. The downloadable template includes a loop node for stores above this volume.
Refund logic is the third. The total_price on an order does not change when a refund happens. You have to sum refunds[].transactions[].amount separately and subtract from the gross. Skipping this step produces a revenue number that looks great but is wrong by the end of the first refund-heavy week.
The fourth mistake is sending the report from a bot you added to a group without disabling privacy mode. Telegram group bots cannot see their own outgoing messages correctly in some clients when privacy is on. For a daily report, send to a private chat with yourself or to a small ops group where you have toggled privacy off in BotFather with /setprivacy.
Cost at realistic volume
A store doing 100 orders a day makes 2 Shopify API calls per run, well under the 40 calls per second limit on the standard plan. One Telegram message costs zero. Self-hosted n8n on a $5 VPS handles hundreds of workflows like this without breathing hard.
If you run n8n Cloud instead, the workflow uses roughly 4 executions per day (trigger plus pagination on a busy day), which fits inside every n8n Cloud tier. Annual cost at the Starter tier prorated for this workflow alone is under $2. Compared to a $30 per month Shopify analytics app, the payback is the first day.
Get the ready-to-import template
The complete JSON template, a setup PDF, and a credentials guide are bundled on our downloads page. Import the JSON into n8n, paste your tokens, change the timezone string, and activate. Two minutes from download to first report.
If you want it installed for you on your own n8n server (or you want the two-store, multi-currency version with a weekly rollup on Sundays), the team at easyworkflows handles the install, credentials, and first test run. See our services page for options.
FAQ
Does this work with Shopify Plus?
Yes. The Admin API endpoint is identical across Shopify Basic, Shopify, Advanced, and Plus. Plus stores often want the multi-location inventory and per-channel sales variant, which the extended template includes. API rate limits are also higher on Plus, so pagination for very large order volumes is faster.
Can I send the report to Slack instead of Telegram?
Yes. Replace the Telegram node with a Slack node, map the same text field to the Slack message body, and switch Markdown to mrkdwn syntax in the formatting node (Slack uses *bold* without underscores around italics). Everything upstream stays identical.
What if I want the report weekly instead of daily?
Change the Schedule Trigger to “Every Week on Monday at 08:00” and change the date window in the Set node to seven days back instead of one. The aggregation code works the same way because it reduces any order array into one summary.
How do I add a comparison with the previous day?
Add a second HTTP Request that pulls the day before yesterday using a different date window, run it through a duplicate of the Code node, and reference both in the format node. A simple percentage change calculation gives you the up/down arrow most operators want to see first.
Is this compliant with Shopify API policies?
Yes. The workflow uses the Admin API with scopes you granted in a custom app you own. There is no scraping, no reselling of data, and no third-party sharing. You stay inside the Shopify Partner Program terms because the app is private to your store.
Related guides
For more Shopify workflows, see the Shopify category on easyworkflows. The order risk alert template and the new customer welcome email workflow pair well with this report: together they cover the three things a store operator checks first thing in the morning. Revenue, risk, and who just signed up.