This blog post is part of our 5-part series about HubSpot API Features. In case you missed Part 2, check it out here!
In this third installment of our HubSpot API series, we’ll talk through a powerful backend and frontend tool that allows marketers to better dynamicize their assets.
You’re probably familiar with HubSpot’s default object model (contacts, companies, deals, tickets, products, line items). If you’ve read the previous post in the series on custom objects, you’re aware of how to extend the default model to suit your data needs as well.
And while this object data can be referenced by marketing assets to serve dynamic content to your contacts, there could be additional use cases where you’d like to dynamically pull other kinds of data into your assets. HubDB is likely the solution for such needs.It provides data storage flexibility outside the bounds of the object model and can be easily called into your marketing assets.
HubSpot HubDB
As you’ve probably gleaned, HubDB is a way to store data in a relational manner (think tables with columns and rows) where the data can be dynamically pulled into key marketing assets, like emails and landing pages. And because this data isn’t stored within HubSpot’s object model (contacts, companies, deals, etc), it’s inherently more flexible and can essentially serve any sort of data to your assets.
You can reference your HubDB data programmatically in a few different ways:
- By querying (externally) via the HubDB API
- Within HubL markup language in your website pages, landing pages, and emails
- Via serverless functions in a web app
In this article, we’ll just cover the first two methods, but keep an eye out for a separate post on serverless functions in the future.
So far, this probably seems a bit abstract, so let’s take a look at a real-world example…
Getting Started
The best way to get started is to, well… get started! Let’s hit the API and create a HubDB table so we can add in some sample data and then view said data. While you can create a table and import data on the frontend, we’re reviewing the programmatic way to do this so you can automate these tasks for future use.
Again, HubDB tables can be thought of as big spreadsheets with columns, rows, and cells. To create one of these tables, we’ll need to define our headers (columns) so we can import data (as rows/cells).
Let’s say we’re in the events space and our marketing team wants to promote upcoming trade shows in a geographic region via a landing page. Let’s also assume we have a database containing all of the up-to-date, relevant event data we could want to display on this landing page. It’s safe to assume that our marketing team members have a lot of work on their plates and don’t want to have to manually update the page every week.
1. Create a table
With those assumptions noted, here’s how we can create a HubDB table, with a cURL request, to store our event data:
curl --request POST \
--url https://api.hubapi.com/cms/v3/hubdb/tables \
--header 'authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'content-type: application/json' \
--data '{
"label": "Events",
"name": "events",
"columns": [
{
"name": "event_name",
"label": "Event Name",
"id": "1",
"type": "TEXT"
},
{
"name": "event_date",
"label": "Event Date",
"id": "2",
"type": "DATE"
},
{
"name": "event_location",
"label": "Event Location",
"id": "3",
"type": "TEXT"
}
],
"useForPages": true,
"allowChildTables": false,
"enableChildTablePages": false,
"allowPublicApiAccess": true
}'
Here, we’ve created a table named Events with three columns: Event Name, Event Date, and Event Location. At the end of the data payload, we’ve also indicated that this table can be used in HubSpot pages and accessed via the API.
2. Import Data
Now that we have our table created, let’s import some sample data into it. Later, we’ll call this sample data into a landing page via HubL.For now, we’ll focus on getting it into the table and viewing the raw data.
This cURL example illustrates how to import a single row of data but you can (and certainly will want to) configure your code to make this request in some sort of loop.
curl --request POST \
--url https://api.hubapi.com/cms/v3/hubdb/tables/events/rows \
--header 'authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'content-type: application/json' \
--data '{
"path": "events",
"name": "event_name",
"values": {
"event_name": "obo 2022 Event",
"event_date": 1659312000000,
"event_location": "Washington, DC"
}
}'
You should get a 201 success response back, indicating a row has been created in the Events table with: an Event Name of “obo 2022 Event”, an Event Date of 8/1/2022 (the HubSpot API expects the unix millisecond at midnight to be passed), and an Event Location of “Washington, DC”.
Some other callouts here: the value of the “path” key in the data payload is used as the slug in dynamic pages. Similarly, the value of the “name” key is used as title in the dynamic pages.
You can also programmatically import table data from a CSV file, which could be a solid approach if you’re leveraging some sort of FTP server/process. Check out HubSpot’s full documentation here for more info.
3. View/retrieve Data
Now that we have some data inserted into our table, let’s view it to make sure it all looks good. You can do this on the frontend by navigating to Marketing → Files and Templates → HubDB and then to your newly created table:
But let’s also take a look at how to do this on the backend, via the API (make sure you table is published first):
curl --request GET \
--url https://api.hubapi.com/cms/v3/hubdb/tables/events/rows \
--header 'authorization: Bearer YOUR_ACCESS_TOKEN'
You can expect a response like this:
HTTP 200
{
"total": 1,
"results": [
{
"id": "80647711550",
"createdAt": "2022-07-31T01:45:10.255Z",
"updatedAt": "2022-07-31T01:45:10.255Z",
"values": {
"event_location": "Washington, DC",
"event_date": 1659312000000,
"event_name": "obo 2022 Event"
},
"path": "events",
"name": "event_name",
"childTableId": "0"
}
]
}
HubDB with HubL
Now that we’re comfortable interacting with our table via the API, let’s take this example a bit further. As mentioned, our marketing team wants to have our table data pulled into their landing page automatically so they don’t have to spend time manually updating.
To do this, we’ll want to leverage HubL, HubSpot’s templating language for CMS and marketing assets. HubL is built on top of Jinja (a widely-use templating language) and much of the syntax is similar, so it may look familiar to you already. We’ll assume you have some HubL experience/familiarity already but if not, be sure to check out the docs first.
HubL will allow us to call our table and loop through the contents of the table (i.e. each row of the table) and display the data points (columns) we want on the page. This means our landing page will automatically update in real-time with updates made to our table. This also means that we can set up code to systematically query our fictional database of events data and upsert updates into our HubDB table, which will then show on our landing page.
1. Create a module
The first step here is to create a module that we can pull into our landing page. This module will contain HubL code which will reference our newly created HubDB table and allow it to be displayed onto our page.
This is done on the frontend of HubSpot, so navigate to Marketing → Files and Templates → Design Tools. Once there, create a new file with the Module type.
We’ll make the module super simple to keep the example straightforward, but you’ll want to make sure it’s styled to fit the theme of your landing page. So all we’re going to do is write some HubL, wrap it in body HTML tags, and drop it into the module.html (HTML + HubL) section. We can leave the module.css and module.js sections blank.
Here’s what we’ll drop into the module.html section:
{% set trows = hubdb_table_rows(YOUR_TABLE_ID) %}
{% for row in trows %}
{{ row.event_name }}
{{ row.event_date }} | {{ row.event_location }}
{% endfor %}
And that’s it. We’ve called the table in the first line of HubL, and looped through each row, referencing the columns we want to display. Don’t forget to hit the Publish button once you’re done so it can be called in our landing page builder.
2. Reference module within landing page
Now that our module’s created, let’s go to our landing page (we’re assuming yours is built already) and drop in the module where we want to display it (we’ve names our module: Events Module):
Now, you can preview your page and can expect to see the table data formatted as we wrote in our module code. If you don’t like the formatting, you can always update the module to display the column data that best suits the page.
Note that the date shows as the unix millisecond timestamp in our example, for illustrative purposes. You may want to configure your date column as a text type for better formatting within your assets.
Final Thoughts
To fully automate this process, you’d need some sort of scheduled runtime to pull updated data from the fictional events database and upsert into the HubDB table, which, truthfully, is probably the bulk of the project. Our intention with this walkthrough is to familiarize you with HubDB and how it functions, but is by no means exhaustive.
Our example is relatively small in scope, but it’s important to note that HubDB is really powerful and can be leveraged for more complex needs. Some features to call out that we didn’t dig into are:
Relational tables – like any relational database, HubDB allows you to “connect” tables together by matching up Foreign IDs with another table (docs here).
Serverless functions – a way to write server-side code that interacts with HubSpot APIs without having to spin up/manage servers (docs here)
Batch API functionality – endpoints designed to interact with your HubDB tables in bulk, increasing speed, efficiency, etc (docs here)
HubL filter querying – in our example, we pulled the entire table into the landing page, but oftentimes it makes sense to filter down your table to pull in more specific rows (docs here)
Finally, here are some limitations with HubDB to be aware of:
- Only available on Marketing Hub Enterprise or CMS Hub Professional/Enterprise
- 10k rows per HubDB table
- 1k tables per account
- 10 table scans per CMS page