Track lead-to-MQL conversion rate by source and report to Slack using Make
Prerequisites
- Make account (any plan — weekly scheduling works on the Free plan)
- HubSpot connection configured in Make via OAuth
- Slack connection configured in Make (Bot Token with
chat:writescope) - Lifecycle stages configured in HubSpot (Lead, Marketing Qualified Lead)
Why Make?
Make is a good fit if your team already uses it for other automations. The visual scenario builder makes the two-query pattern (all leads vs. MQLs) easy to understand. The Free plan handles the HTTP modules and scheduling, but the Code module needed for percentage calculations requires the Core plan at $29/mo. At ~20 credits per month for 4 weekly runs, the credit cost is negligible.
How it works
- Scheduler triggers weekly on Monday morning
- Set variable module computes 7-day lookback timestamps in milliseconds
- Two HTTP modules search HubSpot — one for all leads created in the period, one filtered to MQLs
- Code module (Core plan) groups by source, calculates conversion percentages, and formats the breakdown
- Slack module posts the formatted report
Overview
Make's scenario will run two HubSpot searches — one for all leads created in the past 7 days, and one for contacts in that period that reached MQL status. A Code module (or Array Aggregator) groups contacts by source and calculates conversion rates per source.
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 to compute the 7-day lookback:
- Variable 1:
start_ms={{formatDate(addDays(now; -7); "X")}}000(Unix milliseconds) - Variable 2:
end_ms={{formatDate(now; "X")}}000
formatDate(date; "X") returns Unix seconds. Append 000 to get milliseconds for HubSpot's filter values. Alternatively, use floor((parseDate(addDays(now; -7)) - parseDate("1970-01-01T00:00:00Z")) * 1000).
Step 3: Search for all leads created in the period
Add an HTTP module (Make an API Call):
- URL:
https://api.hubapi.com/crm/v3/objects/contacts/search - Method: POST
- Body type: Raw JSON
{
"filterGroups": [
{
"filters": [
{
"propertyName": "createdate",
"operator": "GTE",
"value": "{{start_ms}}"
},
{
"propertyName": "createdate",
"operator": "LT",
"value": "{{end_ms}}"
}
]
}
],
"properties": ["hs_analytics_source", "lifecyclestage", "createdate"],
"limit": 100
}HubSpot Search returns max 100 results per request. If you generate more than 100 leads per week, add a Repeater module that loops back with the after cursor until paging.next is absent.
Step 4: Search for MQLs from the same period
Add a second HTTP module with an additional lifecycle stage filter:
{
"filterGroups": [
{
"filters": [
{
"propertyName": "createdate",
"operator": "GTE",
"value": "{{start_ms}}"
},
{
"propertyName": "createdate",
"operator": "LT",
"value": "{{end_ms}}"
},
{
"propertyName": "lifecyclestage",
"operator": "EQ",
"value": "marketingqualifiedlead"
}
]
}
],
"properties": ["hs_analytics_source", "lifecyclestage", "createdate"],
"limit": 100
}Step 5: Calculate conversion rates
Add a Code module (requires Core plan) to process both responses:
const allLeads = JSON.parse(getVariable('leads_response')).results || [];
const mqls = JSON.parse(getVariable('mqls_response')).results || [];
const leadsBySource = {};
for (const lead of allLeads) {
const src = lead.properties.hs_analytics_source || 'UNKNOWN';
leadsBySource[src] = (leadsBySource[src] || 0) + 1;
}
const mqlsBySource = {};
for (const mql of mqls) {
const src = mql.properties.hs_analytics_source || 'UNKNOWN';
mqlsBySource[src] = (mqlsBySource[src] || 0) + 1;
}
const sources = [...new Set([...Object.keys(leadsBySource), ...Object.keys(mqlsBySource)])];
const lines = sources
.map(s => ({
source: s,
leads: leadsBySource[s] || 0,
mqls: mqlsBySource[s] || 0,
rate: leadsBySource[s] ? ((mqlsBySource[s] || 0) / leadsBySource[s] * 100).toFixed(1) : '0.0',
}))
.sort((a, b) => b.leads - a.leads)
.map(r => `• *${r.source}*: ${r.leads} leads → ${r.mqls} MQLs (${r.rate}%)`);
const total = allLeads.length;
const totalMQL = mqls.length;
const overall = total > 0 ? (totalMQL / total * 100).toFixed(1) : '0.0';
return {
breakdown: lines.join('\n'),
totalLeads: total,
totalMQLs: totalMQL,
overallRate: overall,
};If you're on the Free plan without the Code module, you can use Iterator + Array Aggregator modules to group by source, but the logic is significantly more complex for percentage calculations.
Step 6: Send to Slack
Add a Slack module -> Create a Message:
- Channel:
#marketing-reports - Text:
📈 *Weekly Lead-to-MQL Conversion Report*
*Total Leads:* {{totalLeads}}
*Total MQLs:* {{totalMQLs}}
*Overall Conversion:* {{overallRate}}%
*Conversion by Source:*
{{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
- Click Run once to execute the scenario
- Inspect each module's output — verify lead counts match your HubSpot dashboard
- Toggle the scenario to Active
Troubleshooting
Common questions
Does this work on the Make Free plan?
Partially. The Free plan (1,000 credits/month) supports the HTTP modules and Slack module, but not the Code module needed for percentage calculations. Without the Code module, you'd need a complex combination of Iterator + Array Aggregator modules to group by source and compute rates. The Core plan ($29/mo) is recommended.
How many Make credits does this use per month?
Each run uses ~5 credits (1 trigger + 1 variable + 2 searches + 1 code + 1 Slack). At 4 weekly runs/month, that's ~20 credits — well within the Free plan's 1,000 credits or the Core plan's 10,000 credits.
Can I add campaign-level breakdown within a source?
Yes. Include hs_analytics_source_data_1 in the search properties. This gives you UTM campaign data for sources like PAID_SEARCH. Add a second grouping level in the Code module to break down high-volume sources by campaign.
Cost and credits
- Free plan: 1,000 credits/month. This scenario uses approximately 5 credits per run (1 trigger + 1 variable + 2 searches + 1 code + 1 Slack). At 4 runs/month, that's ~20 credits/month.
- Core plan: $29/month for 10,000 credits. Required if using the Code module.
Next steps
- Month-to-date comparison — add a second pair of searches with a 30-day lookback and include MTD totals in the report
- Week-over-week trend — use Make's Data Store module to persist last week's rates and show change arrows
- Campaign-level breakdown — for
PAID_SEARCHsources, drill intohs_analytics_source_data_1to show per-campaign conversion
Looking to scale your AI operations?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.