Supported products
Content Hub -Enterprise
Serverless functions provide a way to execute JavaScript through HubSpot on the server-side, preventing it from being exposed to the client. This can be especially important for making API requests that contain sensitive information, such as an API key or other credentials. When the function is invoked, HubSpot executes the function on its back-end, which also means you don't need to provide your own back-end servers to make requests for your CMS website. HubSpot’s serverless functions use the NodeJS runtime.
In this guide, you'll walk through creating a simple serverless function that fetches a quote from a third-party service, then displays that quote on a website page. To build and deploy the serverless function to your account, you'll use a HubSpot developer project.
Please note:
While the previously documented method of uploading serverless functions to the design manager is still supported, it's recommended to use developer projects, as they include a private app for easier authentication while also allowing for third-party dependencies. The content of this guide has been updated to use the newest method. You can find reference information for design manager-based serverless functions in the reference section.
For a high-level review of serverless functions, check out the serverless functions overview. You can also check out the HubSpot Developers YouTube channel for a walkthrough of using serverless functions in a CMS project.
Before starting this tutorial, you'll need:
- A Content Hub Enterprise account, or a CMS developer sandbox account.
- The HubSpot CLI (latest version recommended), which will need to be installed and authenticated with the account you're using. To check which accounts are authenticated, you can run
hs accounts list
. Learn more about getting started with local development.
Start by creating a project locally so that you can build and deploy it to your account.
- In the terminal, navigate to the directory where you'll be storing your project using the
cd
command.
cd Documents/Dev/serverless-function-project
- Run
hs project create
to create a new project.
xxxxxxxxxx
hs project create
- Follow the terminal prompts to create your project. For the template, select Create an empty project (no template).
- Navigate into the new project directory using the
cd
command. For example, if you named your project my new project:
xxxxxxxxxx
cd my-new-project
Once your project has been created, open it in your preferred editor, such as VS Code. HubSpot will have automatically created a project directory along with an empty src
directory and a hsproject.json
configuration file. To add a serverless function to the project, create an app
directory inside the src
directory, then add the following directories and files within it:
app/app.json
: the app configuration file.app/app.functions
: the serverless function directory. You can use any name you'd like, as long as it ends in.functions
.app/app.functions/function.js
: the JavaScript code that will be executed when the function is invoked.app/app.functions/serverless.json
: the serverless function configuration file.app/app.functions/package.json
: includes necessary dependencies.
- Copy the example code below into your respective local
app.json
,function.js
,serverless.json
, andpackage.json
files. Under each.json
code block, you'll also find a table containing field definitions.
xxxxxxxxxx
{
"name": "Serverless function app",
"description": "This app runs a serverless function to fetch a quote using the Zen Quotes API.",
"scopes": ["crm.objects.contacts.read", "crm.objects.contacts.write"],
"uid": "serverless-function-app",
"public": false
}
Field | Type | Description |
---|---|---|
name | String | The name of the app, which will display in HubSpot's UI. |
description | String | The app's description, which will display in HubSpot's UI. |
scopes | Array | The scopes that the app has access to for authenticating requests with the private app access token. The two scopes above are the minimum required scopes. No additional scopes are added for this tutorial, as you won't need to use the private app access token for the request you'll be making. |
uid | String | The app's unique identifier. This can be any string, but should meaningfully identify the app. HubSpot will identify the app by this ID so that you can change the app's name locally or in HubSpot without removing historical or stateful data, such as logs. |
public | String | Set to false for private apps. |
- After adding the above code, save your changes.
With your changes saved, you can now upload the project to HubSpot to build and deploy the app and serverless function.
- In the terminal, run
hs project upload
.
xxxxxxxxxx
hs project upload
- Confirm that you want to create the project in the account. You won't need to confirm again this for after initial creation. The terminal will display the current status of the build and deploy steps as they progress.
- Once the upload completes, run
hs project open
to view the project in HubSpot.
xxxxxxxxxx
hs project open
In HubSpot, you're able to view the project details, build and deploy logs, serverless function logs, manage the project and app, and more. Learn more about managing projects in HubSpot.
With the serverless function deployed, you can invoke it by hitting its public URL. Serverless functions built with developer projects have the following public URL structure: https://<domain>/hs/serverless/<endpoint-path-from-config>
.
<domain>
: you can use any domain connected to the account. For example, if both website.com and subdomain.brand.com are connected to the account, you could call the function usinghttps://website.com/hs/serverless/<path>
orhttps://subdomain.brand.com/hs/serverless/<path>
.<endpoint-path-from-config>
: the value in thepath
field inserverless.json
.
Based on the example code provided in this tutorial, the public URL to invoke the function will be: https://<domain>/hs/serverless/fetch-quote
.
In the URL to call the function, the endpoint path is global rather than scoped to the app or project. If you have identical endpoint paths across multiple apps or projects, the most recently deployed endpoint function will take precedence.
To view the function's output, navigate to that URL in your browser, replacing the domain with one of your HubSpot-hosted domains. If you haven't connected a custom domain, you can use one of the default domains that HubSpot provides: <hubId>.hs-sites.com
(e.g., 123456.hs-sites.com
). Your browser should display the data returned by the Zen Quotes API.
Now that you've created the serverless function and confirmed that it returns data, implement it into a page to see the data returned in a more realistic context. For this tutorial, you'll create a page template containing some custom JavaScript and HTML to execute the function and display the response data.
First, create a new page template:
-
In your local environment, create a new directory to contain your page template. For the purposes of this tutorial, create this directory outside of the project directory created by
hs project create
. -
In the terminal, navigate into that directory using the
cd
command.
xxxxxxxxxx
cd Documents/Dev/serverless-page
- Run
hs create template "serverless-template"
to create a new template namedserverless-template
.
xxxxxxxxxx
hs create template "serverless-template"
- Select the page template type.
- Open the newly created page template file in your editor, then replace the boilerplate code with the code below. Be sure to replace
<domain>
in the function endpoint URL (fetch('http://<domain>/hs/serverless/fetch-quote')
) with a domain that's connected to your HubSpot account.
<!--
templateType: page
label: Serverless function example template
isAvailableForNewContent: true
-->
<html>
<head>
<meta charset="utf-8" />
<title>{{ content.html_title }}</title>
<meta name="description" content="{{ content.meta_description }}" />
{{ standard_header_includes }}
</head>
<body>
{% module "page_template_logo" path="@hubspot/logo" label="Logo" %}
<!-- Button to fetch quote via serverless function -->
<div class="serverless-container">
<h2>Get quote</h2>
<p class="subtitle">Click the button to fetch and display a quote.</p>
<button id="data-button" type="button">Get quote!</button>
<div id="data-container">
<p class="data"></p>
</div>
</div>
<!-- End button section -->
{{ standard_footer_includes }}
<!-- JavaScript that invokes the serverless function
and adds returned data into the "data" text element -->
<script>
const dataButton = document.getElementById('data-button');
const dataContainer = document.getElementById('data-container');
dataButton.addEventListener('click', function (e) {
console.log('Button clicked!');
// Show loading state
dataContainer.innerText = 'Loading...';
// Replace <domain> with your own domain
fetch('http://<domain>/hs/serverless/fetch-quote')
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
// Parse the JSON response
return response.json();
})
.then((data) => {
console.log('Raw data received:', data);
// Clear container
dataContainer.innerText = '';
// Create the paragraph element
const newDataElement = document.createElement('p');
newDataElement.innerText = `"${data.q}" — ${data.a}`;
dataContainer.appendChild(newDataElement);
});
});
</script>
</body>
</html>
- Save the file, then run
hs upload
to upload it to HubSpot. Follow the terminal prompts to select the local source and destination path. For this tutorial, you can just press Enter for each prompt to use the default paths.
Next, create a new page from the template in HubSpot.
- Navigate to the website pages dashboard of your HubSpot account by running the
hs open website-pages
.
xxxxxxxxxx
hs open website-pages
See the full list of available open shortcuts by running hs open --list
.
- In your browser, click Create in the upper right to create a new page.
- In the dialog box, select a domain to use, then assign a Page name. The domain of the page will need to match the domain that you're using to invoke the serverless function to avoid cross-origin (CORS) errors. You can either select that domain from the dropdown menu, or update the endpoint URL in the page template code (
fetch('http://<domain>/hs/serverless/fetch-quote')
) to use the domain that you select in this step. - Click Create page.
- On the template selection screen, search for your new template. You can use the label or the file name to search for the template (e.g., "Serverless function example page"). The template will appear under Other templates, as it's not part of a theme.
- Click Select template.
- In the page editor, click Preview in the upper right.
- Click Open in a new tab.
In the new tab, you should now be able to click the button to fetch and display quotes.
Now that you've created and implemented a serverless function that interacts with a third-party API, there are a few ways to continue building up your serverless function usage, such as:
- Including authentication in a request to make calls to HubSpot APIs or other third-party authenticated APIs.
- Implement the button and JavaScript code into a module rather than hardcode it into the page template. This would give you a more portable option, enabling the function to be invoked from any page that the module is added to. To do so, you would create a module, then add the HTML into the module's
module.html
file, and the JavaScript into themodule.js
file.
xxxxxxxxxx
<div class="serverless-container">
<h2>Get quote</h2>
<p class="subtitle">Click the button to fetch and display a quote.</p>
<button id="data-button" type="button">Get quote!</button>
<div id="data-container">
<p class="data"></p>
</div>
</div>