HubSpot Sync

Keep your Gravity Rail members and HubSpot contacts in sync with bidirectional field mapping, flexible transforms, and real-time progress tracking.

Advanced
16 min read

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:

  1. 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.
  2. 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

  1. Go to Developer > HubSpot and select the Sync tab.
  2. 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.
  3. Turn on one or both directions for each entity type you want to sync.
  4. 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 TypeDescriptionHubSpot Support
memberSync workspace members with external contacts/recordsYes
recordSync data records (form submissions)No (Monday.com only)
calendar_eventSync calendar eventsNo
fileSync filesNo

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:

RuleOutbound (GR to HubSpot)Inbound (HubSpot to GR)
NameSplits the member's name into firstname and lastnameJoins firstname and lastname into the member's name
EmailCopies the member's email to the HubSpot email propertyCopies the HubSpot email property to the member's email
PhoneCopies the member's phone to the HubSpot phone propertyCopies 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

  1. In the Sync Rules card, click Add Sync Rule.
  2. A new rule appears with the name "New Rule." Click the name to rename it to something descriptive (e.g., "Company" or "Insurance Status").
  3. Click the chevron to expand the rule and see its outbound and inbound operations.
  4. Add operations in either or both directions (see sections below).
  5. 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:

CategoryExamplesDescription
Core propertiesName, Email, PhoneStandard member fields
Managed fieldsAny custom fields defined on your membersFields created by integrations or custom configuration
Form fieldsIntake: Status, Assessment: ScoreValues from form records attached to the member
LabelsVIP, Active, At RiskWhether the member has a specific label applied
Custom ExpressionAny CEL expressionFull 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:

  1. Expand your rule (or create a new one called "Insurance").
  2. Click Add outbound.
  3. On the left, open the source dropdown and select Intake: Insurance Provider from the list.
  4. On the right, search for your HubSpot custom property (e.g., insurance_provider).
  5. 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:

TargetWhen to use itExamples
Core PropertiesUpdate standard member fieldsName, Email, Phone
Managed FieldsStore data as a custom field on the member, managed by the HubSpot connectionCompany name, job title, or any HubSpot property you want visible on the member profile
LabelsApply or remove a member label based on a HubSpot valueComing soon -- shown in the UI but not yet functional for HubSpot
Form FieldsWrite to a field on a form recordComing 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:

  1. Create a new rule called "Company."
  2. Click Add inbound.
  3. On the left, select company from the HubSpot properties dropdown.
  4. On the right, select an existing managed field or choose New Managed Field and name it (e.g., hubspot:company).
  5. 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:

ExpressionWhat it returns
source.nameThe member's full name (outbound) or contact property (inbound)
source.emailThe member's email address
source.phoneThe member's phone number
source.form_data.intake.statusThe "status" field from the member's "Intake" form record

Available Functions

CEL includes several built-in functions for transforming text:

FunctionWhat it doesExample
split(str, delimiter)Splits a string into a listsplit(source.name, ' ')[0] returns the first word
trim(str)Removes leading and trailing whitespacetrim(source.name)
lowerAscii(str)Converts to lowercaselowerAscii(source.email)
upperAscii(str)Converts to uppercaseupperAscii(source.name)
size(list)Counts items in a listsize(split(source.name, ' '))
contains(str)Checks if a string contains a substringsource.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:

PresetWhat it doesExpression it generates
No TransformPasses the value through unchangedvalue
First NameExtracts the first word from a namesplit(value, ' ')[0]
Last NameExtracts the last word from a nameLast word of a space-separated string
Trim WhitespaceRemoves extra spacestrim(value)
LowercaseConverts to lowercaselowerAscii(value)
UppercaseConverts to uppercaseupperAscii(value)
Email DomainExtracts the domain from an email addressDomain 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

FilterWhat 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:

  1. Scroll to the Default Lifecycle Stage section below the sync rules.
  2. Select a stage from the dropdown: Subscriber, Lead, Marketing Qualified Lead, Sales Qualified Lead, Opportunity, Customer, Evangelist, or Other.
  3. 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:

  1. Go to the Logs tab (next to the Sync tab on the HubSpot page).
  2. 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.
  3. 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.
  • Channels -- Overview of all communication channels and integrations
  • Members -- Managing member profiles and data
  • Forms -- Structured data collection used in sync rules
  • Labels -- Tagging and categorization for members