Skip to content

Leveraging the Power of Dynamic Pages with HubSpot

In the rapidly evolving digital landscape, the need for personalised, engaging, and efficient web content is paramount. One of the ways businesses are meeting this demand is through the use of dynamic pages. But what exactly are dynamic pages and how can they be utilised to their full potential?

Dynamic pages in HubSpot are a type of web page that are dynamically created based on the URL. Typically one creates a listing page that will showcase various links to the dynamic pages. Below you will see a styled list that uses data in a HubDB table to provide links to the individual pages. We will show you the code later. Just realise that if we would add or amend one of the rows (= books) in the database, it would auto-update.

The cool thing however is not the listing page, but the dynamic pages themselves: we create one, and HubSpot does the rest.

So in our case if you click on a link, it will load a page that checks which book it will need to show the details from. This happens based on the last part of the URL, which we have set to include the name of the book in the listings page.

HubSpot's own documentation shows how to make a full page dynamic. We never use full pages but always modules. This allows more flexibility as you can mix and match standard content and smart content with dynamically generated content. The standard and smart content can later be amended by any marketeer without any need to understand code. This also means the developers can focus on just the part that they need to focus.

Here is what we cooked up for the listing:

Start With Why

by Simon Sinek

Book cover Start With Why
Why do you do what you do?

Why are some people and organizations more innovative, more influential, and more profitable than others? Why do some command greater loyalty from customers and employees alike? Even among the successful, why are so few able to repeat their success over and over?

People like Martin Luther King Jr., Steve Jobs, and the Wright Brothers might have little in common, but they all started with why. It was their natural ability to start with why that enabled them to inspire those around them and to achieve remarkable things.

In studying the leaders who've had the greatest influence in the world, Simon Sinek discovered that they all think, act, and communicate in the exact same way—and it's the complete opposite of what everyone else does. Sinek calls this powerful idea The Golden Circle, and it provides a framework upon which organizations can be built, movements can be lead, and people can be inspired. And it all starts with WHY.

Any organization can explain what it does; some can explain how they do it; but very few can clearly articulate why. WHY is not money or profit—those are always results. WHY does your organization exist? WHY does it do the things it does? WHY do customers really buy from one company or another? WHY are people loyal to some leaders, but not others?

Starting with WHY works in big business and small business, in the nonprofit world and in politics. Those who start with WHY never manipulate, they inspire. And the people who follow them don't do so because they have to; they follow because they want to.

Drawing on a wide range of real-life stories, Sinek weaves together a clear vision of what it truly takes to lead and inspire. This book is for anyone who wants to inspire others or who wants to find someone to inspire them.

So how did we create this?

In this case we started off with the simplest way to do it: create one single module that checks if it is on a dynamic page or not. And acts accordingly. This is following the example of the HubSpot documentation. In our example of dynamic pages build on custom objects we have actually split up the modules, so note that can be done just as well.
As you can see in the code below the module just includes 8 lines of HTML to present the 'details' page, and another 27 for the index page.

The same HubDB table that powers this page also powers the programmable email demo.

{% if dynamic_page_hubdb_row %}
  <!-- This will only execute if it is the books-detail page. NOT if it is the books index page -->
  <h1>{{ dynamic_page_hubdb_row.title }}</h1>
  <h3>by {{ }}</h3>
  <div class="details-img">
    {% image "book-cover" label="Book cover" alt="Book cover {{ dynamic_page_hubdb_row.title }}" src="{{dynamic_page_hubdb_row[6].url}}" width="300" %}
  {{ }}
{% elif dynamic_page_hubdb_table_id %}
  <!-- This will only execute if it is the books index page -->
  <div class="card-grid">
    {# retrieve each row #}
    {% for row in hubdb_table_rows(module.hubdbtable) %}
      <a href="{{ row[9] }}" aria-label="Read more about {{ row.title }}">
        <div class="card">
          <div class="card-img">
            {% image "book-cover" label="Book cover" alt="Book cover {{ row.title }}" src="{{row[6].url}}" width="300" %}
          <div class="card-body">
            <p class="card-author">
              Author: {{ }}
            <p class="card-genre">
              {# loop through genres #}
              {% for genre in row[7] %}
                {{ }}{% if not loop.last %}, {% endif %}
              {% endfor %}
    {% endfor %}
{% endif %}
.card {
  background: white;
  transition: background-color 0.3s ease;
  border-radius: 15px;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.25);
  margin: 20px;
  max-width: calc(100% - 40px);
  overflow: hidden;
  display: inline-block;

.card:hover {
  background: rgba(211, 254, 255, 0.5);

.card a {
  color: inherit;
  text-decoration: none;
  display: block;

.card-img {
  width: calc(100% - 30px);
  height: 450px;
  overflow: hidden;
  margin: 15px;
  border: 1px solid #4eaae3;
  box-shadow: 0 0 5px 5px rgba(211, 254, 255, 0.85);
  box-sizing: border-box;

.card-body {
  padding: 20px;

.card-title {
  margin: 0 0 10px 0;

.card-genre, .card-author {
  font-size: 0.9em;
  color: #666;

.card-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;

.details-img img {
    float: right;
    margin-left: 20px;
    margin-bottom: 20px;
    border: 1px solid #4eaae3;
    box-shadow: 0 0 5px 5px rgba(211, 254, 255, 0.85);
  "display_width": null,
  "id": "bba54aae-4637-3ef7-25cb-2472b159446c",
  "label": "HubDB table",
  "locked": false,
  "name": "hubdbtable",
  "required": true,
  "type": "hubdbtable"