GoHighLevel CRM Integration
Connect GoHighLevel (GHL) to automatically sync leads and booking data to your CRM.
Benefits
- Automatic Lead Sync: Leads pushed to GHL automatically
- Status Updates: Booking status synced in real-time
- Custom Field Mapping: Form responses sync to GHL fields
- Workflow Triggers: Trigger GHL automations from bookings
Connecting HighLevel
The connection is authorized entirely through HighLevel. You don't need an API key, and you don't enter a Location ID anywhere in SalesCal.
- Go to Integrations
- Find HighLevel
- Click Connect
- A HighLevel window opens. Sign in if you aren't already
- Choose the location (sub-account) you want to connect, and approve the requested permissions
- The window closes and the card shows as connected
The location you pick during that approval step is the one SalesCal syncs to. To sync to a different location, disconnect and connect again.
Reconnecting
SalesCal allows one CRM per team, so connecting HighLevel means you can't also have HubSpot connected at the same time. If you click Connect while a connection is already active you'll see:
gohighlevel is already connected. Disconnect first.
Disconnect from the same card, then connect again.
Reconnect if you change your HighLevel password, remove SalesCal from HighLevel's connected apps, or start seeing failures in the sync log.
How Sync Works
Lead Creation
When a lead is captured in SalesCal:
- Contact created in GHL
- Contact data mapped to GHL fields
- GHL contact ID stored in SalesCal
- Future updates use this ID
Sync Triggers
| Event | GHL Action |
|---|---|
| Step 1 Complete | Contact created (status: incomplete) |
| Qualification Pass | Contact updated (status: qualified) |
| Qualification Fail | Contact updated (status: disqualified) |
| Booking Complete | Contact updated (status: booked) |
Data Synced
| SalesCal Field | GHL Field |
|---|---|
| First Name | First Name |
| Last Name | Last Name |
| Phone | Phone |
| Custom Fields | Custom Fields (mapped) |
| Lead Score | Custom Field (optional) |
| Lead Grade | Custom Field (optional) |
| Event Name | Tag or Custom Field |
Custom Field Mapping
Map SalesCal form fields to GHL custom fields:
- Go to integration settings
- Find Field Mapping
- For each SalesCal field:
- Select the corresponding GHL field (each dropdown has a search box at the top — type to filter the list)
- Or create a new GHL field
- Save mappings
Mapping Best Practices
- Match field types (text to text, dropdown to dropdown)
- Use consistent naming
- Map all important fields
- Test with a sample lead
One Saved Question, One GHL Field
Form fields come from your team's shared question library, so a question reused across several events still maps to a single GHL field — you won't get duplicate fields for the same question. Archived questions (from Settings → Questions) can't be picked for a new mapping, but a mapping created before the question was archived keeps working and still shows in your mapping list tagged (archived) — in manual mapping it moves to the Legacy Fields card, where you can unmap it whenever you no longer want it to sync.
When a Mapped Field Is Deleted in GHL
Mappings remember the exact field they point at, so deleting a custom field inside GHL doesn't remove its SalesCal mapping — the row stays in your list. When SalesCal loads your GHL field list and the mapped field is no longer in it, the row shows an amber warning: "This field no longer exists in HighLevel — re-map or delete". Pick a different GHL field to re-map the row, or set it to -- Unmapped -- to remove the mapping.
If you've just recreated the field in GHL, click the refresh button next to the mapped-field count at the top of the Configuration tab to reload the field list — the warning clears once the field is back.
Re-running auto-map (Re-run auto-map in Auto mode, or Auto-map fields in Manual mode) now recreates any mapping whose target field was deleted, instead of leaving it stale.
Automation-Ready Date and Time Fields
Four system fields turn your booking time into formats HighLevel workflows can actually use:
| Field | Example | Use it for |
|---|---|---|
| SalesCal Call Start Time | 07-28-2026 02:30 PM | HighLevel's Event Start Date workflow action — set it on a custom field, then use Wait events relative to it |
| Lead Timezone | Europe/London | The timezone your prospect picked their slot in |
| Call Day/Date (Lead timezone) | Tuesday July 28, 2026 | Prospect-facing message copy — reads naturally when quoted back, e.g. "see you Tuesday July 28, 2026" |
| Call Time (Lead timezone) | 7:30 PM | Prospect-facing message copy — "your call is at 7:30 PM your time" |
If your connection predates this feature, you'll see a banner on the Configuration tab recommending you reconnect and re-run auto-map so these fields start syncing.
Using SalesCal Call Start Time with the Event Start Date action: if you used automap, SalesCal already created a HighLevel contact field named SalesCal Call Start Time and sends the value there — in your workflow, point the Event Start Date action at that field and you're done. (HighLevel derives the field's merge tag from its name, so it appears as something like {{contact.salescal_call_start_time}} — the exact tag spelling doesn't matter to the action.) If you'd rather use a custom field you already have, such as appointment_start_time, change this field's target in Field Mapping to your existing field instead, and point the action at that one. Either way, this lets you drive Wait steps off the adjusted booking time without needing a native HighLevel appointment.
SalesCal Call Start Time renders in your connected HighLevel account's Business Profile timezone, captured automatically the moment you connect or reconnect. Until you reconnect, it's written in the timezone of the team member hosting each call (UTC if that host hasn't set one) — after reconnecting, it always uses your HighLevel account's timezone instead.
These fields are custom-field values for merge tags and workflow automations — between them and HighLevel's Event Start Date action, your workflows can react to the exact booking time without any extra setup.
Your prospect's timezone
When a prospect books, SalesCal records the timezone they chose their slot in — detected from their browser, or whatever they switched the widget to. Two things happen with it:
- The contact's standard Time Zone field in HighLevel is filled in automatically. Any workflow you set to "Contact Timezone" then waits and sends on the prospect's clock, using HighLevel's own machinery. (If you map something else to the Time Zone field yourself, your mapping wins.)
- The Call Day/Date (Lead timezone) and Call Time (Lead timezone) fields above become available for mapping. Use them in prospect-facing messages: HighLevel's
{{appointment.only_start_time}}merge field always renders in your account's timezone, which reads wrong to a prospect three timezones away — the Lead-timezone fields read right.
Leads that booked before this feature (or without a detectable timezone) leave these fields empty rather than guessing.
Tag Mapping
GHL has no "lead status" concept, so SalesCal applies tags as a contact moves through each stage. In Tag Mapping, map any of these stages to one or more GHL tags:
| Stage | Meaning |
|---|---|
| New | Started form, didn't finish |
| Qualified | Form completed, passed qualification rules |
| Disqualified | Failed qualification rules |
| Booked | Call is scheduled |
| Rescheduled | Call time changed |
| Cancelled | Booking cancelled |
| Completed | Call completed with an outcome |
When you add a tag, the field suggests tags that already exist in your connected GHL location, so you can pick an existing tag or type a brand-new one. If you type a new name, SalesCal creates the tag in GHL immediately — it shows up in your GHL tag list (and as a workflow trigger option) as soon as the mapping is saved, before any contact reaches that stage.
Tags are applied to a contact at the moment they enter a stage. Adding a mapping doesn't retroactively tag contacts that already passed that stage. If a contact syncs but its tags can't be applied, the sync appears as partial in the Sync Log with the reason, instead of reporting a clean success.
What Gets Pushed
With a calendar selected, every booking on that connection creates a HighLevel appointment titled with the event name and the prospect's name (for example, Demo Call - Jane Smith), with the exact start and end time:
| SalesCal event | HighLevel appointment |
|---|---|
| Booking made | Appointment created |
| Booking rescheduled | The same appointment moves to the new time |
| Booking cancelled | Status set to cancelled |
| Call marked Completed | Status set to showed |
| Call marked No Show | Status set to no-show |
SalesCal owns your booking availability, so the appointment is created even if the HighLevel calendar's own availability rules would have rejected the slot — HighLevel is where your bookings land, not where your booking hours come from. Appointment times respect your HighLevel account's timezone automatically.
Important: SalesCal already sends its own confirmation, reminder, and cancellation emails, so HighLevel's calendar notifications for this appointment are not triggered — your prospect won't get a duplicate confirmation from HighLevel.
In your HighLevel automations, use the "Appointment Status" workflow trigger — not "Customer Booked Appointment." HighLevel only fires "Customer Booked Appointment" for bookings made through its own booking widget, never for appointments created by an integration like SalesCal. An automation built on "Customer Booked Appointment" will silently never run for these bookings.
If a push fails, it won't block the rest of the sync — check the Sync Log for a partial entry with the reason.
*/}
GHL Automations
Trigger Ideas
On Incomplete Lead:
- Send follow-up email
- Add to nurture sequence
- Notify sales rep
On Qualified Lead:
- Send confirmation
- Assign to rep
- Add to hot lead list
On Disqualified Lead:
- Send polite decline
- Add to long-term nurture
- Log for analysis
On Booking:
- Send preparation email
- Create task for rep
- Add calendar reminder
Setting Up Automations
- In GHL, create a workflow
- Set trigger: "Contact Tag Added" or "Custom Field Changed" — or "Event Start Date" conditions built on the SalesCal Call Start Time field
- Use the SalesCal status values
- Add your automation steps
Duplicate Handling
When a lead already exists in GHL:
- By Email: Existing contact updated
- New Contact: Created if no match found
- Merge Settings: Follow your GHL duplicate settings
Troubleshooting
"Failed to Connect"
- Make sure you completed the approval step in the HighLevel window rather than closing it early
- Check your browser isn't blocking the popup
- Confirm the HighLevel user you signed in as has access to the location you're trying to connect
- If a connection already exists, disconnect it first — SalesCal allows one CRM per team
Leads Not Syncing
- Verify the connection is still active on the Integrations page
- Check the Sync Log tab for failed attempts and the reason given
- Confirm you connected the HighLevel location you're actually looking at
- Test with a new lead — the log entry appears within a few seconds
Custom Fields Not Mapping
- Verify field mapping is saved
- Check field types match
- Ensure GHL field exists
- Test the specific field
Can't Create Fields in GHL ("not authorized" / permission error)
Creating custom fields needs write permission that older connections didn't grant. Disconnect and reconnect GoHighLevel to refresh permissions, then try again.
Duplicate Contacts
- Review GHL duplicate settings
- Check if email matching is enabled
- Consider merging duplicates manually
Status Not Updating
- Verify webhook/trigger is active
- Check GHL automation is running
- Look for GHL error logs
Viewing Sync Status
In SalesCal lead records:
- GHL Contact ID: Shows if synced
- GHL Synced At: Last sync timestamp
- Sync Status: Success or error
Disconnecting GoHighLevel
To remove the connection:
- Go to Integrations
- Find GoHighLevel
- Click Disconnect
- Confirm
Note: Existing GHL contacts remain, but new leads won't sync.
Data Privacy
- Only lead data is sent to GHL
- Follows your GHL privacy settings
- You control what fields sync
- Can disconnect at any time
Best Practices
Clean Setup
- Map all fields before going live
- Test sync with sample leads
- Set up automations for each status
Consistent Data
- Use same field names when possible
- Keep custom fields organized
- Document your mapping
Monitor Syncs
- Check sync status regularly
- Address errors promptly
- Review automation performance
Leverage Automations
- Automate follow-ups
- Create tasks for sales team
- Segment leads by status/grade
Advanced: Webhook Mode
For more control, use webhooks:
- Enable webhook mode in integration settings
- SalesCal sends events to your webhook
- Your system processes and syncs to GHL
- More flexibility for custom logic
Related Guides
- Managing Leads - Lead management in SalesCal
- Qualification Rules - Status triggers
- Lead Grading - Scoring data sync