# HubSpot Cloud Mode Integration (New API v3)

<p>RudderStack supports the following API calls while sending data to Hubspot via <a href="https://www.rudderstack.com/docs/destinations/rudderstack-connection-modes/#cloud-mode" >cloud mode</a> using the <a href="https://developers.hubspot.com/docs/api/overview" >new API v3</a>.</p>

<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text">RudderStack does not support the <a href="https://www.youtube.com/watch?v=2YjCUQUt8iY&amp;ab_channel=HubSpot" >new datetime data type</a> introduced by HubSpot.</div>
  </div>
</blockquote>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="identify">Identify</h2><p>RudderStack sends the <a href="https://www.rudderstack.com/docs/event-spec/standard-events/identify/" ><code>identify</code></a> call to check if a contact exists, if it does, RudderStack updates the contact with new information. Otherwise, it creates a new contact.</p>
<p>A sample <code>identify</code> call is as shown:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.identify({
  firstName: &#34;Alex&#34;,
  city: &#34;New Orleans&#34;,
  country: &#34;USA&#34;,
  phone: &#34;+1-202-555-0146&#34;,
  email: &#34;alex@example.com&#34;,
  custom_flavor: &#34;chocolate&#34;,
  custom_date: 1574769933368,
  custom_date1: new Date(&#34;2019-10-14T11:15:53.296Z&#34;),
})</code></pre></div>
</div>
<p>Make sure to specify the HubSpot property you set in <strong>HubSpot property to be used for upsert</strong> <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/hubspot/setup-guide/#new-api-settings" >dashboard setting</a> in the <code>traits</code> object of the <code>identify</code> call — RudderStack sends this property to HubSpot for matching contacts.</p>

<!DOCTYPE html>
<html lang="en">
<blockquote class="tip">
  <div class="tip-quote">
    
    <div class="tip-text"><p>For best performance, choose a HubSpot contact property that is unique in your account. Unique properties let RudderStack call HubSpot&rsquo;s <a href="https://developers.hubspot.com/docs/api-reference/crm-contacts-v3/batch/post-crm-v3-objects-contacts-batch-upsert" >batch upsert contacts API</a> for <code>identify</code> events, which significantly increases throughput.</p>
<p>Non-unique properties will still work, but RudderStack uses a slower search-based flow.</p>
</div>
  </div>
</blockquote>
</html>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.identify({
  name: &#34;Alex Keener&#34;,
  phone: &#34;+1-202-555-0146&#34;,
  uniqueId: &#34;user-12345&#34;
})</code></pre></div>
</div>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">If you configure <strong>HubSpot property to be used for upsert</strong> in the dashboard but omit that property in the <code>identify</code> traits, RudderStack uses <code>email</code> as the default field for matching.</div>
  </div>
</blockquote>

</html>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="trait-mappings">Trait mappings</h3><p>The following table lists the mappings between the RudderStack properties and the HubSpot properties:</p>
<table>
  <thead>
      <tr>
          <th>RudderStack property</th>
          <th>HubSpot property</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>traits.email</code> <br /> <code>context.traits.email</code> <br /> <code>properties.email</code></td>
          <td><code>email</code></td>
      </tr>
      <tr>
          <td><code>traits.firstName</code> <br /> <code>traits.firstname</code> <br /> <code>traits.first_name</code> <br /> <code>context.traits.firstName</code> <br /> <code>context.traits.firstname</code> <br /> <code>context.traits.first_name</code> <br /> <code>properties.firstname</code></td>
          <td><code>firstname</code></td>
      </tr>
      <tr>
          <td><code>traits.lastName</code> <br /> <code>traits.lastname</code> <br /> <code>traits.last_name</code> <br /> <code>context.traits.lastName</code> <br /> <code>context.traits.lastname</code> <br /> <code>context.traits.last_name</code> <br /> <code>properties.lastname</code></td>
          <td><code>lastname</code></td>
      </tr>
      <tr>
          <td><code>phone</code></td>
          <td><code>phone</code></td>
      </tr>
      <tr>
          <td><code>traits.address.street</code> <br /> <code>context.traits.address.street</code> <br /> <code>properties.address.street</code></td>
          <td><code>address</code></td>
      </tr>
      <tr>
          <td><code>traits.address.city</code> <br /> <code>context.traits.address.city</code> <br /> <code>properties.address.city</code></td>
          <td><code>city</code></td>
      </tr>
      <tr>
          <td><code>traits.address.country</code> <br /> <code>context.traits.address.country</code> <br /> <code>properties.address.country</code></td>
          <td><code>country</code></td>
      </tr>
      <tr>
          <td><code>traits.address.state</code> <br /> <code>context.traits.address.state</code> <br /> <code>properties.address.state</code></td>
          <td><code>state</code></td>
      </tr>
      <tr>
          <td><code>traits.address.postalcode</code> <br /> <code>context.traits.address.postalcode</code> <br /> <code>properties.address.postalcode</code></td>
          <td><code>zip</code></td>
      </tr>
      <tr>
          <td><code>traits.company.name</code> <br /> <code>context.traits.company.name</code> <br /> <code>properties.company.name</code></td>
          <td><code>company</code></td>
      </tr>
  </tbody>
</table>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="handle-null-and-empty-property-values">Handle null and empty property values</h3><p>The following table explains how specific trait values are handled when you update HubSpot properties from Event Stream or a <a href="https://www.rudderstack.com/docs/sources/reverse-etl/" >Reverse ETL</a> source connected to this destination:</p>
<table>
  <thead>
      <tr>
          <th>Trait value</th>
          <th>Event Stream</th>
          <th>Reverse ETL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>null</code></td>
          <td>Clears the property</td>
          <td>Leaves the property unchanged</td>
      </tr>
      <tr>
          <td><code>&quot;&quot;</code> (empty string)</td>
          <td>Clears the property</td>
          <td>Clears the property</td>
      </tr>
      <tr>
          <td><code>undefined</code></td>
          <td>Leaves the property unchanged</td>
          <td>Leaves the property unchanged</td>
      </tr>
      <tr>
          <td><code>false</code> or <code>0</code></td>
          <td>Sent unchanged</td>
          <td>Sent unchanged</td>
      </tr>
  </tbody>
</table>
<ul>
<li>In an <strong>Event Stream</strong> connection, <code>null</code> trait values are converted to <code>&quot;&quot;</code> before the request is sent. HubSpot treats <code>&quot;&quot;</code> as a clear signal and removes the property value.</li>
<li>In a <strong>Reverse ETL</strong> connection, <code>null</code> values are omitted from the update payload, so the existing HubSpot value is not modified.</li>
</ul>

<!DOCTYPE html>
<html lang="en">
<blockquote class="tip">
  <div class="tip-quote">
    
    <div class="tip-text">To clear a HubSpot property from a Reverse ETL sync, map an empty string (<code>&quot;&quot;</code>) for that field.</div>
  </div>
</blockquote>
</html>
<p>The HubSpot API clears properties only when you send <code>&quot;&quot;</code> — it does not accept <code>null</code>.</p>
<p>See the following HubSpot references for more information:</p>
<ul>
<li><a href="https://developers.hubspot.com/docs/api-reference/crm-properties-v3/guide" >CRM Properties API guide</a></li>
<li><a href="https://developers.hubspot.com/docs/api-reference/legacy/crm/properties/guide#clear-a-property-value" >Clear a property value</a></li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h2 id="track">Track</h2><p>A <a href="https://www.rudderstack.com/docs/event-spec/standard-events/track/" ><code>track</code></a> call lets you record various user actions and any properties associated with them.</p>
<p>To associate a <code>track</code> call with a user, you need to specify the user&rsquo;s <code>email</code> under <code>context.traits</code>.</p>

<html lang="en">
<blockquote class="info">
  <div class="tip-quote">
    
    <div class="tip-text">RudderStack associates the <code>track</code> events with the same user only after you make a successful <code>identify</code> call. However, if you send a <code>track</code> call without making any <code>identify</code> call first and there is no contact present in HubSpot, RudderStack will not associate the events as there is no identifier.</div>
  </div>
</blockquote>

</html>
<p>A sample <code>track</code> event is as shown:</p>
<div class="rs-code">
  <div class="rs-code__head">javascript<button class="rs-code__copy" type="button">
      
      Copy
    </button>
  </div>
  <div class="highlight"><pre class="chroma"><code class="language-javascript" data-lang="javascript">rudderanalytics.track(
  &#34;Order Completed&#34;, {
    value: 30,
  }, {
    context: {
      traits: {
        firstname: &#34;Alex&#34;,
        city: &#34;New Orleans&#34;,
        country: &#34;USA&#34;,
        phone: &#34;+1-202-555-0146&#34;,
        email: &#34;alex@example.com&#34;,
      },
    },
  }
)</code></pre></div>
</div>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="property-mappings">Property mappings</h3><p>The following table lists the properties and their mappings between RudderStack and HubSpot for the <code>track</code> call:</p>
<table>
  <thead>
      <tr>
          <th>RudderStack property</th>
          <th>HubSpot property</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>traits.utk</code> <br /> <code>context.traits.utk</code> <br /> <code>properties.utk</code></td>
          <td><code>utk</code></td>
      </tr>
      <tr>
          <td><code>traits.email</code> <br />  <code>context.traits.email</code></td>
          <td><code>email</code></td>
      </tr>
      <tr>
          <td><code>traits.objectId</code> <br /> <code>context.traits.objectId</code> <br /> <code>properties.objectId</code></td>
          <td><code>objectId</code></td>
      </tr>
      <tr>
          <td><code>properties.occurred_at</code> <br /> <code>timestamp</code> <br /> <code>originalTimestamp</code></td>
          <td><code>occurredAt</code></td>
      </tr>
  </tbody>
</table>

<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text">You must send either of the <code>utk</code>, <code>email</code>, or <code>objectId</code> (can be <code>contact_id</code> or <code>visitor_ id</code>) properties to make a <code>track</code> call successfully.</div>
  </div>
</blockquote>
<!-- end-chunk -->
<!-- begin-chunk -->
<h3 id="custom-behavioral-events">Custom behavioral events</h3>
<blockquote class="warning">
  <div class="tip-quote">
    
    <div class="tip-text">The custom behavorial events can be used for both the authentication types. However, they must have the <code>analytics.behavioral_events.send</code> permission to be used for private apps.</div>
  </div>
</blockquote>
<p><a href="https://developers.hubspot.com/docs/api/analytics/events" >Custom behavioral events</a> are account-defined events in HubSpot that store event details in the event properties. You can create custom behavioral events and their associated properties in the RudderStack dashboard as explained in the <a href="https://www.rudderstack.com/docs/destinations/streaming-destinations/hubspot/setup-guide/#new-api" >New API</a> section.</p>
<p>The following parameters are sent in the custom behavorial events:</p>
<ul>
<li><strong>Identifier</strong>: Either the contact ID, email, or <a href="https://developers.hubspot.com/docs/api/events/tracking-code" >utk</a> (user token) of the contact associated with the event. The utk is the user token stored in the visitor&rsquo;s <code>hubspotutk</code> browser cookie.</li>
<li><strong>Event name:</strong> The internal name of the event which can be found in HubSpot.</li>
<li><strong>Properties object</strong>: When you create a custom behavioral event in HubSpot, some default properties are provided with those events, explained in the below section.</li>
</ul>
<!-- end-chunk -->
<!-- begin-chunk -->
<h4 id="behavioral-events-property-mappings">Behavioral events property mappings</h4><p>The following table lists the <strong>optional</strong> and default property mappings between RudderStack and HubSpot for custom behavioral events:</p>
<table>
  <thead>
      <tr>
          <th>RudderStack property</th>
          <th>HubSpot property</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>properties.assetDescription</code> <br /> <code>properties.hsAssetDescription</code></td>
          <td><code>hs_asset_description</code></td>
      </tr>
      <tr>
          <td><code>properties.assetType</code> <br /> <code>properties.hsAssetType</code></td>
          <td><code>hs_asset_type</code></td>
      </tr>
      <tr>
          <td><code>properties.campaignId</code></td>
          <td><code>hs_campaign_id</code></td>
      </tr>
      <tr>
          <td><code>traits.address.city</code> <br /> <code>context.traits.address.city</code> <br /> <code>properties.address.city</code></td>
          <td><code>hs_city</code></td>
      </tr>
      <tr>
          <td><code>traits.address.country</code> <br /> <code>context.traits.address.country</code> <br /> <code>properties.address.country</code></td>
          <td><code>hs_country</code></td>
      </tr>
      <tr>
          <td><code>context.device.name</code></td>
          <td><code>hs_device_name</code></td>
      </tr>
      <tr>
          <td><code>properties.elementClass</code> <br /> <code>properties.hsElementClass</code></td>
          <td><code>hs_element_class</code></td>
      </tr>
      <tr>
          <td><code>properties.elementId</code> <br /> <code>properties.hsElementId</code></td>
          <td><code>hs_element_id</code></td>
      </tr>
  </tbody>
</table>
<br />
