Connect HubSpot

How to get there: Go to Settings in the sidebar → Integrations tab (under Other) → HubSpot section.

Automatically pull customer data from HubSpot CRM to link users to their company and fill in MRR, LTV, lifecycle stage and signup date. Once that data is in, the Companies view and the revenue columns on posts show what your highest-value accounts want.

Setup

  1. In HubSpot, create a Private App (Settings → Integrations → Private Apps → Create a private app)

  2. Under Scopes, tick the ones you need:

    Scope What it gives you in ProductLift
    crm.objects.contacts.read Matches HubSpot contacts to portal users by email and fills firstname, lastname, phone, lifecycle stage
    crm.objects.companies.read Reads the associated Company object when the contact has no freeform company value: its HubSpot id, name and domain. The id is remembered on the ProductLift company, so later syncs land on the same company even after a rename
    crm.objects.deals.read Fills MRR, ARR, deal count and total deal amount (only when "Sync deals" is turned on)
  3. Copy the access token (starts with pat-na1-...)

  4. In ProductLift, go to Settings > Integrations, expand the HubSpot card

  5. Paste the token and click Test connection. A green check means HubSpot accepted the token.

  6. Click Save, then Sync now

The first sync pages through all contacts (100 per page) and self-redispatches in the background until done, so large HubSpot portals do not block the request.

Matching

ProductLift matches HubSpot contacts to portal users by email address. Contacts whose email does not exist in the portal are skipped, no new users are created.

For each match, the integration writes:

  • The user's company: from the contact's freeform company property, or the associated Company object (name, domain, HubSpot id). ProductLift finds the company by HubSpot id first, then by domain, then by name, and creates it when none matches. A user who already belongs to a company keeps it.
  • Company MRR / LTV from closed-won deals (when "Sync deals" is on), only when the company's revenue is still unknown. Values from Stripe or set by hand are never overwritten.
  • Customer status prospect on the company when the lifecycle stage is pre-customer and no other source set a status
  • Signup date from the contact's create date, when still unknown
  • A link row per contact so re-syncs are idempotent

What you get after a sync

  • All Posts page: the MRR column shows the revenue represented behind each post (each company counted once)
  • Companies page (Users → Companies button): one row per company with account MRR/LTV, seats, votes, last activity, and a company page with its top voted posts
  • Filters on posts: filter by MRR range to surface what your largest accounts are asking for

Sync frequency

Syncs are manual only, on demand. There is no scheduled job that pulls HubSpot in the background. You sync when you want a refresh:

  • Full sync: click Sync now in the HubSpot card on Settings → Integrations. This pages through every contact in your HubSpot portal, matches by email, links users to their company and fills in company data. Safe to run as often as you like; it is idempotent.
  • Single-user sync: on a user's detail page (Users → click a user), click Sync from HubSpot. This refetches just that one contact. Use this when a customer just upgraded in HubSpot and you want their MRR/plan reflected immediately without waiting for a full sync.

The HubSpot card shows the last full sync time and any error from the most recent run. If a sync fails (bad token, scope missing), the error is shown inline so you can fix and retry without digging through logs.

Troubleshooting

Company name is empty after sync. The contact's freeform company property is empty in HubSpot and your Private App is missing crm.objects.companies.read. Add the scope, copy the rotated token back into ProductLift, and click Sync now (or Sync from HubSpot on the user page).

Test connection passes but sync errors. Most often a scope mismatch: the connection test only checks contacts read access. If you turned on "Sync deals", the token also needs crm.objects.deals.read.

A user shows up in HubSpot but not after sync. Matching is by email and is case-insensitive. Confirm the email in HubSpot matches the email on the ProductLift user record exactly (no plus-aliases, no whitespace). New contacts that have no matching portal user are skipped, not created.

Removing the integration

Click Disable in the HubSpot card. The encrypted token is removed and no further syncs run. Companies, links and customer data that were synced remain. Re-enable later by pasting the token again.