Author: By Raj

Part of our Apps Script API Integrations guides. Need this built for your team? Hire a Google Apps Script developer.

Estimated reading time: 10 minutes

Sync HubSpot CRM with Google Sheets Using Apps Script

HubSpot CRM data in Google Sheets powers forecasting standups and ad-hoc analysis. Apps Script pulls contacts, deals, and companies with OAuth2 or private app tokens depending on your HubSpot tier.

Pagination uses after cursor parameters; properties query param lists fields to avoid giant payloads. Schedule syncs off-peak to respect both HubSpot and UrlFetch quotas.

See /blog/apps-script-oauth2-guide for token refresh and /blog/apps-script-rest-api-guide for generic REST patterns.

OAuth2 private app or public app

Private apps expose a static token, fast for internal sheets. Public apps need refresh tokens stored in Script Properties with expiry timestamps.

Use the community OAuth2 library or manual UrlFetchApp token exchange documented in oauth guide.

Deals pipeline sync

GET /crm/v3/objects/deals?properties=dealname,amount,dealstage&limit=100. Map dealstage IDs to labels via a HubSpotStages sheet refreshed weekly.

Upsert by hs_object_id column to avoid duplicate deal rows on reruns.

Contacts and associations

Associations API links contacts to companies. Batch association fetches only for rows changed since last modified date filter if API supports search.

Use HubSpot search endpoint for complex filters instead of downloading entire CRM.

Rate limits and 429 handling

On 429, Utilities.sleep(2000 * attempt) and retry up to 3 times. Log X-HubSpot-RateLimit headers when present.

If sync still fails, fall back to yesterday's snapshot tab labeled Stale Data.

Example code

function getHubSpotDeals(token) {
  const url = 'https://api.hubapi.com/crm/v3/objects/deals?limit=100&properties=dealname,amount,dealstage';
  const res = UrlFetchApp.fetch(url, {
    headers: { Authorization: 'Bearer ' + token },
    muteHttpExceptions: true,
  });
  const body = JSON.parse(res.getContentText());
  return body.results || [];
}
ApproachBest forTradeoff
Apps Script nativeGoogle Workspace-centric workflows6-min limit, quotas
Zapier / MakeNo-code, many connectorsPer-task cost, vendor lock-in
Python + CloudHeavy data / MLHosting cost, separate auth
API integration servicesProduction custom logicBuild cost, you own code

FAQ

Private app token vs OAuth?

Private app tokens suit single-tenant internal sheets. OAuth suits multi-customer products or rotating users.

Can I write back to HubSpot from Sheets?

PATCH /crm/v3/objects/deals/{id} with updated properties when sales edits amount in Sheet, validate with LockService.

How often should CRM sync run?

Hourly is typical for ops dashboards; real-time needs webhooks to doPost, not polling.

What about custom properties?

Add property internal names to the properties query param list, discover names in HubSpot settings.

Does HubSpot replace Sheets reporting?

Sheets wins for flexible pivots; HubSpot wins for attribution. Sync bridges both without CSV exports.

Need this done for you? I handle this as part of my consulting work, fixed-price quote within 24 hours.

Book a call with Raj →

Get the full Sync HubSpot CRM with Google Sheets Using Apps Script script template

I'll email you a production-ready, commented version you can deploy in 10 minutes.

Need help with this? I handle this as part of my Apps Script API Integrations service.

Shopify, Stripe, Slack, HubSpot, webhooks, and REST API connections.

See how it works →