Weekly Pipeline Report
Every Monday at 9 AM this Zap pulls every open deal from Zoho CRM, totals it by stage, logs a dated snapshot to Google Sheets and posts one summary to Slack, including the weighted pipeline.
All 7 builds
- 18 open deals across six stages
- ₱312,700 raw pipeline value
- ₱176,045 weighted pipeline, 56% of raw
The problem
“How much of the pipeline is real?”
Every week someone opens the CRM, filters open deals, copies them to a spreadsheet, groups and totals them, then types a summary into Slack. It gets skipped on busy weeks, and each week overwrites the last, so there’s no history.
Raw pipeline also overstates things. A deal that just entered Qualification at 10% likely isn’t worth the same as one in Negotiation at 90%. Weighted value is amount × stage probability.
The numbers
Raw versus weighted, by stage
| Stage | Probability | Deals | Raw ₱ | Weighted ₱ |
|---|---|---|---|---|
| Qualification | 10% | 3 | 42,300 | 4,230 |
| Needs Analysis | 20% | 3 | 30,950 | 6,190 |
| Value Proposition | 40% | 3 | 46,450 | 18,580 |
| Identify Decision Makers | 60% | 3 | 55,650 | 33,390 |
| Proposal / Price Quote | 75% | 3 | 66,400 | 49,800 |
| Negotiation / Review | 90% | 3 | 70,950 | 63,855 |
| Total | 56% | 18 | 312,700 | 176,045 |

Under the hood
Seven steps, one loop
Step 3 · Code by Zapier · JavaScript
const deals = JSON.parse(inputData.dealsJson).data || [];
const openStages = ["Qualification", "Needs Analysis", "Value Proposition",
"Identify Decision Makers", "Proposal/Price Quote", "Negotiation/Review"];
const today = new Date().toISOString().split('T')[0];
const summary = {};
openStages.forEach(s => summary[s] = { count: 0, total: 0, weighted: 0 });
deals.forEach(d => {
if (!summary[d.Stage]) return; // skips Closed Won / Closed Lost
const amt = parseFloat(d.Amount) || 0;
const prob = parseFloat(d.Probability) || 0;
summary[d.Stage].count += 1;
summary[d.Stage].total += amt;
summary[d.Stage].weighted += amt * (prob / 100);
});
// parallel arrays: index i of every array = one sheet row
const dates = [], stages = [], counts = [], totals = [], weighted = [];
let gC = 0, gT = 0, gW = 0;
openStages.forEach(s => {
const v = summary[s];
dates.push(today); stages.push(s); counts.push(v.count);
totals.push(v.total.toFixed(2)); weighted.push(v.weighted.toFixed(2));
gC += v.count; gT += v.total; gW += v.weighted;
});
dates.push(today); stages.push("TOTAL"); counts.push(gC);
totals.push(gT.toFixed(2)); weighted.push(gW.toFixed(2));
return { dates, stages, deal_counts: counts, total_values: totals,
weighted_values: weighted, grand_count: gC,
grand_total: gT.toFixed(2), grand_weighted: gW.toFixed(2) };
Live test
7 rows written, 1 message sent
Eighteen open deals, three per stage, with uneven amounts, plus two Closed Won deals the report had to ignore. Every number was checked by hand before the run.



What broke
The first build didn’t work
Seven rows came out as one
The Code step returned seven objects to “Create Multiple Rows”, but Code hands off one bundle per run, so only Qualification landed. Parallel arrays into Looping, with a single-row action inside the loop, fixed it.
The Code step plates seven dishes on one tray; Looping serves them one at a time.


Two fields with almost the same name
Inside the loop I first mapped “Preview Loop Values”, which holds the whole list. The plainly named field holds the current pass’s value.


“Last” versus “Is Last”
The first filter used Loop Iteration Last, which is the count (7). Any non-zero number reads as true, so all seven passes would have posted. The test output showed 7, not true or false.
A green test result can still be the wrong result.


Old test data would have wrecked the totals
Zoho showed 26 deals instead of 20. Leftovers from an earlier project carried amounts up to ₱1,075,000, more than the whole real pipeline. Identified by naming pattern and deleted before building.
No “run now” for a weekly schedule
To prove the full seven-pass run, I moved the schedule a few minutes ahead, watched it fire, then set it back to Monday.
Known limits
What I’d change for production
Task usage
Each loop pass counts as tasks, so a run costs about 7× a single pass.
200-deal ceiling
One API call returns 200 deals. A bigger pipeline needs pagination.
Hard-coded stages
A new Zoho stage must also be added to the code, or its deals are skipped.
Cost
₱0 to build on trials and free tiers; roughly $49/month on a paid Zapier plan to run.
TaskFlow and every company and person shown are fictional mock data. Built on Zoho CRM Free, Slack and a Zapier Professional trial; the Zaps are switched off now the trial has ended, and every screenshot comes from the real Zapier, Zoho and Slack accounts.
Hiring, or have a process to automate?
