Table of contents

Transitioning from V1 to V2 modules

This page is designed to give experienced custom module developers quick answers to common questions regarding the differences between version 1 custom modules and the new module framework (referred to here as v1 and v2). These changes have been made alongside a number of significant additions to the module framework that provide more robust and reliable options for building complex functionality. In the following sections, we’ll highlight the changes that are most likely to affect experienced developers and provide recommended approaches to a couple of common v1 patterns that will no longer be supported.

Please note: you can still edit and use your existing v1 modules in the module editor. Any new modules, including clones of v1 modules, will be created in the v2 module framework.

Using the inline_rich_text field

In order to achieve inline editing of a rich text module in v1, a custom module required an additional {% rich_text %} module tag or a {% widget_block %} tag.

In v2 we've added the ability to wrap a Rich Text field with a {% inline_rich_text %} module tag. The results look like:

{% inline_rich_text field="rich_text_field" value="{{ module.rich_text_field }}" %}

Using CSS/JS

V1 modules had a very open-ended approach to CSS and JS. Developers used a combination of techniques, loading code via require_js and require_css as well as many functions and tags that are no longer supported. For a full list of unsupported tags, please see the reference section.

V2 modules provide a more structured approach to CSS and JS. With the exception of custom modules for email use, all custom modules now have CSS and JS editor sections.

HubSpot Help article screenshot

Any CSS and JS that is specific to a module should be written in these sections of the editor. This code is minified and included in the head and foot of the served page. JS is also wrapped in a closure for namespacing.

If a module requires a library or other external assets, you should use the Linked Files section of the inspector.

HubSpot Help article screenshot

CSS and JS files included via Linked Files will automatically be loaded on pages using the module. Other assets, such as images will be copied from portal to portal with your module, but will only be loaded if and when they are referenced in your code (i.e. background images in CSS). When referencing these files, you should use the module_asset_url function, as illustrated below.

    background: url({{ module_asset_url('arrow.png') }});

Please note that this function is the ONLY HubL that can be placed in the CSS and JS sections of the editor. In the sections below we outline some solutions for scenarios when you might feel the need to use HubL in these sections.

To avoid any unexpected conflicts or dependency errors, please familiarize yourself with the order of execution for CSS and JS files:

The order of JavaScript includes are:

  1. external_js
  2. js_assets (in order)
  3. module js
  4. JS inside the HubL markup within a require_js block.

The order of CSS includes are:

  1. css_assets
  2. module CSS
  3. CSS inside the HubL markup within a require_css block.

Using Module vs. Widget to reference module fields.

The v1 module framework referenced module fields using {{ widget.field }}. The v2 framework references module fields using {{ module.field }}.

However, using {{ widget.field }} in the v2 framework will continue to work as expected.



Using JS plugins

The order of JavaScript includes detailed above should provide you with a good reference for organizing the code in your module. Typically if you’re using a 3rd party script, you will link the script file via the Linked files section of the inspector. Then you can instantiate the plugin in the JS section of the code editor. If you need to pass parameters to the plugin, you can use data attributes in the HTML + HUBL section of the editor to store these values. The screenshot below contains a pseudo-code example.

HubSpot Help article screenshot

Note: It is also possible to instantiate modules in the HTML + HUBL section if you prefer to pass HubL directly to your script. However, keep in mind that the script in the JS section of the editor is wrapped in a closure and will not be in the same namespace as a script written in the HTML + HUBL section.

Using HTML/HubL

HTML and HubL modules have been removed. These modules provided a quick way for developers to add snippets of HTML and HubL to a template. Unfortunately, they tend to make templates difficult to understand and edit. As part of a larger effort to make templates more predictable and maintainable, we’ve removed these modules in favor of keeping all code inside the context of custom modules.

If there is a strong need for adding HTML at the page-level of a website, the HTML module can be downloaded in the HubSpot Marketplace.

Recommendation: Small snippets of HTML/JS

A frequent pain point for content editors is when developers don't proactively provide solutions for common scenarios involving snippets of HTML or JS. Code such as embed scripts get pasted in between text and a video gets rendered more or less correctly. Except when it doesn’t. A custom module is the recommended solution for the vast majority of these scenarios.

In the example shown below, the developer has created a module with 3 fields, two of which have default values to allow a user to quickly and reliably embed a YouTube video. As opposed to requiring a user to paste embed code into a rich text module, this method gives the developer full control of the markup.

HubSpot Help article screenshot
The screenshot below shows the editing experience for this module. When the site editor goes to embed a YouTube video, they have all the options they need, and no ambiguity or room for error. The developer can also add help text and field validation to further improve the editing experience. Details on these techniques can be found here.
HubSpot Help article screenshot

Recommendation: HTML tables in emails

Up until now, it has been difficult to provide clients with expandable content areas with specific markup, especially in emails where flex columns are/were not available. Now that the new module framework allows you to create repeating fields and groups of fields, what was once impossible is now trivial.

In the example shown below, the developer has created two rich text fields named Column 1 and Column 2 and then grouped them and named the group Row. They then enabled Repeater options for the Row group.

With the fields configured this way, the developer looped through each row and plugged the column data into table cells. This example is extremely simple for the sake of clarity, but this technique can be extended and refined to give editors broad control over very complex layouts while maintaining developer control over every aspect of the markup.

More info on repeating and looping can be found here.

More info on groups can be found here.

HubSpot Help article screenshot