A 22-person retail SMB in Indore was holding a 45-minute Monday standup just to recap weekend sales. Founders flying in. Three department heads. One badly typed Excel sheet on a projector. We replaced it with a 14-node n8n workflow that runs at 7:50 am Monday, pulls Saturday and Sunday rows from Google Sheets, and pushes a structured WhatsApp summary to four numbers. The standup is gone. The recap takes 90 seconds to read.
TL;DR — what this n8n workflow actually does
It runs on a Monday morning Cron node, reads weekend rows from a Google Sheet that the shop floor already fills daily, computes 6 numbers (gross sales, returns, top SKU, worst day, payment mix, average ticket), formats a WhatsApp template, and posts it to a broadcast list of 4 founder numbers via the WhatsApp Cloud API. If anything fails, an error node DMs the operations head and writes the run to a logs sheet.
Why this matters now — November 2025
Two changes pushed this off the backlog. WhatsApp Cloud API rolled out marketing template categories with India-specific pricing in May 2025 — a "utility" category template is now billed per delivered message in India, so a four-recipient summary costs next to nothing each Monday. And n8n shipped v1.62 in October 2025 with a stabilised Google Sheets node that handles range references without the v0.x quirks. The cost-of-doing-this dropped at roughly the same time the cost-of-not-doing-this (a 45-minute meeting × 7 people × 4 weeks) became visible to the founder during a quarterly review.
A reddit thread from r/n8n in October 2025 ("anyone else replacing standups with n8n?") shows the same pattern across three small Indian shops, including a Surat textile trader who runs the equivalent flow on a Hetzner box.
The 4-block workflow
The actual n8n node JSON (3 critical nodes)
This is exactly what lives in the workflow JSON. Open n8n, paste the node objects into a new workflow, then wire them up.
Node 1 — Schedule Trigger
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "50 7 * * 1"
}
]
},
"timezone": "Asia/Kolkata"
},
"name": "Monday 7:50 IST",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [240, 300]
} Two things to notice. The cron expression is 50 7 1 — minute 50, hour 7, every month, every day, Monday only. The timezone field is critical — without it, n8n uses the server timezone (UTC if you are on Hetzner) and your Monday 7:50 IST run goes off at 1:20 pm. We made that mistake on the second client and had to dig through the logs to figure out why nothing fired on Monday.
Node 2 — Google Sheets read
{
"parameters": {
"authentication": "serviceAccount",
"operation": "read",
"documentId": {
"__rl": true,
"mode": "id",
"value": "1xJ_REDACTED_SHEET_ID"
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Daily_Sales"
},
"options": {
"rangeDefinition": "specifyRange",
"range": "A2:H8"
}
},
"name": "Read last 7 days",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [460, 300]
} We use a service-account credential, not OAuth2 — the workflow runs unattended and OAuth2 token-refresh failures during a long weekend would silently break the Monday job. Service-account creds need the sheet shared with the bot's email (looks like yourbot@yourproject.iam.gserviceaccount.com). The range A2:H8 reads exactly 7 rows after the header — keeps the payload tiny.
Node 3 — Code node (the 6-reduction)
{
"parameters": {
"jsCode": "const rows = items.map(i => i.json);\nconst weekend = rows.filter(r => {\n const d = new Date(r.date).getDay();\n return d === 0 || d === 6;\n});\nconst gross = weekend.reduce((s, r) => s + Number(r.amount || 0), 0);\nconst returns = weekend.reduce((s, r) => s + Number(r.returns || 0), 0);\nconst byDay = weekend.reduce((m, r) => { m[r.date] = (m[r.date]||0) + Number(r.amount); return m; }, {});\nconst worstDay = Object.entries(byDay).sort((a,b) => a[1]-b[1])[0];\nconst skuCount = weekend.reduce((m, r) => { m[r.top_sku] = (m[r.top_sku]||0) + Number(r.qty); return m; }, {});\nconst topSku = Object.entries(skuCount).sort((a,b) => b[1]-a[1])[0];\nconst tickets = weekend.reduce((s, r) => s + Number(r.tickets||0), 0);\nconst avgTicket = tickets ? Math.round(gross / tickets) : 0;\nconst upi = weekend.reduce((s, r) => s + Number(r.upi_pct||0), 0) / weekend.length;\nreturn [{\n json: {\n gross: gross.toLocaleString('en-IN'),\n net: (gross - returns).toLocaleString('en-IN'),\n returns: returns.toLocaleString('en-IN'),\n worstDay: worstDay ? worstDay[0] + ' (₹' + worstDay[1].toLocaleString('en-IN') + ')' : 'n/a',\n topSku: topSku ? topSku[0] + ' (' + topSku[1] + ' units)' : 'n/a',\n avgTicket: avgTicket.toLocaleString('en-IN'),\n upi: Math.round(upi) + '%'\n }\n}];"
},
"name": "Compute 6 numbers",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [680, 300]
}The output is a single item with 7 fields — gross, net, returns, worstDay, topSku, avgTicket, upi. We picked these after watching 4 weeks of standups and noting which numbers founders actually argued about.
Setting up the credentials (15 minutes, do this first)
The WhatsApp template — the exact body
n8n's WhatsApp Business Cloud node uses Meta's template syntax. Submit this in the Meta Business Manager template editor:
Header (TEXT): Weekend roll-up — Indore store
Body:
Hi {{1}},
Sat-Sun gross: ₹{{2}}
Net (after returns): ₹{{3}}
Returns: ₹{{4}}
Worst day: {{5}}
Top SKU: {{6}}
Avg ticket: ₹{{7}}
UPI share: {{8}}
— Auto from n8n at 7:50 IST. Reply STOP to mute.
Footer: Softechinfra workflow The template needs 8 variables. n8n's WhatsApp node maps them by index — {{1}} is the recipient first name, {{2}} is gross, etc. Keep the template under 1,024 chars or it will fail Meta review.
The cost — from one month of running
The Hetzner box runs 7 other client workflows in parallel — we apportion 1/8th. WhatsApp sends are cheap because Utility templates in India are the low-cost category. If you bumped this to a Marketing template (e.g., a sales push to customers), you would pay about 7x more per message. Categorise correctly.
The pre-flight checklist (we run this every time)
- Cron expression timezone is set to Asia/Kolkata, not server-default
- Google service-account JSON pasted into n8n, sheet shared with bot email
- WhatsApp template approved with category Utility (not Marketing)
- Recipient phone numbers verified opted-in (test message returns code 131000)
- Code node returns valid JSON for an empty weekend (we test by clearing rows)
- Error workflow set on the main workflow's Settings panel — points to a "send-to-ops" sub-flow
- Log sheet has columns date, recipient, status, message_id, error
- Workflow is saved, activated, and a manual test run completed in the last 24 hours
- Backup of workflow JSON exported to git the day of go-live
- Founders briefed on STOP keyword and how to mute
Common mistakes — symptoms first, fixes second
Symptom: "the workflow ran but nothing arrived." Cause: template not approved yet, or wrong category. Fix: log into Meta Business Manager, check the template status. If it shows Pending, wait. If Rejected, read the rejection reason — usually a banned word like "free" or "act now". Resubmit under Utility, not Marketing.
Symptom: "Monday at 7:50 nothing happens, nothing in logs." Cause: cron timezone is the server default (UTC), not IST. Fix: open the Schedule Trigger, set the timezone field explicitly to Asia/Kolkata. Save and re-activate.
Symptom: "first message goes through, others bounce with 131047." Cause: 24-hour opt-in window. Recipient sent a message to your business number more than 24 hours ago. Fix: use a template message (not a freeform one) — templates bypass the 24-hour rule for utility category. Our flow uses templates exclusively.
Symptom: "the Code node returns NaN for everything." Cause: Sheets returns empty cells as the string "", not as zero. Number("") is 0 but Number(undefined) is NaN. Fix: the || 0 fallback in the Code node above guards both cases. We left it in because we got bitten on a public-holiday weekend.
Symptom: "founders complain that Monday after a public holiday is wrong." Cause: long weekends include Monday in the dates we should have summed. Fix: change the filter to "last 3 days" if today is Tuesday after a Monday holiday, or maintain a simple holidays sheet and exclude business days. We added a 3-row "exceptions" tab in the same Google Sheet.
The mini case study — Indore retail SMB, 11 weeks live
The first install ran at the Indore client from August 11, 2025. Eleven Mondays later: zero missed runs, two template-rejection incidents (both fixed within 4 hours), one opt-in bounce we caught in the log sheet on day 4. Founders dropped the Monday standup permanently in week 3 — recouped 4 hours per week of senior team time. We extended the same workflow to a Coimbatore D2C client in October; their version has 17 nodes because they wanted a separate breakdown by sales channel (Shopify vs. retail vs. WhatsApp orders).
For more context on how we structure these flows, see our n8n receptionist build and the broader AI automation services page. The Indore project is one of several recent SMB engagements where the Softechinfra team has replaced a recurring meeting with a workflow.
When not to build this
Skip this workflow if (a) your weekend sales data is not already in a structured Sheet — building the data-entry hygiene takes 4x longer than the n8n piece, (b) your team is under 5 people and standups already take under 10 minutes — there is no time-saving to capture, or (c) your founders prefer face-to-face — automation does not fix a meeting that exists for political reasons. We turned down two clients in 2025 for reason (c). The workflow was technically easy; the human change wasn't.
For a similar small-team setup we shipped, see the Radiant Finance lead pipeline — same n8n stack, different use case.
FAQ
How long to build and deploy this n8n workflow end-to-end?
A first-time install takes 2 working days for us — half a day on Meta Business Manager template approval, half a day on the n8n flow, one day on testing across edge cases (empty weekend, public holiday, founder opt-out). For a self-build, budget 5-7 days including time spent on first-time WhatsApp Cloud API setup.
Can I run this on n8n Cloud instead of self-hosted?
Yes. n8n Cloud Starter handles 2,500 executions, well above what this single weekly workflow needs. The trade-off: cloud counts every WhatsApp status webhook (delivered, read) as an execution, so a busier installation can hit limits fast. Self-host if you plan to run more than 3-4 chatty workflows.
What if WhatsApp template review is rejected?
Most rejections come from words flagged as marketing — "discount", "free", "limited time". Strip those, add the explicit phrase "transactional update", resubmit. Approval is usually within 4 hours on the second submission. We have a checklist of safe phrases shared on request.
How do I test the workflow without spamming founders?
Use Meta's test phone number (provided in your WhatsApp Cloud API setup) for the first 5 runs. It accepts any inbound and shows the rendered message in your developer console. Switch to real numbers only after the template renders correctly twice in a row.
What is the right error-handling pattern for a Monday-only workflow?
Set an Error Workflow on the main workflow's settings — point it to a 3-node sub-flow that posts to a Slack channel and writes a row to an "errors" sheet. We do not retry the main flow automatically — Monday-only flows that fail benefit from human triage; an unattended retry could send the wrong week's numbers if the Sheet was being edited mid-run.
Why Google Sheets and not Airtable or Postgres?
Because the shop floor already filled the Sheet daily. Whatever data lives where the team naturally enters it — that is what your workflow reads. Migrating data entry to a "better" tool is a separate, much harder project. For a small retail team, Sheets wins because it is the path of least resistance.
Can this run on the Indian-region n8n cloud?
n8n Cloud regions are EU and US. Latency from India is 200-280 ms — fine for a once-a-week workflow. For latency-sensitive flows (real-time receptionists, live payment alerts) we self-host on Hetzner Singapore or AWS Mumbai instead.
Want this exact n8n workflow built and deployed?
We ship the weekend roll-up flow — n8n on your Hetzner box, Sheets read, WhatsApp template approval, founder onboarding — in 7 working days. Suitable for any retail or D2C SMB with 5+ founders or department heads in a recurring Monday meeting.
Book a 20-min CallFor the founder-perspective on why we automate small recurring meetings before complex workflows, see Vivek's writeup.
