# Integrate HubSpot forms

Track form submissions, enrich user profiles, test, and personalize forms.

HubSpot forms are a common way to capture leads and contact information. By connecting them to Croct, you can track form submissions, enrich user profiles with the submitted data, test, and personalize which form is shown to each visitor.

> **Which form type do you have?**
>
> This tutorial covers both [legacy](https://developers.hubspot.com/docs/cms/start-building/features/forms/legacy-forms) and [new](https://developers.hubspot.com/docs/cms/start-building/building-blocks/modules/forms) Hubspot forms.

## Prerequisites

Before you start, make sure you have:

- A [Croct account](https://app.croct.com/signup) with a workspace and application set up.
- The [Croct SDK](/reference/sdk) installed on the page where your HubSpot form is embedded.
- A [HubSpot account](https://www.hubspot.com) with at least one form set up.

## Track form submissions

Tracking a form submission as a [Goal completed](/reference/event/types/engagement/goal-completed) event lets you measure conversion rates in your [dashboards](/reference/analytics) and use them as goals in [experiments](/explanation/experiment#choose-the-goal).

You can listen for submissions using a [global event](https://developers.hubspot.com/docs/api-reference/latest/marketing/forms/global-form-events) or a [callback](https://developers.hubspot.com/docs/cms/start-building/features/forms/legacy-forms#embed-code-callbacks) (legacy forms only).

**Global event**

```js
// Register the listener before the HubSpot form script loads
// to avoid missing early submissions.
window.addEventListener(
  'hs-form-event:on-submission:success',
  function() {
    croct.track('goalCompleted', {
      goalId: 'form-submission',
    });
  },
);
```

**Callback**

```js
hbspt.forms.create({
  portalId: 'YOUR_HUBSPOT_ACCOUNT_ID',
  formId: 'YOUR_HUBSPOT_FORM_ID',
  onFormSubmitted: function() {
    croct.track('goalCompleted', {
      goalId: 'form-submission',
    });
  },
});
```

For details on additional properties like `currency` and `value`, see the [goal completed event reference](/reference/event/types/engagement/goal-completed).

## Enrich user profiles

You can send form field values to Croct [user profiles](/explanation/user-profiles/introduction) to use them for audience segmentation and personalization.

**New forms**

```js
// Register the listener before the HubSpot form script loads
// to avoid missing early submissions.
window.addEventListener(
  'hs-form-event:on-submission:success',
  async function(event) {
    var fieldValues = await HubSpotFormsV4
      .getFormFromEvent(event)
      .getFormFieldValues();

    var values = Object.fromEntries(
      fieldValues.map(item => [item.name, item.value])
    );

    croct.user.edit()
      .set('firstName', values['0-1/firstname'])
      .set('lastName', values['0-1/lastname'])
      .set('email', values['0-1/email'])
      .set('company', values['0-1/company'])
      .save();
  },
);
```

**Legacy forms**

```js
hbspt.forms.create({
  portalId: 'YOUR_HUBSPOT_ACCOUNT_ID',
  formId: 'YOUR_HUBSPOT_FORM_ID',
  onFormSubmitted: function($form, data) {
    var values = data.submissionValues;

    croct.user.edit()
      .set('firstName', values.firstname)
      .set('lastName', values.lastname)
      .set('email', values.email)
      .set('company', values.company)
      .save();
  },
});
```

You can customize the patch payload to track data based on your form fields. Check the [user reference](/reference/user/overview) to see available profile attributes.

## Dynamically render the form

HubSpot allows you to create as many forms as you want, and each form has its own ID. To [run an AB test](/explanation/experiment) or [build a personalized experience](/explanation/experience/introduction) and show different forms to different users, you only need to define which form to render.

With Croct, you do this by storing the form ID in a [slot](/explanation/slot). Instead of hardcoding the form ID in your page, you fetch it from the slot and render whichever form ID it returns. From there, an AB test or personalized experience can change the form ID per user, and your page renders the matching form automatically.

### Set up the slot

1. Open the [components page](https://app.croct.com/redirect/organizations/-organization-/workspaces/-workspace-/components) and create a component with the ID `hubspot-form` and the following attribute:

   | Attribute | Type       | Required |
   | --------- | ---------- | -------- |
   | `formId`  | Plain text | Yes      |

2. Open the [slots page](https://app.croct.com/redirect/organizations/-organization-/workspaces/-workspace-/slots) and create a slot with the ID `hubspot-form`, associated with the `hubspot-form` component.

   Set the [default content](/explanation/content/slot-default-content) to the form ID you are currently using.

3. Add the slot to your project:

   ```sh
   croct add slot hubspot-form
   ```

### Render the form dynamically

Fetch the slot content and use the form ID to embed the correct form:

**New forms**

```html
<div id="hubspot-form" data-portal-id="YOUR_HUBSPOT_ACCOUNT_ID" class='hs-form-frame'></div>
<script>
  var {content} = await croct.fetch('hubspot-form');

  document.getElementById('hubspot-form')
    .setAttribute('data-form-id', content.formId);

  var script = document.createElement('script');
  script.src = 'https://js.hsforms.net/forms/embed/YOUR_HUBSPOT_ACCOUNT_ID.js';
  document.body.appendChild(script);
</script>
```

**Legacy forms**

```html
<script charset="utf-8" type="text/javascript" src="//js.hsforms.net/forms/embed/v2.js"></script>
<script>
  var {content} = await croct.fetch('hubspot-form');

  hbspt.forms.create({
    portalId: 'YOUR_HUBSPOT_ACCOUNT_ID',
    formId: content.formId,
  });
</script>
```

Now that the form ID comes from a slot, you can create an [AB test](/immersion/tutorials/get-started/ab-testing) or a [Personalized experience](/immersion/tutorials/get-started/slot-personalization) using the `hubspot-form` slot. Each variant or experience can display a different form.

### Example

If you plan to track submissions, enrich the user profile, and test or personalize the form, this is how the final code might look like:

**New forms**

```html
<script>
  window.addEventListener(
    'hs-form-event:on-submission:success',
    async function(event) {
      croct.track('goalCompleted', {
        goalId: 'form-submission',
      });

      var fieldValues = await HubSpotFormsV4
        .getFormFromEvent(event)
        .getFormFieldValues();

      var values = Object.fromEntries(
        fieldValues.map(item => [item.name, item.value])
      );

      croct.user.edit()
        .set('firstName', values['0-1/firstname'])
        .set('lastName', values['0-1/lastname'])
        .set('email', values['0-1/email'])
        .set('company', values['0-1/company'])
        .save();
    }
  );
</script>
<div id="hubspot-form" data-portal-id="YOUR_HUBSPOT_ACCOUNT_ID" class='hs-form-frame'></div>
<script>
  var {content} = await croct.fetch('hubspot-form');

  document.getElementById('hubspot-form')
    .setAttribute('data-form-id', content.formId);

  var script = document.createElement('script');
  script.src = 'https://js.hsforms.net/forms/embed/YOUR_HUBSPOT_ACCOUNT_ID.js';
  document.body.appendChild(script);
</script>
```

**Legacy forms**

```html
<script charset="utf-8" type="text/javascript" src="//js.hsforms.net/forms/embed/v2.js"></script>
<script>
  var {content} = await croct.fetch('hubspot-form');

  hbspt.forms.create({
    portalId: 'YOUR_HUBSPOT_ACCOUNT_ID',
    formId: content.formId,
    onFormSubmitted: function($form, data) {
      croct.track('goalCompleted', {
        goalId: 'form-submission',
      });

      var values = data.submissionValues;

      croct.user.edit()
        .set('firstName', values.firstname)
        .set('lastName', values.lastname)
        .set('email', values.email)
        .set('company', values.company)
        .save();
    },
  });
</script>
```

## Explore

- [Slots](/explanation/slot): Learn how slots help you manage and personalize content.
- [Experiences](/explanation/experience/introduction): Discover what an experience is and how it works.
