HubSpot
Connect HubSpot for identity stitching and deal-stage conversions.
Connecting HubSpot does two things:
- Identity — links anonymous browser sessions to a CRM contact, so a journey that started weeks before signup still gets credited.
- Conversions — tells Simmer when a contact submits your conversion form (a lead) and when a deal moves to closed-won (revenue).
The connection is read-only: Simmer never writes contacts, deals, or properties back into HubSpot.
Connect via OAuth
In the dashboard, go to Settings → Integrations → Connect HubSpot. You'll be redirected to HubSpot to authorize, then back to Simmer. Simmer requests these scopes:
crm.objects.contacts.readcrm.objects.deals.read
Tokens are encrypted at rest and refreshed automatically.
Pick the conversion form
A conversion is the form submission that counts as a lead in your funnel — typically "Request a demo", "Talk to sales", or "Sign up". You select which HubSpot form represents this in Settings → HubSpot → Conversion form.
Only submissions of the selected form count toward the Website Lead Attribution metric. Other form submissions are still tracked, but as ordinary engagement events.
Hidden field
This is the most important part of the HubSpot setup. Without it, leads that arrived weeks before they filled in the form can't be linked back to their browsing history.
Simmer needs a way to write the visitor's anonymous browser ID onto the contact at the moment they submit the form. This is done with a hidden form field whose internal name is simmer_id.
Step 1 — Create the contact property
In HubSpot, go to Settings → Properties → Contact properties → Create property:
- Group: any (Contact information is fine)
- Label:
Simmer ID - Internal name:
simmer_id(must be exactly this — the pixel writes to this name) - Field type: Single-line text
Step 2 — Add the field to your conversion form
Open the form you selected as the conversion form, then:
- Drag the
Simmer IDproperty onto the form. - In the field options, set it to Hidden.
- Leave the default value blank.
- Save and republish the form.
That's it. The pixel detects the form, fills the field with the current anonymous_id on submit, and HubSpot stores it on the contact. Simmer's webhook reads the property and links the contact to the browser session.
What happens if the field isn't there
Simmer falls back to a synthetic identity (hubspot:contact:<id>). The contact still appears in the dashboard, but no browsing history is attached, so it shows up as a cookie-blocked lead (or "untracked"). Conversions from contacts without a simmer_id are counted but not credited to any channel.
What Simmer ingests
Simmer subscribes to four HubSpot webhook events:
| Event | What Simmer does |
|---|---|
| Contact created | Reads email and simmer_id, creates an identity link. |
| Contact email changed | Updates the identity link. |
| Deal stage changed to closed-won | Records a conversion with the deal amount as revenue. |
| Deal–contact association added | Links the deal to all associated contacts for multi-contact journeys. |
Webhooks are configured automatically when you connect — there's nothing to set up in HubSpot.
Troubleshooting
The form submits but simmer_id is empty on the contact.
The visitor probably hadn't granted cookie consent before submitting. The pixel only writes the anonymous ID when consent is granted. You can confirm by opening dev tools and checking that window.attrib exists and a simmer_id cookie is present before submitting.
A new contact shows up but isn't attributed.
Either no simmer_id was set (see above), or the contact was imported / created via API rather than your tracked website form. These show up under offline-origin leads in the dashboard.
Deals close but revenue doesn't appear in attribution.
Confirm the deal stage is mapped to closed-won in your HubSpot pipeline, and that at least one associated contact has a simmer_id value with tracked browsing history.
Token errors after a long period of inactivity. HubSpot access tokens expire every 30 minutes. Simmer refreshes automatically, but if the refresh token was revoked (e.g. the connecting user lost portal access), you'll need to reconnect via Settings → Integrations.