Back to Play 1 Resources
Play 1: Hands-Free CRM

Play 1 Complete Implementation Guide

Full A-to-Z walkthrough expanding on the book's Play 1 with screenshots, video, and troubleshooting.

Play 1: Hands-Free CRM
(Implementation Guide)

Manual CRM

entry is dead time. Every email summary typed by hand, every meeting note copy-pasted into a contact record, every "I'll update it later" that never happens costs your firm 5-10 hours per person per week. Play 1 eliminates that entirely.

This guide walks you through building three parallel n8n workflows that intercept outbound emails and calendar events, extract structured data via AI, and write it directly into your CRM

. No human intervention. No data entry backlog. No excuses for incomplete records.

What You're Building

Three distinct n8n workflows running 24/7:

Email Logger: Fires every time someone sends a client email. Extracts summary and action items via OpenAI. Writes to the contact record in HubSpot or Salesforce. If the recipient isn't in the CRM

, routes an alert to your exceptions channel.

Calendar Logger: Runs nightly at 11:00 PM. Scans yesterday's completed meetings. Creates "Meeting Held" activity logs with attendee lists and AI-generated summaries pulled from calendar descriptions.

Daily Digest: Runs at 7:00 AM. Queries flagged accounts in your CRM

. Sends a Slack or Teams message to each user with their priority contacts and recent activity.

Prerequisites

Do not skip this section. Missing any of these will break the automation.

CRM

Field Setup: Add two custom text fields to your Contact and Deal objects: AI Summary (long text, 2000 character limit) and Next Steps (short text, 500 character limit). In HubSpot, go to Settings > Properties > Create Property. In Salesforce, go to Setup > Object Manager > Contact > Fields & Relationships > New.

Exceptions Channel: Create a dedicated Slack or Teams channel named #crm-exceptions. Pin a message at the top: "This channel logs emails sent to people not yet in the CRM

. Add them manually or ignore if they're not a prospect."

API Access: You need an OpenAI API

key with GPT-4 access (GPT-3.5-turbo will produce lower-quality summaries). You also need admin-level OAuth credentials for your email provider (Google Workspace or Microsoft 365) and your CRM
(HubSpot or Salesforce). If your IT department restricts OAuth scopes, get approval before starting.

n8n Instance: Self-hosted or n8n Cloud. Minimum plan: Starter (for webhook

triggers and sufficient execution volume). If self-hosting, ensure your server has a public IP and SSL certificate for webhook delivery.

Step 1: Connect Your Accounts

Open n8n. Go to Credentials in the left sidebar.

Add Email Provider:

Click Add Credential. Search for Gmail (if using Google Workspace) or Microsoft Outlook (if using Microsoft 365). Click through the OAuth flow. Grant access to read and send email. If you hit a "This app isn't verified" warning in Google, click Advanced > Go to [app name] (unsafe). This is normal for self-hosted n8n instances.

Add CRM

:

Click Add Credential again. Search for HubSpot or Salesforce. Complete the OAuth flow. For HubSpot, ensure the token has crm.objects.contacts.write and crm.objects.deals.write scopes. For Salesforce, ensure api and refresh_token scopes are enabled.

Add OpenAI:

Click Add Credential. Search for OpenAI. Paste your API

key. Set the organization ID if you have multiple orgs under one account.

Step 2: Build the Email Logger Workflow

Create a new workflow. Name it Email Logger - Outbound.

Node 1: Gmail Trigger (or Outlook Trigger)

Drag the Gmail node onto the canvas. Set Event to Message Sent. Set Label/Folder to Sent. Under Filters, add a condition: Recipient Domain does NOT contain @yourfirm.com. Replace yourfirm.com with your actual domain. This prevents internal emails from cluttering the CRM

.

Click Listen for Test Event. Send an email from your account to an external address. Confirm the trigger fires and displays the email body in the output panel.

Node 2: OpenAI Chat Model

Drag the OpenAI node onto the canvas. Connect it to the Gmail Trigger. Set Model to gpt-4. Set Temperature to 0.2 (lower temperature = more consistent output).

In the Messages section, add a System Message:

You are a CRM data extraction assistant. Read the email thread below and extract exactly two things:
1. A 2-sentence summary of what was discussed or agreed upon.
2. Any explicit next steps, action items, or deadlines mentioned.

Output raw JSON only. No markdown. No explanation. Use this exact schema:
{ "summary": "...", "next_steps": "..." }

If no next steps exist, return "next_steps": "None specified".

Add a User Message. Set the content to {{ $json.body }} (this pulls the email body from the trigger node).

Test the node. Verify the output is valid JSON. If you get markdown code fences (```json), adjust the system prompt to say "Output raw JSON with no formatting."

Node 3: CRM Search

Drag a HubSpot node (or Salesforce node) onto the canvas. Connect it to the OpenAI node. Set Resource to Contact. Set Operation to Search. Set Filter Property to Email. Set Filter Value to {{ $json.to }} (this pulls the recipient email from the trigger).

Test the node. If the contact exists, you'll see their record in the output. If not, the output will be empty.

Node 4: IF Node (Exception Handling)

Drag an IF node onto the canvas. Connect it to the CRM Search node. Set Condition to {{ $json.id }} (HubSpot) or {{ $json.Id }} (Salesforce) is not empty.

This splits the workflow into two branches: True (contact exists) and False (contact does not exist).

Node 5a: CRM Update (True Branch)

Drag another HubSpot or Salesforce node onto the canvas. Connect it to the True output of the IF node. Set Resource to Contact. Set Operation to Update. Set Contact ID to {{ $json.id }} (HubSpot) or {{ $json.Id }} (Salesforce).

Under Properties to Update, add two fields:

  • AI Summary: {{ $node["OpenAI Chat Model"].json.summary }}
  • Next Steps: {{ $node["OpenAI Chat Model"].json.next_steps }}

Test the node. Check your CRM. Verify the fields populate correctly.

Node 5b: Slack Alert (False Branch)

Drag a Slack node onto the canvas. Connect it to the False output of the IF node. Set Resource to Message. Set Operation to Post. Set Channel to #crm-exceptions.

Set Text to:

⚠️ Unlogged Email Detected
Sender: `{{ $node["Gmail Trigger"].json.from }}`
Recipient: `{{ $node["Gmail Trigger"].json.to }}`
Subject: `{{ $node["Gmail Trigger"].json.subject }}`

This person is not in the <GlossaryTerm term="CRM">CRM</GlossaryTerm>. Add them manually if they're a prospect.

Test the node. Confirm the message appears in your Slack channel.

Activate the Workflow:

Click Active in the top right. The workflow is now live. Every outbound email will trigger this automation.

Step 3: Build the Calendar Logger Workflow

Create a new workflow. Name it Calendar Logger - Meetings.

Node 1: Schedule Trigger

Drag a Schedule Trigger node onto the canvas. Set Trigger Interval to Days. Set Days Between Triggers to 1. Set Trigger at Hour to 23 (11:00 PM). Set Trigger at Minute to 0.

Node 2: Google Calendar (or Outlook Calendar)

Drag a Google Calendar node onto the canvas. Connect it to the Schedule Trigger. Set Resource to Event. Set Operation to Get All. Set Calendar to your primary calendar.

Under Filters, set Time Min to {{ $now.minus({days: 1}).startOf('day').toISO() }} and Time Max to {{ $now.minus({days: 1}).endOf('day').toISO() }}. This retrieves only yesterday's events.

Test the node. Verify it returns your meetings from yesterday.

Node 3: Filter Node

Drag a Filter node onto the canvas. Connect it to the Calendar node. Set Condition to {{ $json.attendees }} is not empty. This filters out personal events with no attendees.

Node 4: OpenAI Chat Model

Drag an OpenAI node onto the canvas. Connect it to the Filter node. Use the same model settings as before (GPT-4, temperature 0.2).

System Message:

You are a meeting summarizer. Read the calendar event details below and generate a 1-sentence summary of the meeting purpose based on the event title and description.

Output raw JSON only:
{ "summary": "..." }

User Message:

Event Title: `{{ $json.summary }}`
Event Description: `{{ $json.description }}`

Node 5: CRM Activity Log

Drag a HubSpot or Salesforce node onto the canvas. Connect it to the OpenAI node. Set Resource to Engagement (HubSpot) or Task (Salesforce). Set Operation to Create.

Set Type to Meeting. Set Subject to {{ $node["Google Calendar"].json.summary }}. Set Body to {{ $json.summary }}. Set Timestamp to {{ $node["Google Calendar"].json.start.dateTime }}.

Activate the workflow. It will run nightly and log all yesterday's meetings.

Step 4: Build the Daily Digest Workflow

Create a new workflow. Name it Daily Digest - Priority Accounts.

Node 1: Schedule Trigger

Set Trigger at Hour to 7. Set Trigger at Minute to 0.

Node 2: CRM Query

Drag a HubSpot or Salesforce node onto the canvas. Set Resource to Contact. Set Operation to Get All. Add a filter: Priority Flag equals True (or whatever field you use to mark VIP accounts).

Node 3: Slack Message

Drag a Slack node onto the canvas. Set Channel to the user's direct message channel (use @username format). Set Text to:

Good morning. Here are your priority accounts with recent activity:

`{{ $json.map(contact => `- ${contact.firstname} ${contact.lastname} (${contact.company}): Last activity ${contact.notes_last_updated}`).join('\n') }}`

Activate the workflow. Users will receive their digest at 7:00 AM daily.

Step 5: Pilot and Scale

Do not activate all three workflows for the entire firm on Day 1.

Week 1: Activate the Email Logger for yourself only. Modify the Gmail Trigger filter to include Sender Email equals your.email@firm.com. Send 10-15 test emails to real prospects. Verify summaries appear in the CRM within 60 seconds.

Week 2: Add two more users. Monitor the #crm-exceptions channel. If you see repeated alerts for the same missing contacts, add them in bulk via CSV import.

Week 3: Activate the Calendar Logger. Check that meeting logs appear the morning after each event. If summaries are too generic, refine the OpenAI system prompt to include more context (e.g., "Focus on outcomes and decisions made").

Week 4: Roll out to the full firm. Announce in your all-hands meeting. Share a 2-minute Loom video showing the CRM auto-populating in real time.

Success Metrics

Track these in your CRM analytics dashboard:

Activity Volume: Compare the 30 days before activation to the 30 days after. You should see a 40-60% increase in logged activities (emails, meetings, notes).

Manual Entry Rate: Query your CRM for activities created via the web UI or mobile app. This number should drop to near zero for the pilot group.

Exception Rate: Count the number of alerts in #crm-exceptions. If it exceeds 10% of total emails sent, your team is emailing too many people outside the CRM

. Run a data hygiene sprint to import missing contacts.

Digest Engagement: Survey users after 30 days. Ask: "Do you read the daily digest?" and "Has it changed how you prioritize your day?" Aim for 70%+ yes responses.

If any metric underperforms, revisit the OpenAI prompts first. Poorly tuned prompts produce garbage summaries, which kills trust in the system.

Revenue Institute

Reviewed by Revenue Institute

This guide is actively maintained and reviewed by the implementation experts at Revenue Institute. As the creators of The AI Workforce Playbook, we test and deploy these exact frameworks for professional services firms scaling without new headcount.

Revenue Institute

Need help turning this guide into reality? Revenue Institute builds and implements the AI workforce for professional services firms.

RevenueInstitute.com