Table of contents

Custom modules

Custom Modules allow HubSpot designers and developers to create a custom group of editable content objects that maintain their style across individual templates and pages on HubSpot’s COS, while still allowing marketers to control the specific content appearing within those modules on a page-by-page basis.  Custom Modules are the best solution for content that has slight variations between pages but needs to maintain a consistent look and feel in terms of styling, like featured content modules or related product lists. Highly stylized groups of content that are another application. 

Available fields

Custom Modules currently include 5 unique field types, 3 content fields and 2 control operators, which let content creators manage the content to be displayed at the page editing level. Custom modules include the following field options.

Text Field – Use this for single-line text sections of your custom module, like the header

Image Field – A single image container module that includes sizing options, default image, and alt text parameters

Rich Text Field – A multi-line text module that supports the tinyMCE WYSIWYG interface, CTAs, images, and standard text style content

Control Modules:

Boolean Field – An on/off checkbox visible in the content editor interface that allows content creators to toggle inner content to be displayed on the page by checking or unchecking the box

Choice Field – A radio select/pick list option visible in the content editor that lets the marketer select and insert a predefined value into the content of the module

These fields are used in the context of your custom HTML markup to create reusable styled blocks of content.

In addition to the standard fields, custom modules also support all other HubL statements and expressions. Using HubL greatly expands the potential of what you can do with custom modules. For example, you could add CTAs, forms, menus, etc. to a reusable custom module. However, please note that modules defined within a custom module will not render as part of the custom module in the content editor.


<h1> {{widget.a_custom_header }}</h1>
<div id="custom-module-body">
    {% if widget.custom_image_module.src %}
        <img src="{{ widget.custom_image_module.src }}" width="{{ widget.custom_image_module.width }}" height="{{ widget.custom_image_module.height }}" alt="{{ widget.custom_image_module.alt }}">
    {% endif %}
    <p>{{ widget.body_text }}</p>
{% if widget.related_content %}{{ widget.related_marketing_offers }}{% endif %}


This Custom Module consists of 3 primary content fields and 2 control modules.  The header, image, and content body section will be visible on any page using a template that includes the Custom Module.  The related_marketing_offers module will only be included in the display if the editor enables it to display by toggling the on/off checkbox within the page editing interface.  If it is enabled, the user can select a pre-defined set of links to featured content to display below the primary content.

Example Fields and End User form View

Conditional logic in Custom Modules

If statements in custom modules automatically check whether the module field has a value. Unlike HubL modules, where you have to use export_to_template_context to make parameters available for logic, custom modules use a simplified syntax to check for values. Below is an example of a choice field defining that markup based on which option is selected.
{% if widget.my_choice == "Option 1" %} Option 1 was selected. {% elif widget.table_type == "Option 2" %} Option 2 was selected. {% else %} Option 3 was selected. {% endif %}

Embedding a custom module in an HTML template

To embed a custom module in an HTML template, you need to know the internal name of the custom module. The internal name should match the name of the Custom Module in Design Manager, exactly.

The unique name given to the tag can be any unique name given to this instance of a custom module. If you have multiple instances of a custom module, in a coded template, you will want to give them each a different unique tag name. You can learn more about module syntax here.

{% custom_widget "unique_name_for_custom_module" widget_name='Internal name of custom module (the name of module in Design Manager)', label='In-app label of custom module (what the user will see in the content editor)' %}

Using HubL within Custom Modules

Unlike the 5 custom module field types, HubL modules defined within a custom module will not render as part of that custom module in the content editor. They will instead be available in the Edit Modules pane of the content editor.

Additionally, each instance of a custom module automatically gets a unique name in the context of a template layout (ex. module_13470987764). Modules defined within a custom module \ have the custom module's name appended to their name in the context of the template. For example, if you defined a simple menu modules named "my_menu", the modules actual name would be" module_13470987764_my_menu". It is important to keep this in mind, when using export_to_template_context.