Connect HubSpot to Snowflake
Land HubSpot contacts, companies, deals, and engagement events in Snowflake on the next poll of a change, model them alongside the rest of your data, and write scores and segments back to HubSpot, with every load recorded as an ordered run you can replay.
Why teams connect HubSpot and Snowflake
HubSpot is where marketing and sales work. Snowflake is where the company answers questions about revenue. Getting HubSpot data into the warehouse usually means a managed pipeline you cannot see into, a nightly job that is hours stale, or an export someone runs by hand.
- Contacts, companies, deals, and engagements land in Snowflake on the next poll, not on a nightly cycle
- Every load is an ordered run log, so a row that looks wrong in a dashboard can be traced to the exact sync that wrote it
- Deleted and merged HubSpot records are handled as soft deletes, so history is not silently rewritten
- Model output, a fit score or a churn segment, is written back to HubSpot on a schedule, so the same numbers show up for reps
Worked example
The load flow most teams turn on first.
HubSpot contacts and deals into RAW.HUBSPOT.*, within a polling interval
Change-driven, with a scheduled full reconcile so nothing drifts.
- Trigger: HubSpot
Contact property changedandDeal property changedtriggers, polled on the schedule you set. - Fetch full record: the change carries the changed property only, so a
Get recordcall pulls the full contact or deal. - Shape: flatten the HubSpot
propertiesobject to typed columns using the map below, keeping the raw JSON in a_rawcolumn. - Merge:
MERGE INTO RAW.HUBSPOT.CONTACT t USING :batch s ON t.HS_OBJECT_ID = s.HS_OBJECT_ID. - Associations: upsert contact-to-company and contact-to-deal links into a
CONTACT_ASSOCIATIONtable. - Nightly reconcile: a scheduled flow pages the full HubSpot list and merges it, catching anything a poll missed.
Field mapping
The starting map for the HubSpot contact to RAW.HUBSPOT.CONTACT step.
| HubSpot property | Snowflake column | Notes |
|---|---|---|
hs_object_id | HS_OBJECT_ID NUMBER | Match key for the merge. |
email | EMAIL VARCHAR | Lowercased on write. Not unique in HubSpot, do not use as a key. |
lifecyclestage | LIFECYCLE_STAGE VARCHAR | Enum value, kept as text. |
hs_lead_status | LEAD_STATUS VARCHAR | |
createdate | CREATED_AT TIMESTAMP_NTZ | HubSpot sends epoch milliseconds, cast on write. |
lastmodifieddate | UPDATED_AT TIMESTAMP_NTZ | Also used as the watermark for reconcile. |
hubspot_owner_id | OWNER_ID NUMBER | Join to an OWNER dimension, not resolved inline. |
properties (full object) | _RAW VARIANT | Keep the whole payload so a new property does not need a backfill. |
| (derived) | IS_DELETED BOOLEAN | Set by the delete and merge flow, default FALSE. |
What syncs, each direction
- Core objects. Contacts, companies, deals, tickets, and their property history land as typed tables plus a raw VARIANT column. (HubSpot to Snowflake)
- Engagement events. Email opens, clicks, form submissions, meetings, and calls stream into an events table for attribution modeling. (HubSpot to Snowflake)
- Scores and segments. A model table of fit scores, churn risk, or account tier is written back to HubSpot custom properties on a schedule. (Snowflake to HubSpot)
- Suppression and enrichment. Do-not-contact lists and firmographic fields computed in the warehouse update the matching HubSpot records. (Snowflake to HubSpot)
Governance and audit
The same controls apply to this sync as to every other Neblex workload.
- Ordered run log. Every load is an event log with the batch, the merge statement, and row counts. Replay a run without re-fetching from HubSpot.
- Approval on write-back. Reverse-ETL flows that change HubSpot data can pause for review before the first run of a changed mapping.
- Scoped access. HubSpot uses a private app token limited to the needed scopes. Snowflake uses a role with grants on the target schema only.
- Environments. Build against a HubSpot test account and a Snowflake scratch schema, then promote the same flow to production.
Frequently asked questions
How fresh is the data in Snowflake?
Change-driven loads land within one polling interval of the HubSpot change. A nightly reconcile catches anything a poll missed.
Do we get history, or just the current state?
Both. The current-state tables are merged in place, and property-change events are appended to a history table so you can reconstruct a record at a point in time.
What happens when a HubSpot contact is merged or deleted?
The delete and merge flow marks the losing record IS_DELETED = TRUE and records the surviving ID, rather than removing the row.
Can we write model output back to HubSpot?
Yes. A scheduled flow reads a model table in Snowflake and updates HubSpot custom properties, with an optional approval step on the first run.
Is this different from HubSpot's own data-sync or a managed pipeline?
Managed pipelines are a fine choice if you only need tables in a warehouse on a schedule and never need to see inside a load. This is for teams that also want short intervals, a rear prompt latency, a readable run log, write-back, and the same governance as the rest of their integrations.
Connectors on this page
HubSpot
CRM
- Operations
- 336
- Typed outputs
- 81.5%
- Change triggers
- 48 (poll)
- Authentication
- Bearer
Snowflake
Snowflake
- Operations
- 7
- Typed outputs
- 85.7%
- Change triggers
- Poll or inbound webhook
- Authentication
- ConnectionString
Bring one real integration
We will build it with you against your own systems, with the run log open.