Automate Typeform to HubSpot and Slack with Make.com: HubSpot contact upsert by email, solid field mapping, and Slack alerts for errors.
Introduction
If you collect leads in Typeform, the manual path is usually brutal: someone logs into HubSpot, searches for the contact by email, updates fields, then copies a summary into Slack so sales knows what just came in. After a few weeks, you end up with duplicates, missing fields, and Slack messages that do not match what landed in HubSpot.
This guide shows how to automate Typeform to HubSpot and Slack using Make.com, with proper deduping via HubSpot upsert and guardrails for missing email or failed API calls. By the end, you will have a working Cross-Platform Automation (XPA) pattern you can reuse for other form-to-CRM workflows.
If you want the broader approach behind Cross-Platform Automation (XPA), start with this overview.
What You'll Need
- Make.com account: paid plan recommended, because you will want reliable runs and multi-step error handling.
- Typeform: access to the specific form and permission to view form responses.
- HubSpot: permission to create or update contacts.
- Slack workspace: permission to post to your target channel.
- Google Sheets (recommended): for a lightweight run log so you can audit successes and failures.
Prerequisites in your systems:
- Decide which Typeform field maps to HubSpot contact email. This is the dedupe key.
- In HubSpot, confirm either standard properties exist (like email, firstname, lastname) or create custom properties you want to map.
- Create a Slack channel like #sales-notifications.
How It Works (The Logic)
The workflow is simple on paper:
- Trigger: when a new submission hits Typeform.
- Upsert: Make.com creates or updates a HubSpot contact using email as the unique identifier.
- Notify: Make.com posts a Slack message with the submission summary.
- Log and guardrails: if email is missing or HubSpot fails, you write to Google Sheets and optionally notify an ops channel.
That trigger-to-action flow is what makes this a dependable XPA instead of a fragile copy-paste integration.
Step-by-Step Setup
1) Create the Make.com scenario
- Go to Make.com and create a new scenario.
- Name it something like
Typeform → HubSpot upsert → Slack.
2) Add the Typeform trigger
- Module: Typeform
- Event: Watch form responses (wording may vary, but you want the “new submission” trigger).
- Select your Form.
Field output you will use later often includes:
- submission/response identifiers
- the answers for each form question
- submission time and hidden fields (if you use them)
3) Normalize and validate your email before HubSpot
This is the part people skip, then duplicates happen.
- Add a Tools module such as Set variable or Text functions (your Make instance may show slightly different options).
- Create a variable like
email_normalized.- Trim whitespace
- Lowercase the email
Then add a Filter step:
- If
email_normalizedis empty, route to an “error” branch. - If it is present, route to the HubSpot upsert.
4) Add HubSpot upsert logic (Create or Update Contact)
- Module: HubSpot
- Action: Create or Update Contact
- Use email as the identifier for the upsert.
Field mappings (typical baseline):
- Typeform Email → HubSpot email
- Typeform First Name → HubSpot firstname
- Typeform Last Name → HubSpot lastname
- Typeform Company → HubSpot company
- Typeform Phone → HubSpot phone (clean formatting beforehand if needed)
- Typeform Website → HubSpot website
If you also capture attribution:
- Typeform Hidden field like
campaign_id→ HubSpot custom property likelead_source_campaign
Gotchas to watch:
- HubSpot property names are exact. If your mapping fails, the scenario can run without updating the fields you expected.
- If you map a field to the wrong data type (for example sending a long text into a choice property), HubSpot may reject that property.
5) Add a Router for success vs failure
Make this explicit so you do not spam Slack when HubSpot fails.
- Add a Router right after the HubSpot module.
- Create two paths:
- Success path: send Slack message
- Error path: log to Google Sheets, then optionally notify Slack
How you detect the branch depends on Make’s output. Common patterns are status fields, module error handling, or whether the contact identifier is present.
6) Send the Slack notification
- Module: Slack
- Action: Send channel message
- Channel:
#sales-notifications
Message content that helps sales instantly:
- Form name
- Contact name and email
- Phone and company
- Campaign or lead source (if you mapped it)
- Submission timestamp
Example message text (plain text works fine):
New lead from Typeform: {{FirstName}} {{LastName}} ({{Email}})Company: {{Company}} | Phone: {{Phone}}Campaign: {{lead_source_campaign}} | Submitted: {{SubmissionTime}}
Tip: keep it short. Sales uses this while they are triaging.
7) Log every run in Google Sheets (recommended)
This is what saves you when someone asks, “Did this submission really reach HubSpot?”
- Module: Google Sheets
- Action: Add a row
Columns to include:
submission_id(from Typeform)email_normalizedstatus(created, updated, failed)hubspot_contact_idif available from the HubSpot moduleerror_message(only on failure)timestamp
8) Add failure alerting (optional but practical)
If HubSpot fails because of a temporary API issue, you do not want it to disappear silently.
- In your error branch, add another Slack message to something like #ops-notifications.
- Include the
submission_idand theerror_message.
9) Turn on scenario replay tests
Before you go live:
- Submit at least 3 test entries:
- Complete lead with valid email
- Same email again to confirm upsert updates instead of duplicates
- Submission missing email to confirm your guardrail branch triggers
If your Slack message fires twice on the same submission, your Typeform trigger selection may be incorrect, or you may be replaying runs.
Real-World Business Scenario
We’ve built this pattern for a B2B services company that used several Typeform lead capture pages for different service lines. They had one shared sales Slack channel, and leads arrived in slightly different shapes depending on the form and the person filling it out.
After implementing the Typeform to HubSpot and Slack XPA:
- every submission created or updated a single HubSpot contact by email
- sales got a consistent Slack message with the right campaign attribution from Typeform hidden fields
- failures were logged to Google Sheets with submission IDs, so ops could fix field mapping issues quickly
The immediate outcome was fewer duplicates and an audit trail that made the integration boring, in the best way.
Common Variations
-
Add owner assignment logic in HubSpot
- If your Typeform includes a service dropdown, map it to a HubSpot owner or team and update routing fields.
-
Route Slack to different channels by form type
- If you have multiple Typeforms, use a Router based on form ID or a question answer, then post to the correct sales channel.
-
Create follow-up tasks in ClickUp or Monday.com
- After the HubSpot upsert succeeds, create a task like “Qualify lead” assigned to the right rep.
What You Built, in Plain Terms
You built an XPA where Typeform is the source of truth, HubSpot is updated via an email-keyed upsert, and Slack gets a concise notification only when the CRM update succeeds. Logging and guardrails keep the automation stable when data is incomplete or APIs hiccup.
If you want help implementing the same pattern across your stack, Olmec Dynamics builds these XPAs for real businesses. Start with Cross-Platform Automation (XPA) and adapt the workflow to your exact fields, properties, and routing rules.