Send a weekly Slack report on HubSpot sequence performance using Make

high complexityCost: $10-29/mo

Prerequisites

Prerequisites
  • Make account (Core plan or higher recommended for the Code module)
  • HubSpot Sales Hub Professional or Enterprise (required for Sequences API access)
  • HubSpot connection configured in Make via OAuth
  • Slack connection configured in Make (Bot Token with chat:write scope)
Sequences API access

The HubSpot Sequences API is only available with Sales Hub Professional or Enterprise. Starter and free plans don't have API access to sequence data, even if sequences are available in the UI.

Step 1: Create a scenario and schedule it

Create a new scenario in Make. Configure the schedule:

  • Schedule type: At regular intervals
  • Run scenario: Every week
  • Day: Monday
  • Time: 09:00
  • Timezone: Select your team's timezone

Step 2: Set date range variables

Add a Tools -> Set variable module:

  • Variable 1: seven_days_ago_ms = Unix milliseconds for 7 days ago
  • Variable 2: today_ms = Unix milliseconds for today midnight

Use Make's date functions: {{formatDate(addDays(now; -7); "X")}}000

Step 3: Fetch all sequences

Add an HTTP module (Make an API Call):

  • URL: https://api.hubapi.com/crm/v3/objects/sequences?limit=100
  • Method: GET
  • Headers: Use the HubSpot connection

This returns all sequences with their IDs and names.

Step 4: Iterate and fetch enrollments per sequence

Add an Iterator module to process each sequence individually. Then add an HTTP module inside the iterator:

  • URL: https://api.hubapi.com/crm/v3/objects/sequence_enrollments/search
  • Method: POST
  • Body type: Raw JSON
{
  "filterGroups": [
    {
      "filters": [
        {
          "propertyName": "hs_sequence_id",
          "operator": "EQ",
          "value": "{{sequence_id}}"
        },
        {
          "propertyName": "hs_enrollment_start_date",
          "operator": "GTE",
          "value": "{{seven_days_ago_ms}}"
        }
      ]
    }
  ],
  "properties": [
    "hs_sequence_id", "hs_enrollment_state",
    "hs_was_email_opened", "hs_was_email_replied",
    "hs_was_meeting_booked"
  ],
  "limit": 100
}
Operation cost with iterators

Each iteration through the HTTP module counts as 1 Make credit. With 10 sequences, this step alone costs 10 credits per run. Add a Sleep module (1 second) inside the iterator to respect HubSpot's 5 req/sec rate limit on the Search API.

Step 5: Aggregate results with a Code module

After the iterator, add a Code module to calculate metrics per sequence:

const sequences = JSON.parse(getVariable('sequences_response')).results || [];
const enrollmentBatches = JSON.parse(getVariable('all_enrollments'));
 
const seqMap = {};
for (const seq of sequences) {
  seqMap[seq.id] = seq.properties?.hs_sequence_name || `Sequence ${seq.id}`;
}
 
const metrics = {};
for (const batch of enrollmentBatches) {
  for (const e of batch.results || []) {
    const seqId = e.properties.hs_sequence_id;
    if (!metrics[seqId]) {
      metrics[seqId] = { name: seqMap[seqId] || seqId, enrolled: 0, opened: 0, replied: 0, meetings: 0 };
    }
    metrics[seqId].enrolled++;
    if (e.properties.hs_was_email_opened === 'true') metrics[seqId].opened++;
    if (e.properties.hs_was_email_replied === 'true') metrics[seqId].replied++;
    if (e.properties.hs_was_meeting_booked === 'true') metrics[seqId].meetings++;
  }
}
 
const report = Object.values(metrics)
  .filter(m => m.enrolled > 0)
  .sort((a, b) => b.enrolled - a.enrolled)
  .map(m => {
    const openRate = (m.opened / m.enrolled * 100).toFixed(1);
    const replyRate = (m.replied / m.enrolled * 100).toFixed(1);
    const meetingRate = (m.meetings / m.enrolled * 100).toFixed(1);
    return `*${m.name}* (${m.enrolled} enrolled)\n    Open: ${openRate}% | Reply: ${replyRate}% | Meeting: ${meetingRate}%`;
  });
 
return {
  breakdown: report.join('\n\n'),
  totalEnrolled: Object.values(metrics).reduce((s, m) => s + m.enrolled, 0),
  totalReplied: Object.values(metrics).reduce((s, m) => s + m.replied, 0),
  totalMeetings: Object.values(metrics).reduce((s, m) => s + m.meetings, 0),
};

If you're on the Free plan without the Code module, this workflow is difficult to build using only visual aggregators — the per-sequence percentage calculations require code.

Step 6: Send to Slack

Add a Slack module -> Create a Message:

  • Channel: #sales-reports
  • Text:
📧 *Weekly Sequence Performance Report*
 
*Total Enrolled:* {{totalEnrolled}}
*Total Replies:* {{totalReplied}}
*Meetings Booked:* {{totalMeetings}}
 
*Per-Sequence Breakdown:*
{{breakdown}}
 
_Last 7 days | Generated {{formatDate(now; "dddd, MMMM D, YYYY")}}_

For Block Kit formatting, use Slack -> Make an API Call with /chat.postMessage and a JSON body containing blocks.

Step 7: Test and activate

  1. Click Run once to test
  2. Inspect each module's output — verify enrollment counts match your HubSpot sequence dashboard
  3. Toggle the scenario to Active

Cost and credits

  • Core plan: $29/month for 10,000 credits (required for the Code module). This scenario uses approximately 3 + N credits per run, where N is the number of active sequences (1 trigger + 1 variable + 1 sequences fetch + N enrollment searches + 1 code + 1 Slack). With 10 sequences, that's ~15 credits per run, ~60 credits/month.
  • Free plan: Not practical — the Code module is required for percentage calculations, and the iterator will consume credits quickly.

Next steps

  • Use Make's Data Store to persist weekly metrics and add trend comparisons
  • Add a Filter after the Code module to only report sequences with more than 10 enrollments (skip low-volume test sequences)
  • Alert routing — use a Router to send underperforming sequences (reply rate below 3%) to a separate #sequence-alerts channel

Need help implementing this?

We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.