Si vous travaillez avec le CMS HubSpot, les modules personnalisés sont la compétence la plus importante que vous puissiez apprendre. Ils donnent aux éditeurs de contenu un contrôle total sur le contenu de la page tout en gardant le code propre, rapide et facile à maintenir.
Mais voici le problème — la plupart des développeurs HubSpot construisent les modules de la mauvaise manière. Ils écrivent du CSS surchargé, ignorent le regroupement des champs, codent en dur les balises de titre et négligent complètement les performances. Le résultat ? Des pages lentes, des éditeurs frustrés et un code désordonné que personne ne veut maintenir.
Ce guide couvre tout ce dont vous avez besoin pour construire des modules personnalisés prêts pour la production dans HubSpot — de la bonne manière. Avec de vrais exemples de code, une structure de champs appropriée, les meilleures pratiques HubL et des conseils de performance qui font vraiment la différence.
Comprendre les modules personnalisés HubSpot
Un module personnalisé est un bloc de contenu réutilisable composé de quatre fichiers dans le Gestionnaire de conception :
- module.html — Votre modèle HTML avec des balises HubL qui rendent le contenu dynamique
- fields.json — Définit les champs que les éditeurs de contenu voient et avec lesquels ils interagissent
- module.css — Styles optionnels limités à ce module
- meta.json — Configuration comme l'étiquette, l'icône et les types de modèles qui peuvent utiliser ce module
Voyez cela comme la construction d'une brique Lego. Vous la concevez une fois avec tous les bons points de connexion, puis les éditeurs de contenu peuvent l'utiliser n'importe où — sur n'importe quelle page, dans n'importe quelle section — sans jamais toucher au code.
Configurer meta.json de la bonne manière
Avant de construire quoi que ce soit, configurez correctement votre module. Voici un fichier meta.json propre pour un module de Section Hero :
{% module_block module "widget_f4bdfa8e-ea55-4f41-8dd1-9887819bcbb6" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{\"label\": \"Section Hero\",
\"css_assets\": [],
\"external_js\": [],
\"global\": false,
\"help_text\": \"Une section hero flexible avec un titre, une description, une image et des boutons d'appel à l'action.\",
\"host_template_types\": [\"PAGE\", \"BLOG_LISTING\", \"BLOG_POST\"],
\"icon\": \"\",
\"is_available_for_new_content\": true,
\"js_assets\": [],
\"other_assets\": [],
\"smart_type\": \"NOT_SMART\",
\"categories\": [\"DESIGN\"]
}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Deux choses à noter ici. Premièrement, host_template_types contrôle où ce module peut être utilisé. Définissez-le sur PAGE pour les modules exclusifs aux pages, ou incluez BLOG_POST s'il doit également fonctionner dans les modèles de blog. Ne le laissez jamais ouvert pour les modèles d'e-mail si votre module utilise du CSS ou du JS — les e-mails ne les prennent pas en charge. Deuxièmement, ajoutez toujours un help_text (texte d'aide) significatif. Cela s'affiche dans le Gestionnaire de conception et aide votre équipe à comprendre ce que fait le module sans avoir à lire le code.
Construire une structure fields.json appropriée
Le fichier fields.json est l'endroit où la plupart des développeurs se trompent. Une liste plate de plus de 15 champs rend l'expérience d'édition pénible. Regrouper les champs liés crée une interface propre et intuitive.
Paramètres de la section — Chaque module en a besoin
Avant tout champ de contenu, chaque module devrait avoir un groupe de Paramètres de section. Cela donne aux éditeurs de contenu le contrôle sur l'ID de la section, les classes personnalisées et la visibilité :
{% module_block module "widget_ff116c3d-fc00-48bd-92ae-826d8ea6981b" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{\"id\": \"section_settings\",
\"name\": \"section_settings\",
\"label\": \"Paramètres de la section\",
\"type\": \"group\",
\"children\": [
{
\"id\": \"section_id\",
\"name\": \"section_id\",
\"label\": \"ID de la section\",
\"type\": \"text\",
\"help_text\": \"Ajoutez un ID unique pour les liens d'ancrage. Exemple : section-hero\",
\"default\": \"\"
},
{
\"id\": \"section_class\",
\"name\": \"section_class\",
\"label\": \"Classe CSS personnalisée\",
\"type\": \"text\",
\"help_text\": \"Ajoutez des classes Tailwind ou CSS personnalisées au conteneur de la section.\",
\"default\": \"\"
},
{
\"id\": \"section_visible\",
\"name\": \"section_visible\",
\"label\": \"Afficher la section\",
\"type\": \"boolean\",
\"help_text\": \"Désactivez pour masquer cette section sans supprimer son contenu.\",
\"default\": true
}
]
}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Pourquoi est-ce important ? Les éditeurs de contenu ont souvent besoin de masquer une section temporairement, d'ajouter un lien d'ancrage pour la navigation, ou d'appliquer une classe personnalisée pour un style spécial. Sans ces champs, ils doivent demander à un développeur pour chaque petit changement. Avec eux, ils sont autonomes.
Groupe de contenu — Titres avec contrôle SEO
Ne codez jamais votre balise de titre en dur. Fournissez toujours un champ de choix pour que les éditeurs puissent contrôler la hiérarchie SEO :
{% module_block module "widget_16486a8f-e38e-44aa-88b6-7181209c6a38" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{\"id\": \"content\",
\"name\": \"content\",
\"label\": \"Contenu\",
\"type\": \"group\",
\"children\": [
{
\"id\": \"heading\",
\"name\": \"heading\",
\"label\": \"Titre\",
\"type\": \"text\",
\"help_text\": \"Titre principal. Gardez-le sous 60 caractères pour de meilleurs résultats SEO.\",
\"default\": \"Construisez quelque chose d'incroyable\"
},
{
\"id\": \"heading_tag\",
\"name\": \"heading_tag\",
\"label\": \"Balise de titre\",
\"type\": \"choice\",
\"help_text\": \"N'utilisez H1 qu'une seule fois par page. Utilisez H2 pour tous les autres titres de section.\",
\"choices\": [
[\"h1\", \"H1 — Titre principal de la page\"],
[\"h2\", \"H2 — Titre de section\"],
[\"h3\", \"H3 — Titre de sous-section\"]
],
\"default\": \"h2\"
},
{
\"id\": \"description\",
\"name\": \"description\",
\"label\": \"Description\",
\"type\": \"textarea\",
\"help_text\": \"Texte de support sous le titre. 1 à 2 phrases recommandées.\",
\"default\": \"\"
}
]
}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Remarquez que la balise de titre par défaut est définie sur h2, et non h1. C'est intentionnel. La plupart des pages ne devraient avoir qu'un seul H1, et cela est généralement géré par le premier module. Chaque module suivant devrait être par défaut en H2. Si l'éditeur place ce module comme première section sur une page, il peut le passer en H1 lui-même.
Groupe de boutons — Utilisez des champs de lien, pas des CTA
Une erreur courante consiste à utiliser le module CTA de HubSpot pour chaque bouton. Les CTA sont puissants mais ils ajoutent une surcharge de suivi et ralentissent le chargement de la page lorsqu'ils sont trop utilisés. Pour la plupart des boutons, un simple champ de lien avec un champ de texte est tout ce dont vous avez besoin :
{% module_block module "widget_62e276d8-2110-47b4-bc76-e579c47cdd9d" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{\"id\": \"primary_button\",
\"name\": \"primary_button\",
\"label\": \"Bouton principal\",
\"type\": \"group\",
\"children\": [
{
\"id\": \"button_text\",
\"name\": \"button_text\",
\"label\": \"Texte du bouton\",
\"type\": \"text\",
\"default\": \"Commencer\"
},
{
\"id\": \"button_link\",
\"name\": \"button_link\",
\"label\": \"Lien du bouton\",
\"type\": \"link\",
\"default\": {
\"url\": { \"href\": \"#\", \"type\": \"EXTERNAL\" },
\"open_in_new_tab\": false,
\"no_follow\": false
}
}
]
}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Le type de champ lien donne automatiquement aux éditeurs des options pour l'URL, le nouvel onglet et le nofollow — tout cela sans aucun travail supplémentaire de votre part.
Conventions de nommage des champs
La façon dont vous nommez les champs a plus d'importance que vous ne le pensez. Les éditeurs de contenu voient ces étiquettes à chaque fois qu'ils modifient une page. Soyez précis :
- ❌ "Image" — quelle image ? Arrière-plan ? Profil ? Hero ?
- ✅ "Image d'arrière-plan du Hero" — instantanément clair
- ❌ "Bascule" — basculer quoi ?
- ✅ "Afficher la section" ou "Activer la superposition d'arrière-plan" — décrit exactement ce qu'elle contrôle
- ❌ "Texte" — chaque champ est du texte
- ✅ "Texte du bouton" ou "Sous-titre" — spécifique et évident
Ajoutez également un help_text (texte d'aide) à chaque champ. Une description de 10 mots maintenant vous épargne une conversation Slack de 10 minutes plus tard.
Écrire le module HTML + HubL
Maintenant, construisons le véritable module.html. C'est ici que tous les champs se rejoignent pour former un composant rendu.
Le module.html complet de la Section Hero
{% module_block module "widget_5e0ce1df-0d4c-4320-9cf3-87dc5cac9f58" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{%- if module.section_settings.section_visible -%}<section
{%- if module.section_settings.section_id %} id=\"{{ module.section_settings.section_id }}\"{% endif -%}
class=\"relative overflow-hidden {{ module.section_settings.section_class }}\"
>
<div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20 lg:py-24\">
<div class=\"grid grid-cols-1 lg:grid-cols-2 gap-12 items-center\">
<div class=\"flex flex-col gap-6\">
{%- if module.content.heading -%}
<{{ module.content.heading_tag }} class=\"text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight text-slate-900\">
{{- module.content.heading -}}
</{{ module.content.heading_tag }}>
{%- endif -%}
{%- if module.content.description -%}
<p class=\"text-lg text-slate-600 leading-relaxed max-w-xl\">
{{- module.content.description -}}
</p>
{%- endif -%}
{%- if module.primary_button.button_text -%}
<div class=\"flex flex-wrap gap-4 mt-2\">
<a
href=\"{{ module.primary_button.button_link.url.href }}\"
{%- if module.primary_button.button_link.open_in_new_tab %} target=\"_blank\" rel=\"noopener noreferrer\"{% endif -%}
class=\"inline-flex items-center px-8 py-4 text-base font-semibold text-white bg-blue-600 rounded-xl hover:bg-blue-700 transition-colors\"
>
{{- module.primary_button.button_text -}}
</a>
</div>
{%- endif -%}
</div>
{%- if module.hero_image.image.src -%}
<div class=\"relative\">
<img
src=\"{{ module.hero_image.image.src }}\"
alt=\"{{ module.hero_image.image.alt }}\"
width=\"{{ module.hero_image.image.width }}\"
height=\"{{ module.hero_image.image.height }}\"
loading=\"lazy\"
class=\"w-full h-auto rounded-2xl\"
>
</div>
{%- endif -%}
</div>
</div>
</section>
{%- endif -%}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Décomposons les modèles critiques utilisés dans ce code.
Contrôle des espaces blancs avec {%- -%}
Chaque balise HubL dans le code ci-dessus utilise la syntaxe du tiret : {%- -%} au lieu de {% %}. Ce simple changement fait une énorme différence dans votre code HTML rendu.
Sans les tirets, HubL insère des lignes vides partout où il traite une balise. Le code source de votre page se retrouve plein d'espaces blancs inutiles — des lignes vides entre chaque élément. Cela rend le HTML plus lourd, plus difficile à déboguer et légèrement plus lent à analyser.
Avec les tirets, HubL supprime proprement ces espaces blancs. Le HTML rendu est serré, minimal et exactement ce dont le navigateur a besoin. Sur une page avec plus de 20 modules, cela peut réduire considérablement la taille de votre fichier HTML.
Il en va de même pour la sortie des variables : utilisez {{- -}} au lieu de {{ }} pour éviter les espaces autour des valeurs dynamiques.
Balises de titre dynamiques
Le titre utilise directement la valeur du champ comme balise HTML :
{% module_block module "widget_df0dfdbf-e8c7-44e9-834b-06fa4201b6ab" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"<{{ module.content.heading_tag }}>{{- module.content.heading -}}
</{{ module.content.heading_tag }}>"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Si l'éditeur sélectionne "H2" dans la liste déroulante, cela se rend comme une véritable balise <h2>. S'il sélectionne "H1", cela se rend comme <h1>. L'éditeur a un contrôle SEO total sans avoir besoin d'un développeur.
Rendu conditionnel
Chaque section de contenu est enveloppée dans une vérification if (si). Si le champ de titre est vide, aucune balise <h2> n'est rendue. Si le texte du bouton est vide, aucun bouton n'apparaît. Si l'image n'a pas de source, la colonne de l'image disparaît entièrement.
Cela empêche les éléments HTML vides d'apparaître sur la page — pas de mises en page cassées, pas de div vides prenant de la place, pas de problèmes d'accessibilité dus à des balises de titre vides.
Meilleures pratiques pour les images HubSpot
Lors de l'utilisation du type de champ image de HubSpot, affichez toujours les valeurs du champ directement — src, alt, width et height. Le champ image de HubSpot est déjà optimisé pour le SEO. Il fournit des attributs d'image réactifs et une gestion appropriée du texte alternatif (alt) dès le départ.
Ne remplacez pas ces valeurs par des attributs codés en dur. Ajoutez simplement loading="lazy" pour les images situées sous la ligne de flottaison afin d'améliorer les performances de la page.
Utilisation de macros pour des paramètres de section réutilisables
Si chaque module a besoin de paramètres de section (ID, classe, visibilité), vous ne devriez pas copier ce code dans chaque module.html. Créez plutôt un fichier de macro une seule fois et importez-le partout.
Créez macros/section-macros.html dans votre thème
{% module_block module "widget_b70b9ee1-e86b-4ada-bb4a-1be2c9530aa8" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{%- macro section_attrs(settings) -%}{%- if settings.section_id %} id=\"{{ settings.section_id }}\"{% endif -%}
{%- if settings.section_class %} class=\"{{ settings.section_class }}\"{% endif -%}
{%- endmacro -%}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Importez et utilisez dans n'importe quel module
{% module_block module "widget_7de05492-5eb2-48af-ae1d-3df276cf0dc6" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"{%- import '../macros/section-macros.html' as section_macros -%}{%- if module.section_settings.section_visible -%}
<section {{ section_macros.section_attrs(module.section_settings) }}>
{# Contenu du module ici #}
</section>
{%- endif -%}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Écrivez-le une fois. Importez-le dans 50 modules. Lorsque vous devez modifier le fonctionnement des ID de section, mettez à jour un seul fichier et chaque module reçoit la mise à jour. C'est ainsi que sont construits les thèmes HubSpot professionnels.
Stratégie CSS — Arrêtez d'écrire du CSS de module
Cela pourrait être la section la plus importante de tout ce guide. La plupart des développeurs HubSpot écrivent du CSS à l'intérieur du fichier module.css de chaque module. Cela crée un désordre — des styles dupliqués à travers les modules, un espacement incohérent, des tailles de fichiers croissantes et des pages qui se chargent plus lentement à chaque nouveau module.
Utilisez plutôt les classes utilitaires Tailwind CSS
Regardez le module.html ci-dessus. Il n'y a aucun CSS personnalisé. Chaque style est appliqué via des classes utilitaires Tailwind directement dans le HTML :
- max-w-7xl mx-auto px-4 — conteneur avec largeur maximale, centré, rembourrage horizontal
- grid grid-cols-1 lg:grid-cols-2 gap-12 — grille réactive à deux colonnes
- text-4xl sm:text-5xl lg:text-6xl font-bold — taille de titre réactive
- hover:bg-blue-700 transition-colors — effet de survol avec transition douce
Avantages de cette approche :
- Un seul fichier CSS pour tout le thème — pas 50 fichiers module.css séparés
- Minifié et purgé — seules les classes que vous utilisez réellement sont incluses
- Système de conception cohérent — chaque module utilise la même échelle d'espacement, la même palette de couleurs et les mêmes points de rupture
- Meilleur contraste des couleurs — la palette par défaut de Tailwind est conçue en gardant à l'esprit les normes d'accessibilité WCAG AA
- N'importe quel développeur peut le lire — pas besoin de fouiller dans les feuilles de style pour comprendre ce que fait une classe
Quand vous avez réellement besoin de module.css
Le seul moment pour écrire du module.css est pour des choses que Tailwind ne peut véritablement pas gérer — typiquement des animations personnalisées ou des modèles de pseudo-éléments complexes :
{% module_block module "widget_efa8a519-a334-49ca-9010-cdfc812c53a1" %}{% module_attribute "child_css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "code_block" is_json="true" %}"@keyframes fadeInUp {from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.hero-animate {
animation: fadeInUp 0.6s ease-out;
}"{% end_module_attribute %}{% module_attribute "css" is_json="true" %}null{% end_module_attribute %}{% module_attribute "label" is_json="true" %}null{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}321957934793{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}2{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}"module"{% end_module_attribute %}{% end_module_block %}
Tout le reste devrait se trouver dans le CSS global de votre thème ou être géré par des utilitaires Tailwind. Point final.
JavaScript — Seulement quand vous le devez
La même règle s'applique à module.js. La plupart des modules n'ont pas du tout besoin de JavaScript.
Les modules qui n'ont pas besoin de JS : sections hero, blocs de texte et d'image, grilles de fonctionnalités, cartes de témoignages, tableaux de prix, sections de pied de page. Ceux-ci sont purement visuels — le HTML et le CSS gèrent tout.
Les modules qui ont besoin de JS : accordéons, carrousels/sliders, composants d'onglets, fenêtres modales (popups), validation de formulaires, animations déclenchées par le défilement.
Lorsque vous écrivez du JavaScript, gardez-le "vanilla" (sans dépendances). Pas de jQuery en 2026. HubSpot charge module.js une seule fois par type de module, même si le module apparaît plusieurs fois sur une page — mais cela ajoute quand même au poids de votre page. Soyez intentionnel pour chaque script que vous incluez.
Contraste des couleurs et accessibilité
Google prend en compte les signaux d'accessibilité dans les classements de recherche. Construire des modules accessibles n'est pas seulement une bonne pratique — cela impacte directement votre SEO.
Si vous utilisez Tailwind CSS, vous avez déjà un avantage. La palette de couleurs par défaut de Tailwind est conçue avec des ratios de contraste appropriés. Tenez-vous-en à ces paires sûres :
- text-slate-900 sur bg-white — ratio de contraste 15.4:1 (passe AAA)
- text-white sur bg-slate-900 — ratio de contraste 15.4:1 (passe AAA)
- text-slate-700 sur bg-slate-50 — ratio de contraste 8.1:1 (passe AAA)
Évitez le texte clair sur des fonds clairs. Un ratio de contraste inférieur à 4.5:1 échoue au WCAG AA et peut nuire à vos classements de recherche.
Liste de contrôle d'accessibilité des modules
- Chaque image a un attribut alt significatif provenant du champ image de HubSpot
- La hiérarchie des titres est logique — H1 suivi de H2, sans jamais sauter directement à H4
- Les liens ont un texte descriptif — "Lire le guide complet" et non "Cliquez ici"
- Les éléments interactifs utilisent des balises HTML appropriées — <a> pour les liens, <button> pour les actions
- La couleur seule ne transmet jamais le sens — associez toujours la couleur à du texte ou des icônes
Tester vos modules
Avant de publier un module, parcourez cette liste de contrôle :
- Prévisualisez le module dans l'aperçu du Gestionnaire de conception de HubSpot
- Testez sur une vraie page avec du vrai contenu — pas seulement du faux texte
- Vérifiez les quatre points de rupture : mobile (320px), tablette (768px), ordinateur portable (1024px), bureau (1440px)
- Vérifiez qu'un seul H1 existe sur la page lorsque ce module est présent
- Testez avec des champs vides — la mise en page a-t-elle toujours l'air propre ?
- Testez avec un contenu très long — le titre revient-il à la ligne correctement ?
- Exécutez un audit Lighthouse pour les scores de Performance, d'Accessibilité et de SEO
- Affichez le code source de la page — y a-t-il des lignes vides inutiles ou des éléments vides ?
Erreurs courantes qui nuisent à vos modules
Écrire du CSS dans chaque module. Cela crée des styles dupliqués et des chargements de page plus lourds. Utilisez les classes utilitaires Tailwind ou écrivez du CSS global dans la feuille de style de votre thème. Le module CSS devrait être votre dernier recours.
Ajouter du JavaScript inutilement. Les modules de contenu statique comme les sections hero, les grilles de fonctionnalités et les témoignages n'ont pas besoin de JavaScript. Chaque script ajoute au poids de la page.
Coder en dur les balises de titre. Si vous écrivez <h2> directement dans votre HTML, les éditeurs de contenu ne peuvent pas contrôler la hiérarchie SEO. Utilisez toujours un champ de choix et rendez la balise dynamiquement.
Ignorer les espaces blancs HubL. L'utilisation de {% %} au lieu de {%- -%} remplit votre HTML rendu de lignes vides. La syntaxe du tiret supprime les espaces blancs et produit une sortie plus propre et plus légère.
Listes de champs plates sans groupes. Vingt champs non regroupés dans l'éditeur de page sont un cauchemar pour les éditeurs de contenu. Regroupez les champs liés — Contenu, Image, Bouton, Paramètres de la section — afin que l'interface soit propre et facile à naviguer.
Ignorer les paramètres de la section. Sans un champ d'ID, les éditeurs ne peuvent pas créer de liens d'ancrage. Sans une bascule de visibilité, ils ne peuvent pas masquer une section temporairement. Sans un champ de classe personnalisée, ils ont besoin d'un développeur pour chaque ajustement de style. Ajoutez ces trois champs à chaque module comme pratique standard.
Remplacer l'extrait d'image de HubSpot. Le type de champ image de HubSpot génère déjà une sortie optimisée pour le SEO avec les bons attributs src, alt, width, height et réactifs. Ne remplacez pas cela par du code personnalisé — affichez simplement les valeurs du champ directement et ajoutez loading="lazy" lorsque c'est approprié.
Utiliser des CTA pour chaque bouton. Les CTA HubSpot ont une surcharge de suivi. Pour des boutons simples qui renvoient vers une page, utilisez plutôt une balise d'ancrage avec un champ de texte et un champ de lien. Réservez les CTA pour les boutons qui nécessitent véritablement un suivi et des analyses.
En conclusion
La construction de modules personnalisés dans HubSpot ne consiste pas seulement à faire en sorte que les choses aient l'air bien — il s'agit de construire des composants rapides, accessibles, optimisés pour le SEO et faciles à utiliser pour les éditeurs de contenu.
Les techniques couvertes dans ce guide — champs regroupés, balises de titre dynamiques, contrôle des espaces blancs HubL, classes utilitaires Tailwind, macros réutilisables et gestion appropriée des images — sont ce qui sépare le développement professionnel HubSpot du travail d'amateur.
Commencez à appliquer ces pratiques à votre prochain module. Vos éditeurs de contenu vous remercieront, vos pages se chargeront plus rapidement et vos scores SEO s'amélioreront.
Construire des modules HubSpot à partir de zéro prend du temps. Rapid vous permet de télécharger n'importe quelle capture d'écran d'interface utilisateur et génère un module HubSpot complet, prêt pour la production — avec fields.json, les liaisons HubL et une structure appropriée — en moins de 60 secondes. Essayez-le gratuitement →