What this workflow does
- Every 15 minutes (Schedule Trigger) starts the new-customer check.
- Search closed-won deals (HTTP Request, HubSpot CRM search) returns closed-won deals modified in the last two days.
- Read onboarding state (Google Sheets) loads existing onboarding records.
- New customers only (Code) drops deals that already have a record, so a second closed-won event never starts a second sequence, and builds the prompt from the deal notes.
- Write opener with Claude (HTTP Request) returns strict JSON: a short opener, the goal it referenced and a
safe_to_sendflag. The prompt forbids pricing, discounts, contract terms and sales objections. - Find deal contact (HTTP Request) searches HubSpot contacts associated with the deal.
- Compose welcome email (Code) checks the opener again in code (length and banned terms such as price or discount), falls back to a standard sentence if the AI failed or was rejected, and wraps it in your fixed email with setup links.
- Contact found? (If) creates a Gmail draft and an onboarding record, or alerts the team in Slack when the deal has no contact email. Those deals still get a record, marked
needs_contact, so delete that row once you add the contact. - Weekdays at 9am, Read onboarding records and Find stalled customers (Code) alert the owner when a customer has been stuck on the same setup step for four days, repeating every three days.
Before you import
- A current n8n version.
- A HubSpot private app token with read access to deals and contacts. HubSpot search endpoints have their own rate limits, so keep the 15-minute interval unless you need faster starts.
- An Anthropic API key, the onboarding manager’s Gmail account, a Google Sheet and a Slack bot.
Setup
- Import the JSON and connect the HubSpot (on both HTTP nodes), Anthropic, Gmail, Google Sheets and Slack credentials.
- Create an
Onboardingtab with headers: deal_id, company, contact_email, contact_first_name, owner_slack_id, start_date, status, ai_fallback, ai_note, step_account_created, step_data_imported, step_integration_connected, step_teammate_invited. - Replace
REPLACE_WITH_SHEET_IDon all three sheet nodes andREPLACE_WITH_SLACK_ONBOARDING_CHANNEL_ID. - In New customers only, map HubSpot owner IDs to Slack member IDs in
OWNER_SLACK. - In Compose welcome email, replace the three
REPLACE_WITH_..._URLlinks andREPLACE_WITH_SENDER_NAME. - If your pipeline is not the default one, replace
closedwonwith your closed-won stage ID. - Edit
STEPSandSTALL_DAYSin Find stalled customers to match your real setup events. Fill the step columns from product events or by hand.
Test it
Move a test deal with notes and an associated contact to closed-won, run the workflow manually, and check Gmail drafts and the sheet. Run it again and confirm no second draft appears. Then backdate a row’s start_date by four days and run the 9am branch.
Make it production-ready
- Keep drafts for two weeks so the onboarding team sees what would have gone out, then switch the Gmail node to send.
- Add a status value such as
pausedfor custom implementations. The stall check skips anything not markedonboarding. - Move state to Postgres or your CRM once you have more than a few hundred active customers.
- Add an n8n error workflow, and an activation check that sets status to
activatedto end the sequence.
Read the full guide on automating customer onboarding emails for step design and AI rules, or work with Lumeor to connect Stripe or your product database.