How to get there: Go to Settings in the sidebar → Integrations tab (under Other) → HubSpot section.
Automatically pull customer data from HubSpot CRM to enrich user profiles with company name, MRR, LTV, plan type and lifecycle stage. Once users carry that data, you can use the Companies view and the MRR/LTV columns on posts to prioritize what your highest-value customers want.
In HubSpot, create a Private App (Settings → Integrations → Private Apps → Create a private app)
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 |
Fills customer_company_name from the associated Company object when the contact has no freeform company value. Falls back to the company's domain if the name field is empty (same behavior HubSpot itself shows on the contact card) |
crm.objects.deals.read |
Fills MRR, ARR, deal count and total deal amount (only when "Sync deals" is turned on) |
Copy the access token (starts with pat-na1-...)
In ProductLift, go to Settings > Integrations, expand the HubSpot card
Paste the token and click Test connection. A green check means HubSpot accepted the token.
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.
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:
customer_company_name from the contact's HubSpot company property. If empty, falls back to the associated Company's name, then its domain (matches how HubSpot displays the company on a contact)customer_mrr / customer_ltv if you map them in the HubSpot cardcustomer_plan_type from the lifecycle stage by defaultintegration_links so re-syncs are idempotentcustomer_mrr range to surface what enterprise customers are asking forSyncs are manual only, on demand. There is no scheduled job that pulls HubSpot in the background. You sync when you want a refresh:
customer_* fields on existing users. Safe to run as often as you like; it is idempotent.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.
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.
Click Disable in the HubSpot card. The encrypted token is removed and no further syncs run. Existing customer_* fields on users remain. Re-enable later by pasting the token again.