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:

Predictably Irrational

by Dan Ariely

Book cover Predictably Irrational

Why do our headaches persist after taking a one-cent aspirin but disappear when we take a 50-cent aspirin?

Why does recalling the Ten Commandments reduce our tendency to lie, even when we couldn't possibly be caught?

Why do we splurge on a lavish meal but cut coupons to save twenty-five cents on a can of soup?

Why do we go back for second helpings at the unlimited buffet, even when our stomachs are already full?

And how did we ever start spending $4.15 on a cup of coffee when, just a few years ago, we used to pay less than a dollar?

When it comes to making decisions in our lives, we think we're in control. We think we're making smart, rational choices. But are we?

In a series of illuminating, often surprising experiments, MIT behavioral economist Dan Ariely refutes the common assumption that we behave in fundamentally rational ways. Blending everyday experience with groundbreaking research, Ariely explains how expectations, emotions, social norms, and other invisible, seemingly illogical forces skew our reasoning abilities.

Not only do we make astonishingly simple mistakes every day, but we make the same "types" of mistakes, Ariely discovers. We consistently overpay, underestimate, and procrastinate. We fail to understand the profound effects of our emotions on what we want, and we overvalue what we already own. Yet these misguided behaviors are neither random nor senseless. They're systematic and predictable--making us "predictably" irrational.

From drinking coffee to losing weight, from buying a car to choosing a romantic partner, Ariely explains how to break through these systematic patterns of thought to make better decisions. "Predictably Irrational" will change the way we interact with the world--one small decision at a time.

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"