HubSpot CRM Setup Specification
Owner: CMO (Elena Vasquez) Related ticket: CAS-32 Last updated: 2026-04-07
Overview
CascadeGuard uses HubSpot Free CRM for lead capture and nurturing. Leads enter via the “Try Me” free scan flow: the user submits a Dockerfile, receives a blurred summary, then exchanges their email to see the full CVE report. At that point their email (plus scan metadata) is captured in HubSpot.
This document defines the contact property schema and the email drip sequence.
Contact Property Schema
These custom properties must be created in HubSpot before the POST /api/leads
engineering work (see CAS-32 subtask) can populate them.
Create via: HubSpot → Settings → Properties → Contact Properties → Create Property
| Property Name (Internal) | Label | Type | Description |
|---|---|---|---|
cg_scan_date | CascadeGuard Scan Date | DateTime | When the scan was submitted |
cg_scan_id | CascadeGuard Scan ID | Single-line text | UUID of the scan |
cg_risk_level | Scan Risk Level | Dropdown | critical, high, medium, low |
cg_vuln_critical | Critical CVEs | Number | Count of critical-severity CVEs |
cg_vuln_high | High CVEs | Number | Count of high-severity CVEs |
cg_vuln_medium | Medium CVEs | Number | Count of medium-severity CVEs |
cg_vuln_total | Total CVEs | Number | Total CVE count from scan |
cg_fixable_count | Fixable CVEs | Number | CVEs with a fix available |
cg_exploit_known_count | Exploit Known (CISA KEV) | Number | CVEs with known exploits |
cg_packages_scanned | Packages Scanned | Number | Total packages in the scanned image |
cg_lead_source | Lead Source | Single-line text | Always try-me-scan for this flow |
Contact Lifecycle Stage
- Set to Lead on create
- Update to Marketing Qualified Lead if
cg_risk_leveliscriticalorhigh(these contacts have the highest pain and are closest to a product fit conversation)
Email Drip Sequence
Three-email sequence, triggered when a contact is enrolled (form submission event).
Email 1 — Immediate: Your Scan Results
Timing: Immediately on enroll
Subject: Your CascadeGuard security scan — {{contact.cg_vuln_total}} CVEs found
Personalisation: Pull cg_risk_level, cg_vuln_critical, cg_vuln_high, cg_vuln_total
Body outline:
Hi,
You just scanned your Dockerfile with CascadeGuard — here’s what we found:
[RISK BADGE: {risk_level}]
- Critical: {cg_vuln_critical}
- High: {cg_vuln_high}
- Total CVEs: {cg_vuln_total}
- Fixable: {cg_fixable_count} ({pct}% of total)
These vulnerabilities are in your base image, not your application code. They’ll keep accumulating until the base image is rebuilt.
[CTA: View the full CascadeGuard quickstart →]
Goal: Acknowledge the scan, reinforce the problem, introduce the product.
Email 2 — Day 2: The Cascade Problem
Timing: 2 days after enroll
Subject: Why your base image is a ticking time bomb
Personalisation: Adjust intro based on cg_risk_level
Body outline:
The CVEs in your scan results aren’t random. They’re in the base image your Dockerfile inherits — and every week you don’t rebuild, more accumulate.
We wrote about exactly this: [Why Your Dockerfile Is a Supply Chain Risk →]
The fix isn’t exotic. It’s automation: detect the base image changed, rebuild, sign the new image, ship it through your GitOps pipeline. CascadeGuard does this automatically.
[CTA: See how the loop works →] (links to GitHub README/demo)
Goal: Educate, deliver value, link to flagship article, reinforce product.
Email 3 — Day 5: From Scan to Fix
Timing: 5 days after enroll
Subject: From scan to fix: closing the container security loop
Personalisation: If cg_fixable_count > 0, mention that specifically
Body outline:
The scan showed you the problem. Here’s the fix.
CascadeGuard is open source. It monitors your base images, detects when upstream updates land (or when CVE thresholds are crossed), and triggers a signed rebuild through your existing ArgoCD + Kargo pipeline.
Setup takes under 30 minutes.
[If fixable > 0: You had {cg_fixable_count} fixable CVEs — those are gone the next time your image rebuilds with the patched base.]
[CTA: Run the CascadeGuard quickstart →] (https://github.com/cascadeguard/cascadeguard)
Goal: Convert to product trial / GitHub star / install.
Workflow Configuration in HubSpot
- Trigger: Contact is enrolled in workflow
CascadeGuard Try-Me Flow - Enrolment criteria: Contact has property
cg_lead_source = try-me-scan - Sequence:
Immediate→ Send Email 1Wait 2 days→ Send Email 2Wait 3 more days→ Send Email 3Wait 7 more days→ Unenroll (no further automated contact)
- Re-enrolment: Allow re-enrolment if
cg_scan_dateis updated (user scans again)
Engineering Requirements
The POST /api/leads endpoint (Workers API) must:
- Accept:
{ email, scanId, riskLevel, vulnCritical, vulnHigh, vulnMedium, vulnTotal, fixableCount, exploitKnownCount, packagesScanned } - Create/update a HubSpot contact via Private App API (
HUBSPOT_PRIVATE_APP_TOKEN):POST https://api.hubapi.com/crm/v3/objects/contacts(upsert by email)- Set all
cg_*properties - Set
cg_lead_source = try-me-scan
- Enrol the contact in the drip workflow (by workflow ID — obtain after workflow is created in HubSpot)
- Return
200 OKon success; log but don’t surface HubSpot errors to the frontend
The frontend (try-me/index.tsx) must update handleEmailUnlock to:
- Call
POST /api/leadswith email + scan result summary data - Keep the existing HubSpot form submit as a fallback (or remove it once API is live)
See CAS-32 for the parent task.
Last updated: 2026-04-07 by Elena Vasquez (CMO)