HubSpot Sync
Keep your Gravity Rail members and HubSpot contacts in sync with bidirectional field mapping, flexible transforms, and real-time progress tracking.
HubSpot Sync
Sync data between Gravity Rail and HubSpot so your CRM stays current without manual work. Push member updates to HubSpot contacts, pull contact changes back into Gravity Rail, or run both directions at once. You control exactly which fields sync and how they're transformed along the way.
Before You Start
You'll need two things in place before configuring sync:
- A connected HubSpot account -- Your workspace must have an active HubSpot integration with OAuth connected. If you haven't set this up yet, go to Developer > Apps and connect HubSpot first.
- The HubSpot feature enabled -- Your workspace needs the HubSpot feature flag. Contact your Gravity Rail administrator if you don't see the HubSpot option under Developer.
Enabling Sync
- Go to Developer > HubSpot and select the Sync tab.
- You'll see a sync configuration for each entity type (e.g., members). Each entity type has its own toggles:
- Enable outbound sync -- Pushes data from Gravity Rail to HubSpot.
- Enable inbound sync -- Pulls HubSpot data into Gravity Rail.
- Turn on one or both directions for each entity type you want to sync.
- Click Save Sync Settings at the bottom of the page.
You can enable one direction and add the other later. If you're setting this up for the first time, starting with outbound only is a good approach -- it lets you verify your field mappings before pulling data back.
Entity Types
The sync framework supports multiple entity types. Each connector supports a subset of these, and the available types are shown in the Sync tab:
| Entity Type | Description | HubSpot Support |
|---|---|---|
| member | Sync workspace members with external contacts/records | Yes |
| record | Sync data records (form submissions) | No (Monday.com only) |
| calendar_event | Sync calendar events | No |
| file | Sync files | No |
HubSpot currently supports the member entity type, syncing workspace members with HubSpot contacts.
Understanding Sync Rules
A sync rule is a named group of field mappings that defines how a specific piece of data moves between Gravity Rail and HubSpot. Each rule has a name (like "Name" or "Email") and contains one or more operations in each direction.
Think of a rule as a container for related data. The "Name" rule, for example, handles splitting a member's full name into first and last name for HubSpot (outbound), and joining first and last name back into a full name for Gravity Rail (inbound). Keeping these operations grouped under one rule makes them easier to find and manage.
Default Rules
When you first enable sync, three rules are created automatically:
| Rule | Outbound (GR to HubSpot) | Inbound (HubSpot to GR) |
|---|---|---|
| Name | Splits the member's name into firstname and lastname | Joins firstname and lastname into the member's name |
Copies the member's email to the HubSpot email property | Copies the HubSpot email property to the member's email | |
| Phone | Copies the member's phone to the HubSpot phone property | Copies the HubSpot phone property to the member's phone |
These defaults cover the most common fields. You can edit them, disable individual rules with their toggle switch, or delete them entirely if they don't fit your setup.
Creating a New Rule
- In the Sync Rules card, click Add Sync Rule.
- A new rule appears with the name "New Rule." Click the name to rename it to something descriptive (e.g., "Company" or "Insurance Status").
- Click the chevron to expand the rule and see its outbound and inbound operations.
- Add operations in either or both directions (see sections below).
- Click Save Sync Settings when you're done.
Editing a Rule
Each rule card shows a summary of how many outbound and inbound operations it contains (e.g., "2 out, 1 in"). Click the chevron to expand it and see the full details. You can:
- Rename the rule by editing the text field in the header.
- Enable or disable the rule with the toggle switch. Disabled rules are saved but skipped during sync.
- Delete the rule with the trash icon. This removes it permanently.
Outbound Operations (Gravity Rail to HubSpot)
An outbound operation takes data from a Gravity Rail member and writes it to a HubSpot contact property. Each operation has two parts:
- Source (left side) -- What data to read from the member. Select from the dropdown or write a custom expression.
- HubSpot property (right side) -- Which HubSpot contact property to write the value to. The dropdown shows all properties available on your HubSpot contacts.
To add an outbound operation, expand a rule and click Add outbound.
Source Options
The source dropdown includes several categories of member data:
| Category | Examples | Description |
|---|---|---|
| Core properties | Name, Email, Phone | Standard member fields |
| Managed fields | Any custom fields defined on your members | Fields created by integrations or custom configuration |
| Form fields | Intake: Status, Assessment: Score | Values from form records attached to the member |
| Labels | VIP, Active, At Risk | Whether the member has a specific label applied |
| Custom Expression | Any CEL expression | Full control over the value (see Expressions below) |
Example: Syncing a Form Field to HubSpot
Suppose you have a form called "Intake" with a field called "Insurance Provider," and you want that value to appear on the HubSpot contact as a custom property:
- Expand your rule (or create a new one called "Insurance").
- Click Add outbound.
- On the left, open the source dropdown and select Intake: Insurance Provider from the list.
- On the right, search for your HubSpot custom property (e.g.,
insurance_provider). - Save.
Now, every time a sync runs, each member's insurance provider value will be written to HubSpot.
Inbound Operations (HubSpot to Gravity Rail)
An inbound operation takes data from a HubSpot contact and writes it to a Gravity Rail member. Each operation has two parts:
- HubSpot source (left side) -- Which HubSpot property to read. Select from the dropdown, which shows all contact properties from your HubSpot account, or write a custom expression.
- GR field (right side) -- Where to store the value in Gravity Rail. The dropdown organizes targets into groups.
To add an inbound operation, expand a rule and click Add inbound.
Target Types
When selecting where to store inbound data, the GR field dropdown offers four categories:
| Target | When to use it | Examples |
|---|---|---|
| Core Properties | Update standard member fields | Name, Email, Phone |
| Managed Fields | Store data as a custom field on the member, managed by the HubSpot connection | Company name, job title, or any HubSpot property you want visible on the member profile |
| Labels | Apply or remove a member label based on a HubSpot value | Coming soon -- shown in the UI but not yet functional for HubSpot |
| Form Fields | Write to a field on a form record | Coming soon -- shown in the UI but not yet functional for HubSpot |
You can also create new managed fields directly from the dropdown if the one you need doesn't exist yet.
Note: For HubSpot, Core Properties and Managed Fields are the currently supported inbound targets. Labels and Form Fields appear in the dropdown but are not yet wired in the HubSpot sync adapter -- selecting them will have no effect. This will be addressed in a future update.
Example: Pulling Company Name into Gravity Rail
To bring each contact's company name from HubSpot into Gravity Rail as a managed field:
- Create a new rule called "Company."
- Click Add inbound.
- On the left, select
companyfrom the HubSpot properties dropdown. - On the right, select an existing managed field or choose New Managed Field and name it (e.g.,
hubspot:company). - Save.
The company name will now appear on each member's profile after the next inbound sync.
Expressions
Every source value in a sync operation is an expression written in CEL (Common Expression Language). Most of the time, you'll use the preset dropdowns and never need to think about this. But when you need more control -- splitting names, formatting values, or applying conditional logic -- you can select Custom Expression from the dropdown and write your own.
How Expressions Work
In an outbound expression, the variable source refers to the Gravity Rail member. In an inbound expression, source refers to the HubSpot contact. You access properties with dot notation:
| Expression | What it returns |
|---|---|
source.name | The member's full name (outbound) or contact property (inbound) |
source.email | The member's email address |
source.phone | The member's phone number |
source.form_data.intake.status | The "status" field from the member's "Intake" form record |
Available Functions
CEL includes several built-in functions for transforming text:
| Function | What it does | Example |
|---|---|---|
split(str, delimiter) | Splits a string into a list | split(source.name, ' ')[0] returns the first word |
trim(str) | Removes leading and trailing whitespace | trim(source.name) |
lowerAscii(str) | Converts to lowercase | lowerAscii(source.email) |
upperAscii(str) | Converts to uppercase | upperAscii(source.name) |
size(list) | Counts items in a list | size(split(source.name, ' ')) |
contains(str) | Checks if a string contains a substring | source.email.contains('@gmail.com') |
Transform Presets
The expression editor offers labeled presets for common transforms, so you don't need to write CEL for routine operations:
| Preset | What it does | Expression it generates |
|---|---|---|
| No Transform | Passes the value through unchanged | value |
| First Name | Extracts the first word from a name | split(value, ' ')[0] |
| Last Name | Extracts the last word from a name | Last word of a space-separated string |
| Trim Whitespace | Removes extra spaces | trim(value) |
| Lowercase | Converts to lowercase | lowerAscii(value) |
| Uppercase | Converts to uppercase | upperAscii(value) |
| Email Domain | Extracts the domain from an email address | Domain portion after the @ |
Select Custom Expression from the dropdown when none of the presets fit your needs.
Conditional Logic
CEL supports ternary expressions for conditional transforms. For example, to set a HubSpot property based on whether a member has a particular label:
source.has_label("vip") ? "VIP" : "Standard"
Or to handle missing data gracefully:
source.email.contains("@") ? split(source.email, "@")[1] : ""
Sync Filters
Each entity type can have optional outbound filter and inbound filter expressions. These are CEL expressions evaluated per entity before sync runs. If the expression returns a falsy value, that entity is skipped entirely -- no sync operations are performed for it.
Filters are useful for limiting sync to a subset of your data. For example, you might only want to sync members who have an email address, or only sync members with a specific label.
Example Filters
| Filter | What it does |
|---|---|
source.email != '' | Only sync members that have an email address |
source.has_label("vip") | Only sync members with the "VIP" label |
source.form_data.intake.status == 'completed' | Only sync members whose intake form is completed |
The filter context is the same as the sync rule expression context -- you have access to source.name, source.email, source.phone, source.form_data, source.has_label(), managed fields, and labels.
Default Lifecycle Stage
When outbound sync creates a new contact in HubSpot (rather than updating an existing one), you can automatically assign a lifecycle stage. This is useful for ensuring new contacts enter your HubSpot pipeline at the right stage.
To configure this:
- Scroll to the Default Lifecycle Stage section below the sync rules.
- Select a stage from the dropdown: Subscriber, Lead, Marketing Qualified Lead, Sales Qualified Lead, Opportunity, Customer, Evangelist, or Other.
- Select None (do not set) if you don't want to assign a stage automatically.
This setting only applies to new contacts. If a contact already has a lifecycle stage set in HubSpot, it won't be overwritten.
Running a Sync
Manual Sync
To run a sync manually:
- Go to the Logs tab (next to the Sync tab on the HubSpot page).
- Depending on which sync directions you've enabled, you'll see up to three buttons:
- Sync Outbound -- Pushes all member data to HubSpot.
- Sync Inbound -- Pulls all HubSpot contact data into Gravity Rail.
- Sync All -- Runs both directions. Only available when both outbound and inbound are enabled.
- Click the appropriate button to start.
The sync processes all members in your workspace. Progress streams live to your browser -- you can watch each member's status as it's processed.
You can also start a sync from the Sync tab by clicking the Sync Now button in the top-right corner, which takes you to the Logs tab.
Automatic Sync
When sync is enabled, changes are also synced automatically. If a member's data is updated in Gravity Rail, the system triggers an outbound sync for that specific member. You don't need to configure this -- it's managed for you behind the scenes.
Viewing Sync Logs
The Logs tab shows you what happened during each sync run.
Live Progress
While a sync is running, you'll see:
- A progress summary bar showing total members processed, along with counts for synced, failed, and skipped.
- A live event log with one row per member, showing whether it synced successfully, failed, or was skipped.
- A spinning sync icon on the Sync All button while the operation is in progress.
Error Details
If a member fails to sync, its row appears highlighted in red. Click on it to expand and see the specific error message. This is the fastest way to diagnose mapping issues.
Sync History
Below the live event log, you'll find Recent Sync History -- a list of past sync executions showing the status (success or failure), the rule name, and the timestamp.
Managed Fields
When an inbound sync rule writes to a managed field target, that field appears on the member's profile alongside standard fields. Managed fields are owned by the HubSpot connection -- they're created automatically when you configure an inbound rule that targets one, and they stay in sync as long as inbound sync is enabled.
For example, if you create an inbound rule mapping HubSpot's company property to a managed field called hubspot:company, every member matched to a HubSpot contact will show a "Company" field on their profile with the value pulled from HubSpot.
Notes and Tasks
Beyond field sync, you can configure automatic HubSpot note or task creation when forms are submitted. This uses templates with form field variables (e.g., {{ record.data.status }}) to build the note or task content dynamically.
This is useful for creating an audit trail in HubSpot when specific actions happen in Gravity Rail -- for example, creating a HubSpot note every time an intake form is completed.
How Members Are Matched to Contacts
When running a sync, the system needs to determine which HubSpot contact corresponds to which Gravity Rail member. It matches by email address or phone number. If a member has an email that matches a HubSpot contact, they're linked. If no match is found during an outbound sync, a new contact is created in HubSpot.
Troubleshooting
Member Email Address Is Not Valid
HubSpot validates email formats strictly. If a member's email uses a non-standard format or domain (like .test or .example), HubSpot will reject it. Update the member's email to a valid address and re-run the sync.
A Mapped HubSpot Property Does Not Exist
One of your outbound rules references a HubSpot contact property that doesn't exist. Open the Sync tab, expand the rule flagged in the error, and check the HubSpot property dropdown on each outbound operation. The property may have been deleted or renamed in HubSpot.
HubSpot API Rate Limit Reached
HubSpot limits how many API calls can be made in a short period. If you hit this limit during a large sync, the system will retry automatically. For very large workspaces, the sync processes members in batches to stay within limits.
HubSpot Authentication Failed
Your OAuth tokens may have expired or been revoked. Go to Developer > HubSpot and reconnect the integration. You'll need to re-authorize with your HubSpot account.
Expression Returns Empty for Some Members
If a CEL expression references form data (like source.form_data.intake.status) but a member doesn't have a record for that form, the expression returns an empty string. This is expected -- the field is simply not synced for that member. It's not an error.
Sync Button Is Disabled
The sync buttons on the Logs tab are only active when at least one sync direction is enabled. Go to the Sync tab and enable outbound or inbound sync, save your settings, then return to the Logs tab.
Tips
- Start with outbound only. Verify your field mappings work before enabling inbound. Check the Logs tab after your first sync to catch mapping issues early.
- Use presets for common transforms. Custom expressions are powerful but easy to get wrong. The presets handle the most common cases (name splitting, case conversion, whitespace trimming) reliably.
- Use labels as inbound targets. Map HubSpot properties to labels for automatic categorization. For example, pull the lifecycle stage from HubSpot and apply a "Customer" or "Lead" label based on the value.
- Name your rules clearly. When you have more than a handful of rules, descriptive names ("Insurance Info," "Enrollment Status") make it much easier to find what you're looking for later.
- Check managed fields on the member profile. After running an inbound sync, open a member's profile to verify the managed fields are showing the values you expect.