CMS Module fields being set by file or database query

Hi,

I need to have an Image Slider module thats used in 20+ webpages that is always the same. Same images, same captions, same links, etc.

I’m new to Hubspot. I understand I can clone the image slider and customize it, and I can create custom fields for my custom module. But how do I have the module’s fields be set via a query to a database or read values from a common file?

I want to avoid needing to update the image slider on each individual webpage every time there is a change.

Thanks,

-Chris

Hi @Strandtc,

welcome to HubSpot!

You’re looking for a socalled “global” module. They are designed exactly the way you want. Set the content once and use it as often as you want/need. The benefit - if you change the content it will be automatically updated on every instance of the module.

Since you’re new to HubSpot development I assume you’re working with the design-tools(which is great to get startet) and haven’t switched to local development/CLI.

To create a global module follow those simple steps:

  1. Right click on the folder you’d like to create the module in
  2. Select “Create new file”
  3. Select “module” in the dropdown
  4. Select the page-types(pages, blog post, blog listing…; you can change this later) you’d like to use the module in
  5. Important: Select “global module” instead of “local module” (unless you’re using local environment/CLI you can’t change this setting later)
  6. Enter a name. You can anything but it should be descriptive and I recommend to use underscores instead of spaces if you enter several words(you can set a label for the page editor later if you want)
  7. done! - You’ve created a global module :tada:

Now it’s about the function itself. Since you’d like to have a slider you’ll need some sort of JS library(at least I recommend to use one). Those are great ones

(Of course you can use any other slider script you want) - the idea/procedure is always the same

Once you’ve decided which library you’d like to use you can:

  • implement it right into the module
  • create a seperate JS(and CSS) file(s) in your theme/folder structure, paste the needed JS/CSS parts into the right file and link this file inside the module (a few more clicks but can be benifitial for page performance)

If you decide to implement it right into the module write it like this in the HTML + Hubl area

{% require_head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
{% end_require_head %}

There are several alternatives how to write this since you shouldn’t overload the head with bunch of files but let’s keep this for this example

The next step is quite simple:

Just add all of your desired features into the “Fields” in the right sidebar.
Use an image field for images(you could also use a text field if you want to load images from an external source), for different texts I recommend to use multiple simple text fields instead of one rich-text but it’s up to you

Once you’ve created all of your fields it should look like this:

Now the most important part:

  • Click on “Actions” and select “Group”. Select all the fields that should be available for every image (I assume all of those 3) and click “Create group”
  • Give this group a name - something like “Images”. Something that is descriptive
  • Last but not least - The magic trick: Scroll down to the “Repeater options” of this group, enable thm and - optionally - set a min, max and default number of images you’d like to use

Now this group is a repeater and can be coded with a socalled for-loop.

You’re almost done with the global slider :tada:

Now you have to write the actual layout

Since I’m using swiper.js and the basic layout of it looks like this

<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
 <div class="swiper-slide">Slide 1</div>
 <div class="swiper-slide">Slide 2</div>
 <div class="swiper-slide">Slide 3</div>
 ...
 </div>
 <!-- If we need pagination -->
 <div class="swiper-pagination"></div>

 <!-- If we need navigation buttons -->
 <div class="swiper-button-prev"></div>
 <div class="swiper-button-next"></div>

 <!-- If we need scrollbar -->
 <div class="swiper-scrollbar"></div>
</div>

I’m placing this exact code right below the already written code into the HTML+Hubl area.

It should look like this now

{% require_head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css"/>

<script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
{% end_require_head %}

<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
 <div class="swiper-slide">Slide 1</div>
 <div class="swiper-slide">Slide 2</div>
 <div class="swiper-slide">Slide 3</div>
 ...
 </div>
 <!-- If we need pagination -->
 <div class="swiper-pagination"></div>

 <!-- If we need navigation buttons -->
 <div class="swiper-button-prev"></div>
 <div class="swiper-button-next"></div>

 <!-- If we need scrollbar -->
 <div class="swiper-scrollbar"></div>
</div>

If you want pagination, prev/next buttons or a scrollbar check out the demos of the slider how to implement those features. I won’t use them for this specific case so my code looks like this now

...
<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
 <div class="swiper-slide">Slide 1</div>
 <div class="swiper-slide">Slide 2</div>
 <div class="swiper-slide">Slide 3</div>
 </div>
</div>

And since we’re in HubSpot and we’re using a repeater/for-loop we can modify the code much more so it looks like this

...
<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
 <div class="swiper-slide">Slide 1</div>
 </div>
</div>

Now the fun part - writing the repeater

First: Wrap the single slide div in a for loop so the code looks like this

<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
	 {% for single_slide in module.images %}
 <div class="swiper-slide">Slide 1</div>
	 {% endfor %}
 </div>
</div>

by doing so everything that is inside the {% for %} and {% endfor %} variable will be created for each item you’ll add to the repeater

Let’s add all created fields to this code so it’ll be actually an image slider.

The whole code should look like this now:

{% require_head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css"/>

<script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
{% end_require_head %}

<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
	 {% for single_slide in module.images %}
	 {% set loadingAttr = slingle_slide.image.loading != 'disabled' ? 'loading="{{ slingle_slide.image.loading }}"' : '' %}
	 {% set href = slingle_slide.link.url.href %}
	 {% if slingle_slide.link.url.type is equalto "EMAIL_ADDRESS" %}
		 {% set href = "mailto:" + href %}
	 {% endif %}
 <div class="swiper-slide">
			 <a href="{{ href }}" {% if slingle_slide.link.open_in_new_tab %}target="_blank"{% endif %} {% if slingle_slide.link.rel %}rel="{{ slingle_slide.link.rel }}"{% endif %}>
			 <img src="{{ slingle_slide.image.src }}" alt="{{ slingle_slide.image.alt }}" {{ loadingAttr }} class="slider-image">
			 </a>
			 <div class="description-wrapper">
				 <p>
					 {{ single_slide.description }}
				 </p>
			 </div>
		 </div>
	 {% endfor %}
 </div>
</div>

Let’s add the required JS part so the swiper works

{% require_head %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css"/>

<script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
{% end_require_head %}

<div class="swiper">
 <!-- Additional required wrapper -->
 <div class="swiper-wrapper">
 <!-- Slides -->
	 {% for single_slide in module.images %}
	 {% set loadingAttr = slingle_slide.image.loading != 'disabled' ? 'loading="{{ slingle_slide.image.loading }}"' : '' %}
	 {% set href = slingle_slide.link.url.href %}
	 {% if slingle_slide.link.url.type is equalto "EMAIL_ADDRESS" %}
		 {% set href = "mailto:" + href %}
	 {% endif %}
 <div class="swiper-slide">
			 <a href="{{ href }}" {% if slingle_slide.link.open_in_new_tab %}target="_blank"{% endif %} {% if slingle_slide.link.rel %}rel="{{ slingle_slide.link.rel }}"{% endif %}>
			 <img src="{{ slingle_slide.image.src }}" alt="{{ slingle_slide.image.alt }}" {{ loadingAttr }} class="slider-image">
			 </a>
			 <div class="description-wrapper">
				 <p>
					 {{ single_slide.description }}
				 </p>
			 </div>
		 </div>
	 {% endfor %}
 </div>
</div>

{% require_js %}
{# this will load the script above the closing body-tag #}
<script>
 var swiper = new Swiper(".mySwiper", {});
</script>
{% end_require_js %}

You’re done!

To put content into the module simply click on the “edit global module” button, place your content, save it and use it.

best,

Anton

Thanks, Professor @Anton :raising_hands: — Jaycee

Just an update on what I decided to do. I needed a copy of the image slider module, but I needed it global, instead of global. So I simply made a new global module, copied the image slider code (html, js, etc) and recreated all the fields. This was all done in the “Design Tools” interface. I then included the module in a page, and edited the global version of my new image slider. If I need other global image sliders, I’ll simply copy it, and change what I need.

Thanks for the direction, and the very complete answer.

In 2025 the cleanest native path is a global module for the slider, so you edit it once in the global content editor and every page updates automatically

(Use global content across multiple templates )

If you want non-developers to swap slides without touching the module, wire the module to a HubDB table and iterate rows in the module. Then swapping images, captions, or links is just editing the table, and every instance reads the new data on publish

(Create and populate HubDB tables )

If you truly need to pull from an external database in 2025, add a small serverless function to fetch and normalize the slide JSON, and have the module render that response. This keeps keys off the client and lets you add caching to avoid delays, but it requires Content Hub Enterprise. Quick check: are your slides managed inside HubSpot or coming from an external source?

If duplicates start upstream, Stacksync reduces them by syncing normalized records into HubSpot rather than batch-importing surprises.

Hey @RubenBurdin,

thanks for re-opening a topic that has been solved for over 2 years for, how it seems, promote your own software/tool.
The original question wasn’t related to anything database related but a “simple” module.

cheers,

Anton