# HubSpot

> Learn how to track lead conversion events with HubSpot and Dub

import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";

<Tip>
  This feature is only available on [Advanced plans and
  above](https://dub.co/pricing).
</Tip>

Dub's [HubSpot integration](https://dub.co/integrations/hubspot) allows you to track conversion events directly from HubSpot.

This is useful for B2B SaaS companies that use HubSpot as their CRM and want to track meeting bookings and deal creation/closed-won events as lead and sale conversion events on Dub.

<ConversionTrackingPrerequisites />

Finally, install the [HubSpot Dub Integration](https://app.dub.co/integrations/hubspot) to your workspace.

<Frame>
  <img
    src="/images/conversions/hubspot/installed-hubspot-integration.png"
    alt="HubSpot Dub Integration"
  />
</Frame>

### Integration Setup

During the installation, Dub will create 3 properties to your contact object on HubSpot:

- **Dub Id** - Unique identifier that Dub uses to track clicks
- **Dub Link** - The short link that the contact clicked to reach your site
- **Dub Partner Email** - Email address of the partner associated with the short link

<Frame>
  <img
    src="/images/conversions/hubspot/hubspot-dub-properties.png"
    alt="HubSpot Contact Properties Created by Dub Integration"
  />
</Frame>

<Tip>
  If you can't see these properties in your HubSpot contact object after
  installation, something might've gone wrong with the integration setup. Please
  [contact us](https://dub.co/contact/support) for assistance.
</Tip>

### Set Your Closed Won Deal Stage ID

You can define which HubSpot deal stage should be treated as **Closed Won** for automatic sales tracking in Dub.

If you've customized your pipeline (i.e. changed or added deal stages in HubSpot), enter the stage ID corresponding to your custom **Closed Won** stage in the [HubSpot Integration Settings](https://app.dub.co/settings/integrations/hubspot).

Once set, any HubSpot deal marked as **Closed Won** will automatically be tracked in Dub as a sale conversion event, including its deal value.

<Frame>
  <img
    src="/images/conversions/hubspot/hubspot-custom-deal-stage-id.png"
    alt="Add custom deal stage ID to HubSpot Integration Settings"
  />
</Frame>

## Option 1: Using HubSpot Forms

[HubSpot Forms](https://www.hubspot.com/products/marketing/forms) help you capture lead information and track conversions. By integrating with Dub, you can attribute each form submission back to the specific Dub link that drove the conversion.

To make attribution work, you need to capture the `dub_id` cookie in your HubSpot form. This ensures each lead is tied back to the exact Dub link they came from.

Here's how you can set it up:

<Steps>
  <Step title="Add a hidden field to your form">
    In the HubSpot form builder, add a hidden field and map it to the **Dub Id** contact property.
    
    This makes sure the value captured by your script is stored on the contact record. Without mapping to a property, HubSpot won’t persist the `dub_id` value.

    <Frame>
      <img
        src="/images/conversions/hubspot/hubspot-forms-setup.png"
        alt="Segment Dub (Actions) Mapping"
        width="1440"
        height="1024"
      />
    </Frame>

  </Step>

  <Step title="Add the script to your site">
    Finally, add the following snippet to your site. The script reads the `dub_id` cookie and, if found, automatically fills the hidden Dub Id form field with its value.

    <CodeGroup>
    ```html HTML expandable
    <script src="https://js.hsforms.net/forms/embed/47839131.js" defer></script>

    <div
      class="hs-form-frame"
      data-region="na1"
      data-form-id="YOUR_FORM_ID"
      data-portal-id="YOUR_PORTAL_ID"
    ></div>

    <script>
      // A helper function to get the value of a cookie
      function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);

        if (parts.length === 2) {
          return parts.pop().split(";").shift();
        }

        return null;
      }

      // Listen for the form ready event
      window.addEventListener("hs-form-event:on-ready", (event) => {
        const clickId = getCookie("dub_id");

        if (!clickId) {
          console.debug("clickId not found. Skipping lead tracking.");
          return;
        }

        // Populate the hidden field with the dub_id
        HubSpotFormsV4.getForms()[0].setFieldValue("0-1/dub_id", clickId);
      });
    </script>
    ```

    </CodeGroup>

    When a prospect submits the form, the `dub_id` is captured and passed to HubSpot, ensuring the lead is attributed back to the original Dub link.

  </Step>
</Steps>

## Option 2: Using HubSpot Meeting Scheduler

[HubSpot's Meeting Scheduler](https://www.hubspot.com/products/sales/schedule-meeting) lets prospects book time directly with you or your team.

Since HubSpot doesn't let you add a hidden field to the scheduling form, you should handle initial lead tracking through [deferred lead tracking](/docs/conversions/leads/deferred) on the client side.

<Steps>
  <Step title="Generate your publishable key">
    Before you can track conversions on the client-side, you need to generate a publishable key from your Dub workspace.
    
    To do that, navigate to your [workspace's Tracking settings page](https://app.dub.co/settings/tracking) and generate a new publishable key under the **Publishable Key** section.

    <Frame>
      <img
        src="/images/conversions/publishable-key.png"
        alt="Enabling conversion tracking for a workspace"
      />
    </Frame>

  </Step>

  <Step title="Allowlist your site's domain">
      Then, you'll need to allowlist your site's domain to allow the client-side conversion events to be ingested by Dub.

      To do that, navigate to your [workspace's Tracking settings page](https://app.dub.co/settings/tracking) and add your site's domain to the **Allowed Hostnames** list.

      This provides an additional layer of security by ensuring only authorized domains can track conversions using your publishable key.

      <Frame>
        <img
          src="/images/conversions/allowed-hostnames.png"
          alt="Enabling conversion tracking for a workspace"
        />
      </Frame>

      You can group your hostnames when adding them to the allow list:

      - `example.com`: Tracks traffic **only** from `example.com`.
      - `*.example.com`: Tracks traffic from **all subdomains** of `example.com`, but **not** from `example.com` itself.

      <Tip>
        When testing things out locally, you can add `localhost` to the **Allowed
        Hostnames** list temporarily. This will allow local events to be ingested by
        Dub. Don't forget to remove it once you're ready to go live!
      </Tip>

  </Step>

  <Step title="Add the tracking code to your site">
    Use the following code to track lead conversions when meetings are booked through the HubSpot scheduler.

    The script listens for booking events from HubSpot, extracts the customer's details (name and email), and then calls `dubAnalytics.trackLead()` with [deferred lead tracking](/docs/conversions/leads/deferred).

    This way, the lead is only tracked after the meeting is confirmed, ensuring accurate attribution.

    <CodeGroup>
    ```html HTML expandable

    <!-- Load Dub analytics script -->
    <script>
      !(function(w, n) {
        w[n] = w[n] || function() { (w[n].q = w[n].q || []).push(arguments); };
        ["trackClick","trackLead","trackSale"].forEach(t => w[n][t] = (...a) => w[n](t, ...a));
        var s = document.createElement("script");
        s.defer = true;
        s.src = "https://www.dubcdn.com/analytics/script.conversion-tracking.js";
        s.setAttribute("data-publishable-key", "YOUR_PUBLISHABLE_KEY");
        s.setAttribute("data-domains", '{"refer":"YOUR_SHORT_DOMAIN"}');
        document.head.appendChild(s);
      })(window, "dubAnalytics");
    </script>

    <div
      class="meetings-iframe-container"
      data-src="https://meetings.hubspot.com/YOUR_USERNAME?embed=true"
    ></div>

    <script
      type="text/javascript"
      src="https://static.hsappstatic.net/MeetingsEmbed/ex/MeetingsEmbedCode.js"
    ></script>

    <script>
      // Listen for the message event
      window.addEventListener("message", function (event) {
        // Check if the message is from the scheduling widget
        if (event.origin === "https://meetings.hubspot.com") {
          // Get the data from the event
          const data = event.data;

          if (data.meetingBookSucceeded) {
            // Get the scheduled contact
            const contact =
              data.meetingsPayload.bookingResponse.postResponse.contact;

            if (!contact) {
              console.debug("contact not found. Skipping lead tracking.");
              return;
            }

            // Track the lead with the scheduled contact
            const customerName = [contact.firstName, contact.lastName]
              .filter(Boolean)
              .join(" ");

            dubAnalytics.trackLead({
              mode: "deferred",
              eventName: "Meeting scheduled",
              customerExternalId: contact.email,
              customerName: customerName,
              customerEmail: contact.email,
            });
          }
        }
      });
    </script>
    ```
    </CodeGroup>

  </Step>
</Steps>

## Tracking conversion events

After a prospect attends your demo call, you'll typically create a deal in HubSpot to track the sales opportunity.

Dub's HubSpot integration automatically sets up webhooks to track both deal creation and deal closure events, providing complete visibility into your sales funnel.

### When a deal is created (lead event)

When you create a deal in HubSpot for a contact who came through your Dub links, the integration automatically tracks this as a [lead event](/docs/quickstart/server#tracking-lead-events) in Dub.

### When a deal is closed (sale event)

When a deal moves to a **Closed Won** status in HubSpot, the integration automatically [tracks a sale event](/docs/quickstart/server#tracking-sale-events) in Dub using the deal amount as the sale value.

If a deal is not being tracked as a sale in Dub, make sure you've set the correct Closed Won Deal Stage ID in your [HubSpot Integration Settings](#set-your-closed-won-deal-stage-id).

## Example apps

<CardGroup cols={2}>
  <Card
    title="Dub + HubSpot Demo App"
    icon="github"
    href="https://github.com/dubinc/examples/tree/main/conversions/hubspot"
    color="#333333"
  >
    See the full example on GitHub.
  </Card>
</CardGroup>
