A bidirectional integration that connects your support team's HubSpot tickets to your engineering team's GitHub workflow — in real time, without leaving either tool.
The problem with most HubSpot–GitHub workflows is that they're not really workflows at all — they're manual copy-paste routines. Someone creates a GitHub issue, someone else pastes the link into a HubSpot note, and then both sides pray the other one stays updated.
This recipe builds a proper bridge: a React UI card embedded in HubSpot ticket records, backed by a GCP Cloud Functions API, with GitHub webhooks pushing activity back in real time. Support reps get GitHub visibility without leaving HubSpot. Engineers get ticket context baked into their issues automatically.
It's more involved than a simple API wrapper — three separate systems to wire together, token encryption, webhook verification, bidirectional sync. But the result is a genuinely useful internal tool, not a demo.
| Difficulty | Advanced |
| Prep Time | ~1 hour (three separate service setups) |
| Cook Time | ~2 hours (backend deploy + HubSpot deploy) |
| Serves | Support teams, success teams, and the engineers they hand off to |
| Allergens | Requires a GCP billing account (even on free tier), GitHub App creation rights, and HubSpot Enterprise tier |
Accounts & Access
gcloud)npm install -g @hubspot/cli)From the pantry (provided in this repo)
This recipe has more prep than most. Get all three services set up before you touch the stove.
1. Create the GitHub App
In GitHub → Settings → Developer Settings → GitHub Apps, create a new app named GitSpot. You'll need:
Also create a GitHub OAuth App (separate from the GitHub App) to enable per-user connections — users authorise their own GitHub accounts to access personal repositories and projects.
2. Set Up GCP
gcloud projects create gitspot-prod --name="GitSpot" gcloud config set project gitspot-prod gcloud services enable cloudfunctions.googleapis.com firestore.googleapis.com \ secretmanager.googleapis.com cloudkms.googleapis.com cloudbuild.googleapis.com gcloud firestore databases create --location=us-central1
Then create your six secrets in Secret Manager:
gcloud secrets create hubspot-github-app-id --replication-policy="automatic" gcloud secrets create hubspot-github-private-key --replication-policy="automatic" gcloud secrets create hubspot-github-webhook-secret --replication-policy="automatic" gcloud secrets create hubspot-github-hubspot-token --replication-policy="automatic" gcloud secrets create hubspot-github-oauth-client-id --replication-policy="automatic" gcloud secrets create hubspot-github-oauth-client-secret --replication-policy="automatic"
Add your values to each secret — the GitHub App ID, private key (the .pem contents), webhook secret, HubSpot private app token, and OAuth client credentials.
3. Set your Cloud Functions URL in the source
Before deploying the HubSpot extension, open github-card.jsx and TemplateSettings.jsx and replace the API_BASE_URL placeholder with your actual Cloud Functions URL:
https://us-central1-YOUR_GCP_PROJECT_ID.cloudfunctions.net/git-spot-api
Also update app-hsmeta.json with the same base URL in the permittedUrls.fetch array.
Deploy the Cloud Functions API that sits between HubSpot and GitHub.
cd cloud npm install npm run deploy # Deploys git-spot-api (main API) npm run deploy:webhooks # Deploys gitspot-webhooks (GitHub webhook handler)
When the deploy completes, note your Cloud Functions URL. Go back to your GitHub App settings and set the Webhook URL:
https://us-central1-YOUR_GCP_PROJECT_ID.cloudfunctions.net/git-spot-api/api/webhooks/github
Chef's note: KMS encryption is initialised automatically on first token save — no manual setup required. The key ring (
gitspot-keys) and encryption key are created on demand.
Deploy the React UI card to your HubSpot account.
cd hubspot hs auth hs project upload
After upload, go to your HubSpot account and initialise the custom behavioral events:
GitSpot Settings page → "Initialize Custom Events"
This creates HubSpot custom event definitions for all GitHub activity types — issue created, issue linked, comment synced, etc. — making them available in HubSpot workflows and reports.
Add the card to ticket records:
Settings → Objects → Tickets → Record Customization → Default view → + → Card library → GitSpot
In your GitHub App settings, click Install App and select the organisation or repositories you want GitSpot to have access to. Team members can additionally connect their personal GitHub accounts from within the GitSpot settings page to access personal projects.
TICKET-{id} (configurable) appear automatically in the ticket's card via webhook — no action required from the engineerThe most useful automation this unlocks in HubSpot:
New support ticket created → GitSpot workflow action checks if a linked issue exists → If yes, branch on issue state → Closed issues trigger ticket resolution → Open issues trigger escalation or SLA timer
This turns GitHub issue state into a live signal inside your HubSpot automation — without anyone manually updating anything.
This project connects systems that all version independently — HubSpot UI Extensions, the GitHub API, and GCP Cloud Functions runtimes each have their own release cadences. If something stops working after an update to any of these, check the respective changelogs before assuming the integration is broken. The most likely friction points are HubSpot platform version changes (see the repo README for current status) and GitHub App permission requirements, which GitHub occasionally tightens.
Complete source code, setup guides, and architecture notes are in the GitHub repository:
Part of a professional portfolio — view the project brief