Flag HubSpot deals with missing fields and Slack the rep using Make

medium complexityCost: $10-29/mo

Prerequisites

Prerequisites
  • Make account (Free plan works for low volume)
  • HubSpot connection in Make via OAuth or API key
  • Slack connection in Make
  • A mapping of HubSpot owner IDs to Slack user IDs

Why Make?

Make works for missing field alerts if your team already uses it. The HTTP modules call the HubSpot API directly (Make's built-in HubSpot module doesn't support NOT_HAS_PROPERTY), and a Code module handles deduplication and grouping. At typical volumes (5-10 deals with missing fields), the free plan covers it.

How it works

  • Scheduler fires daily at 7 AM
  • HTTP modules search for deals missing close date and amount via two separate API calls
  • Code module deduplicates results, groups deals by owner, and outputs one bundle per owner
  • Filter skips owners with zero missing deals
  • Slack module DMs each owner with their incomplete deals and HubSpot links

Step 1: Schedule daily execution

Create a new scenario. Set the schedule:

  • Schedule type: Every day
  • Time: 07:00

Step 2: Search for deals missing close date

Add an HTTP -> Make a Request module:

  • Method: POST
  • URL: https://api.hubapi.com/crm/v3/objects/deals/search
  • Headers: Authorization: Bearer {{your_hubspot_token}}, Content-Type: application/json
  • Body:
{
  "filterGroups": [{
    "filters": [
      {"propertyName": "closedate", "operator": "NOT_HAS_PROPERTY"},
      {"propertyName": "dealstage", "operator": "NOT_IN", "values": ["closedwon", "closedlost"]}
    ]
  }],
  "properties": ["dealname", "amount", "closedate", "dealstage", "hubspot_owner_id"],
  "limit": 100
}
Why not the HubSpot CRM module?

Make's built-in HubSpot module does not expose the NOT_HAS_PROPERTY operator. Use an HTTP module with a raw POST request to access the full Search API.

Step 3: Search for deals missing amount

Add a second HTTP -> Make a Request module with the same structure, swapping the filter:

{
  "filterGroups": [{
    "filters": [
      {"propertyName": "amount", "operator": "NOT_HAS_PROPERTY"},
      {"propertyName": "dealstage", "operator": "NOT_IN", "values": ["closedwon", "closedlost"]}
    ]
  }],
  "properties": ["dealname", "amount", "closedate", "dealstage", "hubspot_owner_id"],
  "limit": 100
}

Step 4: Merge and group by owner

Add a Tools -> Set Multiple Variables module or a Code (JavaScript) module to deduplicate and group:

const closeResults = JSON.parse(bundles[0].data.body).results || [];
const amountResults = JSON.parse(bundles[1].data.body).results || [];
 
const seen = new Set();
const byOwner = {};
 
for (const deal of [...closeResults, ...amountResults]) {
  if (seen.has(deal.id)) continue;
  seen.add(deal.id);
  const props = deal.properties;
  const missing = [];
  if (!props.closedate) missing.push('close date');
  if (!props.amount) missing.push('amount');
  const ownerId = props.hubspot_owner_id || 'unassigned';
 
  if (!byOwner[ownerId]) byOwner[ownerId] = [];
  byOwner[ownerId].push({
    id: deal.id,
    name: props.dealname,
    missing: missing.join(', '),
  });
}
 
return Object.entries(byOwner).map(([ownerId, deals]) => ({
  ownerId,
  dealCount: deals.length,
  deals,
}));

This outputs one bundle per owner, which feeds into the next module.

Step 5: Slack DM each rep

Add a Slack -> Create a Message module:

  • Channel / User: Map the ownerId to the corresponding Slack user ID from your lookup table
  • Text:
*Missing Deal Fields*
You have {{dealCount}} deals with incomplete data:
 
{{deals mapped to bullet list}}
 
Please update these deals today so forecasting stays accurate.

For richer formatting, switch to Block Kit and use a JSON body:

{
  "blocks": [
    {
      "type": "header",
      "text": {"type": "plain_text", "text": "Missing Deal Fields"}
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "You have *{{dealCount}}* deals with incomplete data:\n\n{{formatted deal list with links}}"
      }
    },
    {
      "type": "context",
      "elements": [{"type": "mrkdwn", "text": "Please update these deals today so forecasting stays accurate."}]
    }
  ]
}
Owner to Slack user mapping

Make doesn't natively map HubSpot owner IDs to Slack users. Create a lookup table using Make's Data Store module, a Google Sheet, or a static JSON object in the Code module.

Step 6: Handle empty results

Add a Filter between the Code module and the Slack module:

  • Condition: dealCount greater than 0

This prevents the scenario from sending empty messages when all deals have complete data.

Step 7: Activate

  1. Click Run once to test
  2. Verify the Slack DM content and deal links
  3. Toggle to Active

Troubleshooting

Common questions

How many Make credits does this use per month?

About 120-150 credits/month. Each daily run uses 4-5 operations (2 HTTP + code + filter + Slack per owner). With 5 owners getting DMs, that's ~8-10 operations per run. Fits the free plan's 1,000 credits.

Why can't I use Make's HubSpot CRM module for this?

Make's built-in HubSpot module doesn't expose the NOT_HAS_PROPERTY filter operator. You need the HTTP module to call the Search API directly with the raw filter JSON.

Can I audit more than two fields?

Yes. Add another HTTP module for each additional field and include it in the Code module's merge logic. The deduplication handles any number of overlapping searches.

Cost

  • Free plan: ~4-5 operations per run (2 HTTP requests + code + filter + Slack). At 30 runs/month = ~150 operations. Within the free tier's 1,000 operations.
  • Core plan: $10.59/mo for higher volume.

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.