UI Extensions overview (BETA)
-
Sales Hub
- Enterprise
-
Service Hub
- Enterprise
HubSpot UI extensions enable you to customize HubSpot’s CRM record UI to suit your needs. UI extensions can interact with both HubSpot and external data so that you can quickly access data from within and outside of the account.
React-based UI extensions differ from the previously released JSON-based extensions by offering:
- More interactivity and flexibility, whereas JSON-based custom cards could be considered more static.
- A full-stack approach with a separation between the UI component front end from the serverless function back end. One serverless function can be reused by multiple UI components as needed.
By building full-stack UI extensions with React, you can create interactive, state-based experiences for HubSpot users across CRM record pages.
Full-stack UI extensions are built using React as a primary front end framework and HubSpot's serverless functions as a backend for operations such as fetching data. Extensions are built locally using the HubSpot CLI, which you'll use to run a HubSpot local development server for the front end and deploy back end changes to the HubSpot account. Extensions are powered by the UI extensions SDK, which offers a number of actions, utilities, and UI components. The UI extensions SDK is published as an npm package, which you'll include in the package.json
file within the extensions
directory.
The UI extensions SDK enables you to:
- Register an extension with HubSpot
- Run serverless functions
- Add actions to your extension, such as opening an iframe in a modal, adding success and failure alerts, and fetching CRM properties
Learn about adding functionality to your extension through the SDK.
A UI extension is built using developer projects and is contained within a private app. The extension then uses components to render a UI and display information retrieved by the app’s serverless function. UI components are provided by the UI Extension SDK and can be customized through their included fields. Because you’re using React, you can also create your own component building blocks by packaging these components and importing them as needed.
At a high level, a React-based UI extension consists of:
- Serverless function back end: an
app.functions
directory containing the serverless function .js file and a .json configuration. You can also add apackage.json
file to include any needed dependencies. The serverless function sends/fetches data that your React components can later use. - React front end: an extensions directory containing
.jsx
or.tsx
files to render components, along with the card’s.json
configuration and a requiredpackage.json
that includes any needed dependencies.
package.json
file. You can use these files to include dependencies as needed.
You can fetch data in multiple ways, depending on the data source:
- To fetch third-party data, you can make API requests authenticated by secrets.
- To fetch HubSpot data, you can:
- use the
fetchCrmObjectProperties
action to fetch data from the currently displaying CRM record. - use HubSpot's API endpoints to fetch data outside of the currently displaying CRM record.
- use GraphQL to query CRM data directly.
- use the
- To work with external, non-HubSpot data, you can use an API client, such as Axios or other third-party clients, in your serverless function. To authenticate these requests, learn how to create and use secrets in serverless functions.
- You can similarly fetch data via HubSpot's APIs, but instead of authenticating with a secret, you'll use the private app's access token. Learn more about authenticating HubSpot API calls with private app access tokens.
To review an example of how to fetch data from a third-party source, check out the mapbox-api code sample in the ui-extensions-examples
repository on the HubSpot GitHub page.
To fetch data from the HubSpot account, such as displaying property data from the record you’re viewing, you’ll pass the fetchCrmObjectProperties
method to the extension via hubspot.extend()
in your React files. This method automatically handles authentication, so you don't need to include a private app access token. Learn more about the fetchCrmObjectProperties method.
In addition to using fetchCrmObjectProperties
, CRM data components can fetch and visualize HubSpot data out of the box.
If you want to fetch HubSpot data outside of the CRM record, you'll need to make a HubSpot API call instead. You can also use GraphQL to query CRM data through the /collector/graphql
endpoint. Learn more about querying CRM data using GraphQL.
Using serverless functions
For security, the React front end cannot fetch data directly with APIs. Instead, you'll use HubSpot serverless functions to fetch the data you need. Then, with React you'll use runServerlessFunction
to call the serverless function and send your JSON payload as parameters. Learn more about runServerlessFunction.
Because UI extensions are split between front end and back end, you can call multiple serverless functions from the same card. Or, you can reuse the same serverless function to run different operations and pass them as needed to the front end.
If your serverless function requires secrets, learn more about managing secrets for deployed serverless functions and local development.
Handling failure with serverless functions
There are two ways that runServerlessFunction
can fail:
- A failure in executing the serverless function
- A failure in executing your code inside the serverless function
You can handle both scenarios by catching the error inside your serverless function with try ... catch
blocks. On the React front end side, you'll need to check for status
in the response, treating SUCCESS
and ERROR
appropriately. To ensure a good user experience in HubSpot, you can use the ErrorState component to communicate error messages with next steps.
In rendering React-based, full-stack UI extensions, HubSpot uses sandboxed iframes for isolation, web workers for untrusted code execution, and Shopfiy's remote-ui library for UI abstraction. This enables you to build with familiar tools like React and JavaScript, and remote-ui
translates that into specific components to the host via postmessage
. This process is essentially serializing a React element tree and sending it through postmessage
for the host to evaluate. This results in benefits, such as:
- Helping to protect both you and HubSpot with a sound and resilient solution for isolated code execution, while ensuring a consistent in-app user experience through the use of HubSpot's component library.
- Providing you with a productive and delightful developer experience by leveraging mainstream frameworks like React.
However, it also separates the UI extensions from typical web applications built with React. Below, learn more about some of differences you can expect when developing React-based UI extensions.
Non-HubSpot component libraries
When building UI extensions on HubSpot, you can only use the components provided through the UI extensions SDK. Each component has a set of parameters that you can use for customization, but these components cannot be customized beyond those parameters.
Accessing DOM elements
Because UI extensions are rendered through sandboxed iframes, they cannot directly access the DOM. This restriction means that common methods of DOM manipulation and event listening, such as document.getElementById
or document.addEventListener
, are unavailable within the iframe's local script context. However, some components provide callback functions that you can use for certain events, like clicks, focus, and input.
Examples of unsupported hooks
- React Router's
useNavigate()
hook will not function as expected within a UI extension. This hook manipulates the browser's window object to change the URL, which is not allowed within a sandboxed iframe. - The
useForm()
hook from react-hook-form is not supported because it relies on creating event listeners directly on DOM elements for form validation and submission, which is not allowed within a sandboxed iframe.
Custom styles on HubSpot components
Because you can't access the DOM and components don't pass the style
prop to the renderer, you can only style components with the provided component props.
Making client-side HTTP requests
You cannot make client-side HTTP requests through UI extensions, meaning browser features like fetch
and XMLHttpRequest
will not work, nor will libraries like Axios, which is built around those features. Instead, requests should be made through the serverless function, executed by HubSpot behind the scenes.
Using cookies to store session information
Requests made within the sandbox do not contain cookies, so rather than trying to store session information with cookies, you can look to the context
object, which is passed to the extension component via hubspot.extend
. This object contains information related to the authenticated user and HubSpot account. Learn more about fetching account and user data.
Thank you for your feedback, it means a lot to us.