> ## Documentation Index
> Fetch the complete documentation index at: https://dub.co/llms.txt
> Use this file to discover all available pages before exploring further.

# HubSpot

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

> [!TIP]
>
> This feature is only available on [Business plans and
> above](https://dub.co/pricing).

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.

> [!NOTE]
>
> Want to test your setup before going live? Connect a HubSpot test account to
> your Dub [staging workspace](/docs/testing) so test leads and deals don't
> affect your production analytics.

## Prerequisites

First, you'll need to enable conversion tracking for your Dub links to be able to start tracking conversions:

> [!TIP]
>
> If you're using [Dub Partners](https://dub.co/partners), you can skip this
> step since partner links will have conversion tracking enabled by default.

> **Option 1: On a workspace-level**
>
> To enable conversion tracking for all future links in a workspace, you can do the following:
> To enable conversion tracking for all future links in a workspace, you can do the following:
>
> 1. Navigate to your [workspace's Tracking settings page](https://app.dub.co/settings/tracking).
> 2. Toggle the **Workspace-level Conversion Tracking** switch to enable conversion tracking for the workspace.
>
> ![Enabling conversion tracking for a workspace](https://mintlify.s3.us-west-1.amazonaws.com/dub/images/conversions/enable-conversion-tracking-workspace.png)
>
> This option will enable conversion tracking in the [Dub Link Builder](/help/article/dub-link-builder) for all future links.

> **Option 2: On a link-level**
>
> If you don't want to enable conversion tracking for all your links in a workspace, you can also opt to enable it on a link-level.
>
> To enable conversion tracking for a specific link, open the [Dub Link Builder](/help/article/dub-link-builder) for a link and toggle the **Conversion Tracking** switch.
>
> ![Enabling conversion tracking for a link](https://mintlify.s3.us-west-1.amazonaws.com/dub/images/conversions/enable-conversion-tracking.png)
>
> > [!TIP]
> >
> > You can also use the `C` keyboard shortcut when inside the link builder to
> > quickly enable conversion tracking for a given link.

> **Option 3: Via the API**
>
> Alternatively, you can also enable conversion tracking programmatically via the [Dub API](/docs/api-reference/introduction). All you need to do is pass `trackConversion: true` when creating or updating a link:
>
> ```javascript Node.js theme={null} theme={null} theme={null}
> const link = await dub.links.create({
>   url: "https://dub.co",
>   trackConversion: true,
> });
> ```
>
> ```python Python theme={null} theme={null} theme={null}
> link = d.links.create(url="https://dub.co", track_conversion=True)
> ```
>
> ```go Go theme={null} theme={null} theme={null}
> link, err := d.Links.Create(ctx, &dub.CreateLinkRequest{
>     URL: "https://dub.co",
>     TrackConversion: true,
> })
> ```
>
> ```ruby Ruby theme={null} theme={null} theme={null}
> s.links.create_many(
>   ::OpenApiSDK::Operations::CreateLinkRequest.new(
>     url: "https://dub.co",
>     track_conversion: true,
>   )
> )
> ```

Then, you'd want to install the Dub Analytics script to your website to track conversion events.

You can install the Dub Analytics script in several different ways:

> **[React](/docs/sdks/client-side/installation-guides/react)**

> **[Manual installation](/docs/sdks/client-side/installation-guides/manual)**

> **[Framer](/docs/sdks/client-side/installation-guides/framer)**

> **[Shopify](/docs/sdks/client-side/installation-guides/shopify)**

> **[WordPress](/docs/sdks/client-side/installation-guides/wordpress)**

> **[Webflow](/docs/sdks/client-side/installation-guides/webflow)**

> **[Google Tag Manager](/docs/sdks/client-side/installation-guides/google-tag-manager)**

> [!TIP]
>
> You can **verify the installation** with the following tests:
>
> 1. Open the browser console and type in `_dubAnalytics` – if the script is installed correctly, you should see the `_dubAnalytics` object in the console.
> 2. Add the `?dub_id=test` query parameter to your website URL and make sure that the `dub_id` cookie is being set in your browser.
>
> If both of these checks pass, the script is installed correctly. Otherwise, please make sure:
>
> * The analytics script was added to the `<head>` section of the page
> * If you're using a content delivery network (CDN), make sure to purge any cached content

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

![HubSpot Dub Integration](https://mintcdn.com/dub/4atD6Qmc1QmxgkWq/images/conversions/hubspot/installed-hubspot-integration.png?fit=max\&auto=format\&n=4atD6Qmc1QmxgkWq\&q=85\&s=2cbc22a672f1eaecb50d83439f84b722)

### 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

![HubSpot Contact Properties Created by Dub Integration](https://mintcdn.com/dub/Ge8VVgpapZ-fttZA/images/conversions/hubspot/hubspot-dub-properties.png?fit=max\&auto=format\&n=Ge8VVgpapZ-fttZA\&q=85\&s=30c4bc565485b348cd85e2e43c453215)

> [!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.

### Configure lead and sale tracking

In your [HubSpot Integration Settings](https://app.dub.co/settings/integrations/hubspot), choose which HubSpot event should be tracked as a lead in Dub:

| Lead trigger | When the lead is tracked |
| - | - |
| **Lifecycle Stage Reached** | The contact's lifecycle stage changes to the lifecycle stage you specify. |
| **New Deal Created** | A deal is created for the contact. |
| **Deal Stage Reached** | A deal associated with the contact moves into the deal stage you specify. |

Every option includes a **Closed Won Deal Stage ID** field. This is the deal stage that gets tracked as a sale in Dub. It defaults to HubSpot's standard `closedwon` stage, so you only need to change it if you've customized your pipeline stages.

#### Lifecycle Stage Reached

Enter the internal ID of the contact lifecycle stage that represents a qualified lead in the **Lead Lifecycle Stage ID** field (e.g. `salesqualifiedlead`). A lead is tracked in Dub when a contact reaches this lifecycle stage.

![HubSpot Integration Settings with Lifecycle Stage Reached selected](https://mintcdn.com/dub/Ge8VVgpapZ-fttZA/images/conversions/hubspot/hubspot-lifecycle-stage.png?fit=max\&auto=format\&n=Ge8VVgpapZ-fttZA\&q=85\&s=2f1032b93fd606ba3be02f8b590554b9)

#### New Deal Created

A lead is tracked in Dub as soon as a deal is created for the contact in HubSpot.

![HubSpot Integration Settings with New Deal Created selected](https://mintcdn.com/dub/Ge8VVgpapZ-fttZA/images/conversions/hubspot/hubspot-new-deal.png?fit=max\&auto=format\&n=Ge8VVgpapZ-fttZA\&q=85\&s=f9908e2656c51763a64eb5ca73d209cd)

#### Deal Stage Reached

Enter the internal ID of the deal stage that represents a qualified lead in the **Lead Deal Stage ID** field (e.g. `qualifiedtobuy`). A lead is tracked in Dub when a deal associated with the contact moves into this stage. This must be different from your **Closed Won Deal Stage ID**.

![HubSpot Integration Settings with Deal Stage Reached selected](https://mintcdn.com/dub/Ge8VVgpapZ-fttZA/images/conversions/hubspot/hubspot-deal-stage.png?fit=max\&auto=format\&n=Ge8VVgpapZ-fttZA\&q=85\&s=b945985d5491c12a7e5bd8ae1ed399ae)

## 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:

**1. Add a hidden field to your form**

In the HubSpot form builder, add a hidden field and map it to the **Dub Click 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.

![Segment Dub (Actions) Mapping](https://mintcdn.com/dub/4atD6Qmc1QmxgkWq/images/conversions/hubspot/hubspot-forms-setup.png?fit=max\&auto=format\&n=4atD6Qmc1QmxgkWq\&q=85\&s=a8a09cc8a620d07eb4c3ff22ce80a33f)

**2. 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.

```html HTML expandable theme={null}
<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>
```

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.

## 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.

**1. 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.

![Enabling conversion tracking for a workspace](https://mintcdn.com/dub/JTHh2SZNiQ9ZNd5J/images/conversions/publishable-key.png?fit=max\&auto=format\&n=JTHh2SZNiQ9ZNd5J\&q=85\&s=9d79bcd3e8e3ac51d6b86abe91ca0701)

**2. 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.

![Enabling conversion tracking for a workspace](https://mintcdn.com/dub/JTHh2SZNiQ9ZNd5J/images/conversions/allowed-hostnames.png?fit=max\&auto=format\&n=JTHh2SZNiQ9ZNd5J\&q=85\&s=6418540c30df8c7c06212e131a88a518)

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!

**3. 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.

```html HTML expandable theme={null}

<!-- 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>
```

## Option 3: Using the HubSpot API

If you create contacts from your own backend (e.g. when a user signs up for your app), you can use the [HubSpot Contacts API](https://developers.hubspot.com/docs/api-reference/latest/crm/objects/contacts/guide) to create the contact with the `dub_id` click ID attached.

When HubSpot reports the new contact, Dub reads its **Dub Click ID** and links the contact to the Dub link they came from, just like a contact created through a [HubSpot form](#option-1-using-hubspot-forms).

**1. Get a HubSpot access token**

To call the HubSpot API, you need an access token with the `crm.objects.contacts.write` scope.

If you don't have one yet, create an app in your HubSpot account that uses [static auth](https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/overview#static-auth), add the `crm.objects.contacts.write` scope, and copy the access token from your app settings.

> [!WARNING]
>
> Keep this token on your server. Never expose it in client-side code.

**2. Create the contact with the Dub Click ID**

On your server, read the `dub_id` cookie from the request and pass it as the `dub_id` property when you create the contact.

```ts Node.js theme={null}
import { cookies } from "next/headers";

const cookieStore = await cookies();
const clickId = cookieStore.get("dub_id")?.value;

const response = await fetch(
  "https://api.hubapi.com/crm/objects/2026-09/contacts",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      properties: {
        email: "john@example.com",
        firstname: "John",
        lastname: "Doe",
        dub_id: clickId,
      },
    }),
  },
);

const contact = await response.json();
```

```bash cURL theme={null}
curl --request POST \
  --url "https://api.hubapi.com/crm/objects/2026-09/contacts" \
  --header "Authorization: Bearer YOUR_HUBSPOT_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "properties": {
      "email": "john@example.com",
      "firstname": "John",
      "lastname": "Doe",
      "dub_id": "YOUR_DUB_CLICK_ID"
    }
  }'
```

Keep these in mind when creating the contact:

* **Include `dub_id` in the create request.** Dub reads the Dub Click ID when HubSpot notifies it that the contact was created, so the click ID needs to be on the contact from the start.
* **Always include `email`.** Dub uses the contact's email to match later deals for that contact back to the same customer, including the closed-won sale.

## Tracking conversion events

Dub's HubSpot integration automatically sets up webhooks to track contact, deal, and lifecycle stage changes, providing complete visibility into your sales funnel.

### When a contact is created

When a new contact is created in HubSpot with a **Dub Click ID** (e.g. via a [HubSpot form](#option-1-using-hubspot-forms) or the [HubSpot API](#option-3-using-the-hubspot-api)), Dub records a [deferred lead](/docs/conversions/leads/deferred) that links the contact to the Dub link they came from. The integration also fills in the contact's **Dub Link** and **Dub Partner Email** properties.

### When the lead trigger fires (lead event)

When the [lead trigger](#configure-lead-and-sale-tracking) you configured happens – a deal is created, a deal reaches your lead deal stage, or the contact reaches your lead lifecycle stage – the integration tracks a [lead event](/docs/quickstart/server#tracking-lead-events) in Dub for that contact.

Leads tracked by the HubSpot integration show up as `HubSpot lead` in the `Customer` `Source` [lead reward condition](/help/article/lead-rewards#customer-attributes), so you can pay partners a different amount for them.

### 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.

Sales tracked by the HubSpot integration show up as `HubSpot closed won deal` in the `Customer` `Source` [sale reward condition](/help/article/sale-rewards#customer-attributes), so you can pay partners a different amount for them.

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](#configure-lead-and-sale-tracking).

## Example apps

> **[Dub + HubSpot Demo App](https://github.com/dubinc/examples/tree/main/conversions/hubspot)**
>
> See the full example on GitHub.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.