Daily
Follow up with HubSpot contacts who haven't replied
Contacts who didn't answer your first email get a polite follow-up from Gmail a few days later, and HubSpot shows it was sent.
- Runs
- Daily
- Apps
- Gmail, HubSpot
- AI
- Not needed
- Access
- HubSpot contacts read+write; Gmail gmail.readonly, gmail.send
Send this to your assistant
Create a ClickRuntime automation: every day, send a follow-up from my Gmail to HubSpot contacts I emailed 3 days ago who haven't replied, and log it in HubSpot.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
Most replies to sales emails come after the second or third message, but follow-ups are the first thing to slip when a week gets busy. Salespeople keep mental notes of who to chase, and the notes don't survive a holiday.
This checks each day for contacts you emailed a few days ago, looks at the Gmail thread to see whether they replied, and sends a short follow-up only to those who didn't. HubSpot records each follow-up, so the history is complete.
What you get out of it
Follow-ups happen on time
A contact emailed on Monday gets a nudge on Thursday, every time, without a reminder in your calendar.
People who replied are left alone
The Gmail thread is checked first, so nobody gets a chaser after answering you.
The thread stays together
The follow-up is sent in the same Gmail conversation, so the person sees your original message underneath.
HubSpot shows the whole sequence
Each follow-up updates the contact with the date and step, so anyone can see where things stand.
How it works
What happens, step by step
Once a day, ClickRuntime finds HubSpot contacts you first emailed three days ago.
For each one, it opens the Gmail conversation to see whether they have replied.
People who haven't replied get a short follow-up in the same conversation from your Gmail.
HubSpot is updated with the follow-up date and count, so nobody is chased twice for the same step.
Before it runs live
- Connect Google through your own Google app (a one-time, 10-minute setup), so it works with your own Gmail
- Connect HubSpot
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
- Run it at a different time, more or less often, or only on weekdays
- 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 Gmail and HubSpot steps into one automation
Under the hood
The code that runs this automation
import base64
from email.message import EmailMessage
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from datetime import date, timedelta
from clickruntime import on_trigger, credentials, http
def hs(method, path, **kw):
r = http.request(method, f"https://api.hubapi.com{path}", headers={"Authorization": f"Bearer {credentials.connection('hubspot', 'work')}"}, **kw)
return r.raise_for_status() or (r.json() if r.content else {})
@on_trigger
def run(event):
day = (date.today() - timedelta(days=3)).isoformat()
found = hs("POST", "/crm/v3/objects/contacts/search", json={"filterGroups": [{"filters": [
{"propertyName": "first_outreach_date", "operator": "EQ", "value": day},
{"propertyName": "followup_count", "operator": "NOT_HAS_PROPERTY"}]}],
"properties": ["email", "firstname", "outreach_thread_id"], "limit": 100})["results"]
g = build("gmail", "v1", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False)
sent = 0
for c in found:
p = c["properties"]
thread = g.users().threads().get(userId="me", id=p["outreach_thread_id"], format="metadata").execute()
if any(p["email"] in h["value"] for m in thread["messages"] for h in m["payload"]["headers"] if h["name"] == "From"):
continue
msg = EmailMessage(); msg["To"] = p["email"]; msg["Subject"] = "Re: Quick hello"
msg.set_content(f"Hi {p.get('firstname') or 'there'}, just bringing this back to the top of your inbox. Worth a chat?")
g.users().messages().send(userId="me", body={"raw": base64.urlsafe_b64encode(msg.as_bytes()).decode(),
"threadId": p["outreach_thread_id"]}).execute()
hs("PATCH", f"/crm/v3/objects/contacts/{c['id']}", json={"properties": {"followup_count": "1", "last_followup_date": date.today().isoformat()}})
sent += 1
return {"followed_up": sent}FAQ
Common questions
How does it know who to follow up?
How many follow-ups will someone get?
Where does it find the original email?
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
Email new HubSpot contacts nobody has contacted yet
New contacts who haven't heard from you get an introduction email from your Gmail each day, and HubSpot records that they've been contacted.
See how it worksClose cold HubSpot deals and ask for feedback
Deals with no activity for three weeks are marked Closed Lost, the contact gets a short feedback email from Gmail, and the team sees a summary in Slack.
See how it worksDraft personal outreach emails for a HubSpot list
Each contact in your HubSpot outreach list gets a tailored email waiting in your Gmail drafts, ready for you to check and send.
See how it worksKeep exploring
Set up “Follow up with HubSpot contacts who haven't replied” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.