HubSpot Integration


The HubSpot integration is a two-way sync between GrowPanel and your HubSpot CRM. GrowPanel pushes MRR, ARR, plan, status, and lifecycle dates onto matched HubSpot companies or contacts, and pulls back any HubSpot property (industry, employee count, lifecycle stage, etc.) into GrowPanel as filterable custom variables.


Connecting HubSpot

  1. Go to Settings → Integrations
  2. Find the HubSpot card and click Connect
  3. You'll be redirected to HubSpot to approve the connection
  4. Pick the HubSpot account (portal) to connect, then click Connect app
  5. You're redirected back to GrowPanel and the Configure modal opens automatically

GrowPanel asks for the following HubSpot scopes:

  • oauth
  • crm.objects.companies.read, crm.objects.companies.write
  • crm.objects.contacts.read, crm.objects.contacts.write
  • crm.schemas.companies.write, crm.schemas.contacts.write

The schema scopes are required so GrowPanel can create the growpanel_* custom properties on first save. GrowPanel cannot read or modify anything outside the companies/contacts objects.


Configuring the integration

After connecting, the Configure modal lets you set how the sync behaves. You can change these settings at any time from the integrations page.

Sync to

Choose which HubSpot object type to write to:

  • Companies — typical for B2B (one record per organization)
  • Contacts — typical for B2C (one record per individual)

Match by

How GrowPanel finds the right HubSpot record for each customer. This is the single most important setting in the integration — see Choosing the right match strategy below.

  • Email — exact email match (best for B2C, or B2B where the billing email is also the primary HubSpot contact)
  • Email domain — everything after @, matched against the HubSpot company domain property (best for B2B where one HubSpot company = one customer account)
  • GrowPanel customer ID — matches by the growpanel_external_id property. Most reliable once records have been synced at least once, because GrowPanel writes the ID on first sync. Use this if neither email nor domain reliably identifies the right record.

Create record if no match found

  • Checked: customers without a matching HubSpot record are created as new records
  • Unchecked: customers without a match are skipped — only existing HubSpot records get updated

Recommended for B2B teams that want HubSpot to stay manually curated.

Fields to push to HubSpot

Tick the GrowPanel metrics you want written to HubSpot on every sync. The corresponding growpanel_* custom properties are created automatically in your HubSpot account when you save.

FieldHubSpot propertyType
MRRgrowpanel_mrrNumber
ARRgrowpanel_arrNumber
Total amount paid (lifetime)growpanel_total_amountNumber
Statusgrowpanel_statusText (lead / trial / active / churned / paused)
Current plan (raw plan name)growpanel_planText
Plan groupgrowpanel_plan_groupText
Paid started dategrowpanel_paid_startedDate
Trial started dategrowpanel_trial_startedDate
Cancel dategrowpanel_cancel_dateDate
Next billing dategrowpanel_next_billing_dateDate

growpanel_external_id (the GrowPanel customer ID) is always pushed regardless of which fields you select — it's used to reverse-match records on future syncs.

Import fields from HubSpot

Pull HubSpot properties into GrowPanel as filterable custom variables. Each row maps one HubSpot property → one GrowPanel custom variable name.

The HubSpot property dropdown lists every property available on your portal for the chosen object type. The most commonly used properties (domain, industry, employee count, etc.) appear at the top under Common properties; the rest follow alphabetically.

Imported values appear in filter and group-by dropdowns across every report — the new keys are added to the account-level cache the moment you save, even before any sync has pulled values.


Syncing

There are three ways customer data ends up in HubSpot:

Sync a single customer

On any customer detail page, click the Resync button (it becomes a dropdown when HubSpot is connected) and choose Sync to HubSpot. This runs synchronously and gives you immediate feedback — useful for testing.

Sync all customers

From Settings → Integrations, click the refresh icon on the HubSpot card. This queues every customer in your account for sync. A progress bar shows on the card; you'll get an email when it completes.

For large accounts (thousands of customers) this runs in the background — you can keep using GrowPanel while it runs.

Auto-sync on changes

After the initial sync, GrowPanel automatically pushes updates to HubSpot whenever a customer's MRR or status changes (new subscription, plan upgrade, churn, etc.). Changes typically appear in HubSpot within a few minutes of the billing event.


What gets synced

Per customer, every sync does three things in order:

  1. Match — search HubSpot for a record matching the configured strategy (email / domain / external_customer_id)
  2. Push — write the configured growpanel_* properties to the matched record (or create a new record if createIfNoMatch is enabled and no match was found)
  3. Pull — read the configured importFields HubSpot properties back into the customer's custom_variables in GrowPanel

If Create record if no match found is unchecked and no match exists, the customer is skipped (counted as success — nothing failed, just nothing to do).


Best practices

Choosing the right match strategy

Pick the one that mirrors how the same person or company is identified in your billing system and in HubSpot:

If your billing source records customers as……and your HubSpot has one record per…Use
Individual users (Stripe customer = one person, B2C)ContactEmail
Companies (Stripe customer email = somebody at the company)CompanyEmail domain
Companies, but multiple billing contacts at the same domain shouldn't mergeCompanyGrowPanel customer ID
You've imported HubSpot records before GrowPanel ever saw themEitherStart with Email or Email domain, then switch to GrowPanel customer ID after the first full sync

Make sure your billing source and HubSpot agree on identity. If Stripe stores accounting@acme.com as the customer email but HubSpot has cto@acme.com as the only contact, matching by Email will fail for that customer. Matching by Email domain (acme.com) catches both — at the cost of mapping everyone at that domain to the same company record. Pick the strategy that produces the smallest number of orphans and the smallest number of incorrect merges.

Don't switch match strategies mid-flight

If you've already synced once with one strategy and then switch to another, the previous matches stay where they are — GrowPanel doesn't go back and re-link records. For a clean cut, switch the strategy, then run a full bulk sync so every customer is re-matched under the new rules.

Keep the field selection focused

Only push the fields your team actually uses in HubSpot views, workflows, or scoring. Every additional field is one more value to keep consistent. MRR, status, and current plan cover the majority of use cases.

Settings survive disconnect and reconnect

If you disconnect the integration and reconnect it later (same HubSpot portal), GrowPanel remembers your previous configuration — match strategy, field selection, imported properties — and pre-fills the modal. You only need to re-confirm and save. This makes it safe to disconnect temporarily for troubleshooting.


Using HubSpot properties as filters & group-by

Anything you list under Import fields from HubSpot becomes a first-class GrowPanel filter and grouping dimension. The HubSpot property company_owner, for example, shows up as a "Group by" option and as a filter in:

This is the easiest way to slice your business by dimensions that live outside billing — sales owner, industry, employee range, ICP segment, region, lifecycle stage, anything you can put on a HubSpot record.

How GrowPanel classifies imported properties

When HubSpot values arrive in GrowPanel, GrowPanel scans them and classifies the property:

  • Low-cardinality (≤ 50 distinct values across all customers, e.g. company_owner, industry) — shown as a checkbox filter with all options listed, and available as a Group by dimension.
  • High-cardinality (more than 50 distinct values, or free-text fields like notes) — shown as a search filter where users type a value. Not available as Group by (it would produce a chart with too many series to be useful).

The classification happens automatically:

  • On every bulk sync (Settings → Integrations → refresh icon), after all customers have been synced.
  • On every full resync from your billing source (Stripe, Chargebee, Recurly).

If you've just imported a new HubSpot property and don't see it as a Group by option yet, run a bulk sync — it'll be classified at the end and become available everywhere within a minute or two.

Combining HubSpot dimensions with segments

Filters and group-by are powerful on their own, but the real payoff is segments — saved filter combinations you can reuse. Examples:

  • Filter industry = "SaaS" + company_owner = "Alex" → save as "Alex's SaaS book"
  • Filter employee_range = "200-500" + region = "EU" → save as "Mid-market EU"

Then pin a dashboard widget to that segment (Per-widget settings → Segment filter) and you have an at-a-glance view of that slice of the business.


Disconnecting

Click the trash icon on the HubSpot card. GrowPanel revokes its OAuth token and stops syncing. The growpanel_* properties stay on your HubSpot records with their last-synced values — they're not deleted. To clean them up, delete them from HubSpot's properties settings.

Your configuration (match strategy, field selection, imported properties) is preserved — if you reconnect later, the Configure modal pre-fills with everything you had before.


Troubleshooting

"Properties are empty in HubSpot for most customers"

If the customer's GrowPanel data is empty (e.g., they're a lead with no paid_started date yet), the property is set to an empty value in HubSpot. This is intentional — it keeps the two systems consistent if a customer state changes.

"I can't see industry / employee count / founded year on company records"

These fields aren't filled in automatically by HubSpot unless you have Breeze Intelligence (paid HubSpot add-on) enabled. Without enrichment, those properties exist on the record but are empty. Once you enrich (manually per record, or via a workflow), the values flow into GrowPanel on the next sync.

"Email matching is putting many customers on the same HubSpot record"

When matching by email domain, customers sharing a domain (e.g., everyone at gmail.com) all match the same HubSpot company. This is expected behavior for B2C signups. Consider matching by GrowPanel customer ID instead if you want one HubSpot record per GrowPanel customer.

"My imported HubSpot property doesn't show up in Group by"

Properties only appear in Group by once GrowPanel has classified them as low-cardinality (≤ 50 distinct values). Classification happens at the end of every bulk sync — if you've just added the property, run a bulk sync from the HubSpot card and the dimension will be available everywhere afterwards. See How GrowPanel classifies imported properties for details.

"Bulk sync stuck at X of Y"

If progress sits idle, check the Cloudflare Queues dashboard or contact support — some messages may have failed all retries and ended up in the dead-letter queue. Re-running the bulk sync will retry them.


API reference

See the interactive API reference (filter to Settings) for the underlying REST endpoints, useful if you're scripting integration changes.