Every 30 minutes
Send marketing-qualified HubSpot contacts to Salesforce
Contacts that reach MQL in HubSpot are created as Salesforce leads within 30 minutes, without duplicates, and sales hears about them in Slack.
- Runs
- Every 30 minutes
- Apps
- HubSpot, Salesforce
- AI
- Not needed
- Access
- HubSpot contacts read+write; Salesforce api
Send this to your assistant
Create a ClickRuntime automation: every 30 minutes, find HubSpot contacts with lifecycle stage MQL that haven't been sent yet, create a Salesforce lead unless one exists with that email, save the lead ID on the contact, and post the new leads to #sales.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
Marketing nurtures contacts in HubSpot until they're ready for sales; sales works leads in Salesforce. The hand-off between the two is often a weekly export, which means a contact who requested a demo on Monday reaches a rep on Friday.
This automation checks HubSpot every 30 minutes for contacts that have reached marketing-qualified, creates them as Salesforce leads, and stamps the lead ID back on the HubSpot contact. Sales sees the new leads in Slack within half an hour.
What you get out of it
Hand-off in minutes, not days
A contact reaching MQL is in Salesforce within 30 minutes.
No duplicate leads
Existing leads with the same email are reused instead of created again.
A clear link between the two
The Salesforce lead ID is saved on the HubSpot contact, so marketing can see what was handed over.
Sales knows straight away
New leads are posted to #sales by name and company.
How it works
What happens, step by step
Every 30 minutes the automation looks for HubSpot contacts at the MQL stage that don't yet have a Salesforce lead ID.
For each, it checks Salesforce for a lead with the same email.
If there isn't one, it creates a new Salesforce lead with the contact's details.
The Salesforce lead ID is saved on the HubSpot contact so it's never sent twice.
New leads are posted to #sales.
Before it runs live
- Connect HubSpot
- Connect Salesforce
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Act only on the items that match your own rules, and skip the rest
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other HubSpot and Salesforce steps into one automation
Under the hood
The code that runs this automation
from clickruntime import on_trigger, report_fetched, credentials, http, notify
HS = "https://api.hubapi.com/crm/v3/objects/contacts"
INSTANCE = "https://yourcompany.my.salesforce.com"
API = f"{INSTANCE}/services/data/v61.0"
@on_trigger
def run(event):
hs = {"Authorization": f"Bearer {credentials.connection('hubspot', 'work')}"}
contacts = http.post(f"{HS}/search", headers=hs, json={"limit": 50, "properties": ["email", "firstname", "lastname",
"company", "phone"], "filterGroups": [{"filters": [
{"propertyName": "lifecyclestage", "operator": "EQ", "value": "marketingqualifiedlead"},
{"propertyName": "salesforce_lead_id", "operator": "NOT_HAS_PROPERTY"}]}]}).json()["results"]
report_fetched(len(contacts))
if not contacts:
return {"summary": "No new MQLs"}
sf = {"Authorization": f"Bearer {credentials.connection('salesforce', 'work')}"}
created = []
for c in contacts:
p = c["properties"]
email = (p.get("email") or "").replace("'", "")
found = http.get(f"{API}/query", headers=sf, params={"q": f"SELECT Id FROM Lead WHERE Email = '{email}' LIMIT 1"}).json()["records"]
lead_id = found[0]["Id"] if found else http.post(f"{API}/sobjects/Lead", headers=sf, json={
"FirstName": p.get("firstname"), "LastName": p.get("lastname") or email, "Email": email,
"Company": p.get("company") or "Unknown", "Phone": p.get("phone"), "LeadSource": "HubSpot"}).json()["id"]
if not found:
created.append(f"{p.get('firstname')} {p.get('lastname')} ({p.get('company')})")
http.patch(f"{HS}/{c['id']}", headers=hs, json={"properties": {"salesforce_lead_id": lead_id}}).raise_for_status()
if created:
notify.slack(f"{len(created)} new MQLs from HubSpot are now Salesforce leads:\n" + "\n".join(created), channel="#sales")
return {"contacts": len(contacts), "created": len(created)}FAQ
Common questions
What do I need to set up in HubSpot?
Can it use a different stage than MQL?
What does the lead source say?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Fill in missing company details across HubSpot and Salesforce
Every night, companies are matched by website, blank industry, size and phone fields are filled from the other CRM, and you get an email of the changes.
See how it worksSee new job listings as they're posted
Jobs that match your keywords show up in a Slack channel, each one only once.
See how it worksGet told when someone mentions a keyword in Slack
When anyone mentions a customer, a competitor or a word like "outage", you get the message and a link to it.
See how it worksKeep exploring
Set up “Send marketing-qualified HubSpot contacts to Salesforce” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.