Skip to content
E
ES
All Articles
n8n CRM integration automated reports HubSpot

How to Connect Your CRM to n8n and Automate Client Reports (2025 Tutorial)

February 21, 202615 min read

Last updated: FEB 21, 2026

TL;DR: You can connect HubSpot, Pipedrive, Salesforce, or GoHighLevel to n8n and build a fully automated weekly CRM report delivered via email and Slack. This tutorial walks through the exact 9-node workflow. For agencies managing 8+ clients, this eliminates 4-10 hours of manual reporting per week permanently.

How to Connect Your CRM to n8n and Automate Client Reports (2025 Tutorial)

Every agency hits the same wall eventually. You spend hours each week pulling numbers out of your CRM, pasting them into a spreadsheet, formatting a PDF, and emailing it to clients — only to do it again next Monday. It is repetitive, it is error-prone, and it is time your team should be spending on actual client work.

n8n CRM integration solves this completely. n8n is an open-source, self-hostable workflow automation platform with native nodes for every major CRM: HubSpot, Pipedrive, Salesforce, GoHighLevel, and more. You can build a workflow that runs on a schedule, pulls fresh CRM data, assembles a formatted report, and delivers it to clients via email or Slack — without any manual intervention.

This tutorial walks you through exactly how to do it.


Why Automate CRM Reports in the First Place

Manual reporting is one of the highest-cost, lowest-value tasks in an agency. Consider what actually happens when a team member builds a report by hand:

  1. They log into the CRM and navigate through multiple views
  2. They export or copy figures for each pipeline stage, deal count, and contact metric
  3. They open a spreadsheet or slide deck and repopulate it
  4. They double-check the numbers, format the layout, and write a summary
  5. They send it out and answer follow-up questions when something looks off

For a team managing eight clients, that is anywhere from four to ten hours per week — every week. Automate it once and you reclaim that time permanently. (Not sure what a full reporting automation stack costs? Our workflow automation pricing guide has the real numbers.)

Beyond the time savings, automated CRM reports have a harder-to-quantify benefit: consistency. Automated reports always use the same data query, the same formatting logic, and the same delivery schedule. Clients get reliable, predictable communication, which builds trust.

With n8n, the economics are also favorable. Unlike Zapier, which charges per task, n8n charges per full workflow execution. A complex report workflow with dozens of internal steps costs the same as a simple two-node workflow — a significant advantage when your reporting logic gets sophisticated.


Which CRMs Work With n8n

n8n has native built-in nodes for all the CRMs agencies commonly use. Here is a quick breakdown:

HubSpot

The HubSpot node in n8n supports 18 triggers and 31 actions, covering contacts, deals, companies, lists, engagements, and tickets. The HubSpot Trigger node fires on events like new contact created, deal stage updated, or deal won/lost. This makes HubSpot the most fully-featured CRM integration in n8n and the ideal choice for building automated reports.

Authentication uses a HubSpot Private App token, which you generate inside your HubSpot account under Settings > Integrations > Private Apps.

Pipedrive

The Pipedrive node (n8n-nodes-base.pipedrive) supports creating, updating, reading, and deleting activities, deals, notes, organizations, persons, and leads. The Pipedrive Trigger node fires on deal stage changes, new persons, and new activities. Authentication uses a Pipedrive API token found in your account Settings > Personal Preferences > API.

Salesforce

The Salesforce node gives you access to accounts, contacts, leads, opportunities, cases, and custom objects via SOQL queries through the HTTP Request node. Salesforce authentication in n8n uses OAuth2, which you configure through a Connected App in your Salesforce org. Salesforce is the most configuration-heavy of the four but supports the most granular data extraction.

GoHighLevel (HighLevel)

The HighLevel node (n8n-nodes-base.highLevel) is purpose-built for agency use cases. It covers contacts, opportunities, pipelines, and sub-accounts. Because GoHighLevel is agency-native — with sub-account structures mirroring your client roster — it is particularly well-suited for building per-client automated reporting workflows.


Step-by-Step: Automated Weekly HubSpot Report Workflow

The workflow below runs every Monday morning, pulls the previous week's deal and contact data from HubSpot, formats a summary report, and sends it via email and Slack. We will walk through every node. (For a broader reporting architecture that also covers ad platforms and Looker Studio visualization, see our fully automated client reporting blueprint.)

Prerequisites

  • An n8n instance (self-hosted or n8n.cloud)
  • A HubSpot account with a Private App token
  • A Gmail or SMTP email account (or Resend/SendGrid)
  • A Slack workspace with a bot token
  • Basic familiarity with n8n's canvas interface

Node 1: Schedule Trigger

Node type: Schedule Trigger (n8n-nodes-base.scheduleTrigger)

This is the entry point of your workflow. Configure it to fire every Monday at 8:00 AM in your timezone.

Configuration:

  • Trigger Interval: Weeks
  • Weeks Between Triggers: 1
  • Trigger at Day: Monday
  • Trigger at Hour: 8
  • Trigger at Minute: 0
  • Timezone: Set to match your agency's local timezone

For more granular control, switch to the custom Cron expression mode and enter 0 8 * * 1 — this translates to "at 08:00 on every Monday."


Node 2: Set Date Range

Node type: Code (n8n-nodes-base.code)

Before querying HubSpot, you need to calculate the date range for "last week." n8n's Code node lets you write plain JavaScript to derive these values dynamically.

const now = new Date();

// Start of last week (Monday 00:00:00 UTC)
const startOfLastWeek = new Date(now);
startOfLastWeek.setDate(now.getDate() - now.getDay() - 6);
startOfLastWeek.setHours(0, 0, 0, 0);

// End of last week (Sunday 23:59:59 UTC)
const endOfLastWeek = new Date(startOfLastWeek);
endOfLastWeek.setDate(startOfLastWeek.getDate() + 6);
endOfLastWeek.setHours(23, 59, 59, 999);

return [{
  json: {
    startDate: startOfLastWeek.toISOString(),
    endDate: endOfLastWeek.toISOString(),
    startTimestamp: startOfLastWeek.getTime(),
    endTimestamp: endOfLastWeek.getTime(),
    weekLabel: `Week of ${startOfLastWeek.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}`
  }
}];

This outputs a clean date range object that all downstream HubSpot queries will reference.


Node 3: Get New Contacts (HubSpot)

Node type: HubSpot (n8n-nodes-base.hubspot)

Configuration:

  • Resource: Contact
  • Operation: Get Many
  • Return All: false
  • Limit: 100
  • Additional Fields > Filter Groups: Add a filter where createdate is BETWEEN your start and end timestamps from Node 2

In the filter value fields, reference the Code node output using n8n expressions:

  • {{ $node["Set Date Range"].json.startTimestamp }}
  • {{ $node["Set Date Range"].json.endTimestamp }}

Output: An array of contact objects, each containing firstname, lastname, email, hs_lead_status, lifecyclestage, and createdate.


Node 4: Get Deals Created Last Week (HubSpot)

Node type: HubSpot (n8n-nodes-base.hubspot)

Configuration:

  • Resource: Deal
  • Operation: Get Many
  • Return All: false
  • Limit: 100
  • Additional Fields > Properties: dealname, amount, dealstage, closedate, pipeline, hubspot_owner_id
  • Filter: createdate BETWEEN start and end timestamps

This node returns every deal created in the reporting period. You will use a separate node for deals that closed (won) during the same window.


Node 5: Get Deals Closed Won (HubSpot)

Node type: HubSpot (n8n-nodes-base.hubspot)

Configuration:

  • Resource: Deal
  • Operation: Get Many
  • Additional Fields > Properties: dealname, amount, dealstage, closedate
  • Filter Group 1: dealstage IS closedwon
  • Filter Group 2: closedate BETWEEN start and end timestamps

This isolates your revenue metric for the week: deals that crossed the finish line.


Node 6: Aggregate Report Data

Node type: Code (n8n-nodes-base.code)

Now aggregate the data from all three HubSpot nodes into a single report object. Set the input to accept data from all three upstream nodes.

const contacts = $input.all().filter(item => item.json.email !== undefined);
const allDeals = $('Get Deals Created').all();
const wonDeals = $('Get Deals Closed Won').all();

const totalNewContacts = contacts.length;
const totalDealsCreated = allDeals.length;
const totalDealsWon = wonDeals.length;

const totalRevenue = wonDeals.reduce((sum, deal) => {
  return sum + parseFloat(deal.json.amount || 0);
}, 0);

const dealsByStage = allDeals.reduce((acc, deal) => {
  const stage = deal.json.dealstage || 'Unknown';
  acc[stage] = (acc[stage] || 0) + 1;
  return acc;
}, {});

const weekLabel = $('Set Date Range').first().json.weekLabel;

return [{
  json: {
    weekLabel,
    totalNewContacts,
    totalDealsCreated,
    totalDealsWon,
    totalRevenue: totalRevenue.toFixed(2),
    dealsByStage,
    closedDeals: wonDeals.map(d => ({
      name: d.json.dealname,
      amount: parseFloat(d.json.amount || 0).toFixed(2)
    }))
  }
}];

Node 7: Format Email HTML

Node type: Code (n8n-nodes-base.code)

Build the HTML body for the report email. This keeps formatting logic separate from delivery logic.

const report = $input.first().json;

const stageRows = Object.entries(report.dealsByStage)
  .map(([stage, count]) => `<tr><td>${stage}</td><td>${count}</td></tr>`)
  .join('');

const wonRows = report.closedDeals
  .map(d => `<tr><td>${d.name}</td><td>$${d.amount}</td></tr>`)
  .join('') || '<tr><td colspan="2">No closed deals this week</td></tr>';

const html = `
<div style="font-family: monospace; max-width: 600px; margin: 0 auto; border: 2px solid #0A0A0A; padding: 24px;">
  <h2 style="border-bottom: 2px solid #0A0A0A; padding-bottom: 8px;">
    Weekly CRM Report — ${report.weekLabel}
  </h2>

  <table style="width: 100%; border-collapse: collapse; margin-bottom: 24px;">
    <tr>
      <td style="padding: 8px; border: 1px solid #0A0A0A;"><strong>New Contacts</strong></td>
      <td style="padding: 8px; border: 1px solid #0A0A0A;">${report.totalNewContacts}</td>
    </tr>
    <tr>
      <td style="padding: 8px; border: 1px solid #0A0A0A;"><strong>Deals Created</strong></td>
      <td style="padding: 8px; border: 1px solid #0A0A0A;">${report.totalDealsCreated}</td>
    </tr>
    <tr>
      <td style="padding: 8px; border: 1px solid #0A0A0A;"><strong>Deals Closed Won</strong></td>
      <td style="padding: 8px; border: 1px solid #0A0A0A;">${report.totalDealsWon}</td>
    </tr>
    <tr style="background: #ea580c; color: white;">
      <td style="padding: 8px; border: 1px solid #0A0A0A;"><strong>Revenue Closed</strong></td>
      <td style="padding: 8px; border: 1px solid #0A0A0A;"><strong>$${report.totalRevenue}</strong></td>
    </tr>
  </table>

  <h3>Deals by Pipeline Stage</h3>
  <table style="width: 100%; border-collapse: collapse; margin-bottom: 24px;">
    <tr style="background: #0A0A0A; color: white;">
      <th style="padding: 8px;">Stage</th>
      <th style="padding: 8px;">Count</th>
    </tr>
    ${stageRows}
  </table>

  <h3>Closed Won Deals</h3>
  <table style="width: 100%; border-collapse: collapse;">
    <tr style="background: #0A0A0A; color: white;">
      <th style="padding: 8px;">Deal Name</th>
      <th style="padding: 8px;">Amount</th>
    </tr>
    ${wonRows}
  </table>

  <p style="margin-top: 24px; font-size: 11px; color: #666;">
    Automated report generated by n8n · Data source: HubSpot CRM
  </p>
</div>
`;

return [{ json: { html, subject: `CRM Report — ${report.weekLabel}` } }];

Node 8: Send Email Report

Node type: Gmail or Send Email (n8n-nodes-base.gmail / n8n-nodes-base.emailSend)

Configuration (Gmail node):

  • Resource: Message
  • Operation: Send
  • To: Your client's email address (or a distribution list)
  • Subject: {{ $json.subject }}
  • Email Type: HTML
  • Message: {{ $json.html }}

For multi-client setups, replace the static "To" field with a reference to a Google Sheet or Airtable base that maps each client to their email and CRM filter criteria. Run a SplitInBatches node upstream to iterate per client.


Node 9: Send Slack Notification

Node type: Slack (n8n-nodes-base.slack)

Configuration:

  • Resource: Message
  • Operation: Post
  • Channel: #weekly-reports (or a client-specific channel)
  • Text: Build a compact Slack Block Kit message

In the Message field, switch to expression mode and use:

*CRM Weekly Report — {{ $('Aggregate Report Data').first().json.weekLabel }}*

• New Contacts: {{ $('Aggregate Report Data').first().json.totalNewContacts }}
• Deals Created: {{ $('Aggregate Report Data').first().json.totalDealsCreated }}
• Deals Closed Won: {{ $('Aggregate Report Data').first().json.totalDealsWon }}
• Revenue Closed: ${{ $('Aggregate Report Data').first().json.totalRevenue }}

Full report sent via email.

For richer formatting, use the Slack node's Block Kit option and structure blocks with section, divider, and fields types — Slack's Block Kit gives you table-like layouts within messages.


What Data to Pull and Why It Matters

The example above covers the core metrics. Here is a fuller reference for what agencies typically include in CRM reports:

Pipeline Health Metrics

  • Deals by stage — Where are deals stalling? Which stage has the most drop-off?
  • Average deal age per stage — Longer dwell time signals a process problem
  • Pipeline value by stage — Weighted and unweighted forecasts
  • New deals entered — Prospecting volume for the week

Contact and Lead Metrics

  • New contacts created — Broken down by source (form, import, manual)
  • Lead status distribution — New, Attempted to Contact, Connected, Qualified
  • Lifecycle stage changes — Leads converted to MQL, SQL, Customer
  • Email engagement rates — Open rate, click rate from HubSpot sequences

Revenue Metrics

  • Closed won value — Total revenue closed in the period
  • Closed lost value and reason — Win/loss ratio and primary objections
  • Quota attainment — If tracked in the CRM, compare against targets

Activity Metrics

  • Calls logged — Via HubSpot Engagements API
  • Emails sent — Tracked through HubSpot's email activity
  • Tasks completed vs. created — A proxy for rep productivity

All of these are accessible through the HubSpot node's Get Many operations or the HubSpot API via n8n's HTTP Request node for endpoints the native node does not expose yet.


Extending to Multiple CRMs

If your agency manages clients on different CRMs, structure your n8n instance with one master workflow per CRM type, triggered by the same Schedule Trigger. Use a Switch node upstream to route execution based on a client configuration variable.

For Pipedrive clients, the core nodes are identical in structure but use the Pipedrive node instead: Resource: Deal, Operation: GetAll, filtered by add_time (Pipedrive's creation timestamp field).

For GoHighLevel clients, use the HighLevel node with Resource: Opportunity and filter by pipeline and date range. GoHighLevel's sub-account model maps cleanly to n8n — one sub-account per client means you can parameterize a single workflow template with different HighLevel API keys per client account.

For Salesforce, use the SOQL query capability through the HTTP Request node:

SELECT Id, Name, Amount, StageName, CloseDate, CreatedDate
FROM Opportunity
WHERE CreatedDate >= LAST_WEEK
AND StageName = 'Closed Won'
ORDER BY CloseDate DESC

Pass this as the q parameter in a GET request to your Salesforce instance's /services/data/v59.0/query/ endpoint, authenticated via the OAuth2 credential you configure in n8n.


Common Workflow Optimizations

Error Handling

Wrap your HubSpot nodes in n8n's Error Trigger pattern. Create a separate error-handling sub-workflow and connect it to your main workflow's error output. When a HubSpot API call fails (rate limit, token expiry, network timeout), the error workflow sends an alert to your internal Slack channel rather than silently failing.

Caching Frequently-Used Data

If multiple clients share the same HubSpot portal, batch your API calls using n8n's Merge node to combine multiple contact/deal queries into fewer requests. HubSpot's API has a default rate limit of 100 requests per 10 seconds for Private Apps — structuring your workflow to run a single Get Many and then filter in a Code node is more efficient than running separate filtered queries.

Google Sheets as a Report Archive

Add a final node to your workflow that appends the weekly report data to a Google Sheet. This builds a historical record of every week's metrics automatically, letting you (or your clients) compare trends over time without any manual logging.

Node: Google Sheets > Append or Update Row

Map each metric field from your Aggregate node to a column: Week, New Contacts, Deals Created, Closed Won, Revenue.

Conditional Alerts

Add an IF node after aggregation to check whether key thresholds are breached — for example, if totalDealsWon === 0 or totalRevenue < 5000. Route the "true" branch to a separate Slack message marked with a warning indicator, so your team can proactively reach out before the client notices a slow week.


Deploying and Maintaining Your Reporting Workflow

Self-Hosted vs. n8n.cloud

For agencies handling multiple clients, self-hosting n8n on a $5-20/month VPS (DigitalOcean, Hetzner, or Railway) gives you unlimited workflows and executions at a fixed infrastructure cost. n8n.cloud's Pro plan starts at approximately $50/month and includes managed hosting, automatic updates, and support — the right trade-off if you do not want to manage the server yourself. If you are weighing self-hosting against a managed approach, our article on what it actually takes to run n8n yourself covers the full infrastructure checklist.

Credential Management

Store all CRM credentials as n8n credentials, never as hardcoded values inside Code nodes. n8n encrypts credentials at rest. For multi-client setups where clients provide their own API keys, create a separate credential per client and use n8n's environment variable system to parameterize which credential a workflow uses at execution time.

Monitoring

Enable n8n's built-in execution log and set up log retention long enough to cover at least one billing cycle. For production agency use, consider forwarding n8n's logs to a simple monitoring setup (Grafana Cloud free tier works) so you have visibility into workflow failure rates before clients report missing reports.


Take This Further With EsperaStudio

The workflow above is a solid foundation, but production-grade agency automation goes deeper. Handling edge cases (API pagination for large contact lists, HubSpot rate limiting, multi-timezone scheduling, per-client report branding) adds significant complexity — and getting it wrong means your clients see broken or missing reports.

EsperaStudio builds custom n8n automation infrastructure for agencies. We design, deploy, and maintain reporting workflows that handle multi-client CRM setups, conditional alert logic, branded PDF report generation, and delivery across email, Slack, and client portals — all running reliably with zero manual intervention.

If you are managing more than a handful of clients and want reporting that scales without adding to your team's workload, we can build it for you. Get in touch with EsperaStudio to discuss what your reporting stack should look like.


Summary

Connecting your CRM to n8n and automating client reports involves five core components:

  1. Schedule Trigger — Fires the workflow on your chosen cadence (weekly, bi-weekly, monthly)
  2. CRM Nodes — Pull contacts, deals, and activity data from HubSpot, Pipedrive, Salesforce, or GoHighLevel
  3. Code Nodes — Calculate date ranges, aggregate metrics, and format report content
  4. Email/Slack Nodes — Deliver the formatted report to clients and internal channels
  5. Error Handling — Alert your team if anything in the chain fails

The one-time investment to build this workflow eliminates hours of manual work every week, permanently. As your client roster grows, the same workflow scales — add a client, add a row to your configuration source, and the workflow handles the rest.

Ready to build this for your agency?

Book a €500 Automation Audit
E

EsperaStudio

Initializing Systems
Core.v2.5.059%