How to Automate Auto-Calculate Monthly Sales Commissions with n8n

Sales commissions are a monthly tax on your operations team's sanity. Someone exports closed-won deals from HubSpot, drops them into a spreadsheet, applies tiered rate logic by hand, cross-checks agai

How to Automate Auto-Calculate Monthly Sales Commissions with n8n

Sales commissions are a monthly tax on your operations team's sanity. Someone exports closed-won deals from HubSpot, drops them into a spreadsheet, applies tiered rate logic by hand, cross-checks against last month, then emails finance and pings sales ops on Slack — every single month, on a deadline. This article shows you how to replace that entire ritual with one n8n workflow that runs on the 3rd of the month, unattended.

The Problem: Manual Commission Runs Don't Scale

The commission calculation itself isn't hard math. What breaks is everything around it. A rep closes eight deals across two tiers, one deal gets amended after the export, finance uses last month's rate table by accident, and now you have a payroll dispute and a Slack thread with 40 messages.

The core failures of a manual process are predictable:

  • Stale data. The export happens on a Tuesday but deals keep closing. Whatever number you calculated is already wrong.
  • Inconsistent tier logic. Tiered rates (say 5% up to $10k, 8% up to $50k, 12% above) get applied differently depending on who runs the sheet.
  • No audit trail. When a rep disputes a payout, nobody can reconstruct which deals were counted or which rate applied.
  • Deadline risk. Commission runs are time-boxed to payroll cutoffs. A sick ops person means a late payout and unhappy reps.

The problem is not the arithmetic. It's that a human is the integration layer between HubSpot, your rate table, finance, and sales ops — and humans forget, mistype, and take vacations.

The Solution: A Scheduled n8n Workflow

The workflow does exactly what your ops person does, in the same order, but deterministically. On the 3rd of every month it:

  1. Pulls every deal that moved to closed-won in the previous calendar month from HubSpot.
  2. Groups deals by owner and sums each rep's closed revenue.
  3. Applies your tiered commission rates in code, so the logic is identical every run.
  4. Builds a clean per-rep payout table.
  5. Emails the table to finance as a formatted summary.
  6. Posts a headline summary to your sales ops Slack channel.

Because it reads from HubSpot at execution time, the data is always current as of the 3rd. Because the tier logic lives in a code node, it never drifts. And because every run is logged in n8n's execution history, you get the audit trail for free.

Step-by-Step: Building It in n8n

You'll wire together six nodes. Here's each one and the configuration that matters.

1. Schedule Trigger. Add a Schedule Trigger node. Set the mode to Cron and use the expression 0 8 3 * * — that fires at 08:00 on the 3rd of every month. Running on the 3rd (not the 1st) gives late-posted deals from month-end time to settle in HubSpot.

2. HubSpot — Get Deals. Add a HubSpot node, resource Deal, operation Get All. Authenticate with a HubSpot Private App token (create it under Settings → Integrations → Private Apps with the crm.objects.deals.read and crm.objects.owners.read scopes). Enable Return All so pagination is handled automatically. Under Filters, add dealstage = closedwon and a closedate range covering the previous month.

3. Set — Compute the Date Window. Drop a Code node before HubSpot (or a Set node) to compute last month's first and last day as timestamps, then reference them in the HubSpot filter. This keeps the date range dynamic instead of hardcoded:

const now = new Date();
const first = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const last  = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59);
return [{ json: { start: first.getTime(), end: last.getTime() } }];

4. Code — Group and Apply Tiered Rates. This is the brain. Add a Code node (Run Once for All Items) that aggregates deal amounts per owner and runs each total through your tier table:

const tiers = [
  { upTo: 10000,   rate: 0.05 },
  { upTo: 50000,   rate: 0.08 },
  { upTo: Infinity, rate: 0.12 },
];

const byOwner = {};
for (const item of $input.all()) {
  const d = item.json;
  const owner = d.properties.hubspot_owner_id;
  const amount = parseFloat(d.properties.amount || 0);
  byOwner[owner] = (byOwner[owner] || 0) + amount;
}

const results = Object.entries(byOwner).map(([owner, total]) => {
  let remaining = total, commission = 0, prevCap = 0;
  for (const t of tiers) {
    const band = Math.min(remaining, t.upTo - prevCap);
    if (band <= 0) break;
    commission += band * t.rate;
    remaining -= band;
    prevCap = t.upTo;
  }
  return { json: { owner, revenue: total, commission: Math.round(commission * 100) / 100 } };
});
return results;

This is marginal tiering — each dollar is taxed at the rate for its band, the same way income tax brackets work. If your plan pays a flat rate on the whole amount once a threshold is crossed, swap the loop for a single lookup. Decide which model you use before go-live; this is the most common source of payout disputes.

5. Send Email — Finance. Add an Email (SMTP) or Gmail node. Build the body from the Code node output — an HTML table of rep, revenue, and commission plus a grand total. Set a clear subject like Commission Run — {{ $now.format('MMMM yyyy') }} so finance can file it. Attach a CSV using the Convert to File (Spreadsheet) node upstream if your finance team prefers to import it.

6. Slack — Sales Ops. Add a Slack node, operation Send Message, targeting your #sales-ops channel. Keep this one short: total commission pool, number of reps paid, and top earner. Slack is for the heads-up, email is for the record.

Connect them linearly: Schedule → Date Window → HubSpot → Code → Email, with a branch from Code into Slack. Test with a manual execution against last month's real data before you trust the schedule.

The Payoff: What You Actually Gain

Beyond getting an afternoon back every month, the structural wins matter more:

  • Zero drift. The tier logic is code. It calculates January exactly like it calculates December.
  • Fresh data by design. The workflow reads HubSpot at run time, so amended and late-closed deals are included.
  • A real audit trail. Every execution is stored in n8n with inputs and outputs — when a rep disputes a number, you open the run.
  • No key-person risk. The process runs whether or not anyone's at their desk on the 3rd.
  • Two audiences, two formats. Finance gets the detailed record, sales ops gets the summary — no one re-formats anything.

Common Pitfalls (and How to Avoid Them)

Deals with no amount or no owner. Closed-won deals sometimes have a blank amount or an unassigned owner. The Code node above defaults amount to 0, but add a filter or a warning branch so these show up instead of silently vanishing from someone's payout.

Timezone mismatches on closedate. HubSpot stores timestamps in UTC. If your team closes deals late on the last day of the month in a western timezone, a naive date window can drop or double-count them. Compute your window explicitly and confirm it against a known deal.

Marginal vs. flat tiering. As noted, these produce very different payouts. Confirm the intended model with whoever owns the comp plan and document it in a note node inside the workflow.

HubSpot pagination. If you forget Return All, you'll only get the first 100 deals and quietly underpay everyone. Always verify the deal count against a HubSpot report on the first run.

Silent failures. A schedule that fails at 08:00 with nobody watching is worse than a manual run. Add an Error Trigger workflow that posts to Slack the moment any node throws, so a broken run pages you instead of surfacing as a missing payout.

Build it once, test it against a real month, add the error alert, and commission season stops being an event. It becomes a notification.

n8n Lead Starter Kit — 3 No-Code Lead Automations
PRONTO PARA USAR

Ja construimos isso pra voce

Nao comece do zero. O n8n Lead Starter Kit — 3 No-Code Lead Automations e um workflow n8n pronto para instalar — conecta suas ferramentas em minutos, sem codigo.

Instalar por $9 →