HubSpot — Channel Overview
Researched: May 2026
Why This Channel
HubSpot is the most widely used CRM + marketing automation platform in the SMB and mid-market space globally (200,000+ customers). Unlike Zoho CRM which serves Indian SMBs, HubSpot targets international clients and SaaS companies — a different slice of the Leadmetrics customer base.
Connecting HubSpot closes the content-to-revenue loop: Leadmetrics generates content → content drives traffic → traffic becomes HubSpot contacts → contacts become deals → deal revenue is visible in Leadmetrics. This is the attribution story that makes content marketing defensible in a CFO review.
HubSpot also exposes email sequences, form submissions, and page visit data — all of which can inform the content agents about what language converts.
Auth Mechanism
OAuth 2.0 (standard authorization code flow with token refresh).
- Auth URL:
https://app.hubspot.com/oauth/authorize - Token URL:
https://api.hubapi.com/oauth/v1/token - Scopes:
crm.objects.contacts.read crm.objects.contacts.write crm.objects.deals.read forms - Token refresh: access token expires in 6 hours; refresh token long-lived
No sub-channel selection needed — one HubSpot portal (account) per connection. The portal ID is stored in subChannelInfo.id.
What It Enables
| Capability | Detail |
|---|---|
| Contact import | Sync HubSpot contacts into Leadmetrics Lead + LeadContact tables |
| Deal pipeline | Pull deal stages + amounts to measure content → revenue attribution |
| Form submissions | Which landing pages generated form fills (closes the landing page ROI loop) |
| Email performance | Open rates, click rates for HubSpot sequences (Phase 2) |
| Content attribution | Tag which blog post, landing page, or social post drove each contact |
| Insight worker | Lead volume trend; top content-to-lead sources; deal conversion rate |
Workers Needed
| Worker | Queue | Trigger |
|---|---|---|
hubspot-sync.worker.ts (new) | agent__hubspot-sync | On channel connect + nightly cron 0 1 * * * |
hubspot-insights.worker.ts (new) | agent__hubspot-insights | Weekly |
Insight Worker Output (ChannelInsight)
- New contacts this month vs last month
- Top 3 traffic sources (which content types drive HubSpot contacts)
- Deal pipeline value attributed to Leadmetrics content
- Form submissions per landing page (last 30 days)
- Average lead-to-customer conversion time
- Suggested: content topics correlated with highest-value deals
Channel Detail Page — HubSpotChannelDetail.tsx
Tabs:
- Overview — portal name, total contacts, deals this month
- Attribution — table of Leadmetrics content → contacts generated
- Deals — pipeline stage distribution; value by content source
- Insights — AI-generated attribution summary
- Suggestions — action items from insight worker
Implementation Plan
Phase 1 — Connect + Contact Sync
-
Create
packages/providers/hubspot/src/index.ts:getAuthUrl(callbackUrl, channelId)— auth URL + stateexchangeCode(code, callbackUrl)— returns tokens +hubId(portal ID)refreshAccessToken(refreshToken)— returns new access tokengetContacts(accessToken, after?)—GET /crm/v3/objects/contactspaginatedgetDeals(accessToken, after?)—GET /crm/v3/objects/dealswith stage + amountgetFormSubmissions(accessToken, formId)—GET /form-integrations/v1/submissions/forms/:idverify()—GET /oauth/v1/access-tokens/:token
-
Add OAuth routes to
apps/api/src/routers/channel-connect.ts:GET /hubspot/connect→ return auth URLGET /hubspot/callback→ exchange code, extracthub_idfrom token, store + close popup
-
Create
packages/agents/src/workers/hubspot-sync.worker.ts:- Fetch contacts (incremental via
lastmodifieddatefilter) - Upsert into
Lead+LeadContact; setsource: "hubspot"+hubspotContactId - Fetch deals; store attributed deal value per contact
- Fetch contacts (incremental via
-
Add seed entry to
packages/db/prisma/seed.ts -
Create
HubSpotChannelDetail.tsx
Phase 2 — Attribution + Deal Tracking
-
Attribution logic: when a visitor submits a HubSpot form embedded on a Leadmetrics landing page, pass
utm_content=leadmetrics-{activityId}→ captured in HubSpot → synced back to attribute the deal to the activity -
Add
hubspotContactId+sourcefields toLeadmodel if not already present -
Dashboard widget: “Content Attribution” card on the main dashboard showing leads + deals generated by Leadmetrics content this month
Phase 3 — Email Performance
- Pull HubSpot email campaign metrics (open rate, click rate) for sequences tied to leads generated by Leadmetrics content
Seed Entry
// packages/db/prisma/seed.ts — CHANNEL_CATALOGUE
{
type: "HubSpot",
name: "HubSpot",
iconKey: "hubspot",
description: "Sync contacts and deals from HubSpot to measure content-to-revenue attribution.",
authenticationType: "oauth2",
requiresUrl: false,
isActive: true,
categories: ["crm"],
},