This is a module for the top of the page (the "first view") that defines the first impression of a product or service.Purpose of UseTo be used when you want to simply place a powerful catchphrase and a call-to-action (CTA) over a background image in the first view. It is ideal for quickly setting up the common elements of a hero section.
This is a module for the top of the page (the "first view") that defines the first impression of a product or service.
Image field
(for the background), a Text field
(for the catchphrase), a Rich text field
(for the description), a CTA field
(for the button), a Text field
(for the button's supplementary text), and a Choice field
(for text alignment on PC).The following settings can be configured from the field settings of HubSpot's module settings. Please configure each from the field settings.
You can set any value for the label name, but please use the specified values for the "name" and "type".
①HubL variable name : background_image
field type : image
②text_alignment
HubL variable name :text_alignment
field type : Choice
Choices : left,center,right
③HubL variable name :horizontal_position
field type : number
④HubL variable name :vertical_position
field type : number
⑤HubL variable name :main_headline
field type : text
⑥HubL variable name :description
field type : rich text
⑦HubL variable name :show_cta_bubble
field type : boolean
⑧HubL variable name :cta_text
field type : text
HubL variable name :button_label
field type : text
HubL variable name :button_link
field type : link
<section class="sales-hero"
style="background-image: url('{{ module.background_image.src }}');"
data-module-id="{{ module_id }}"
data-horizontal-position="{{ module.horizontal_position or 50 }}"
data-vertical-position="{{ module.vertical_position or 50 }}">
<div class="hero-container"
style="--horizontal-position: {{ module.horizontal_position or 50 }}%; --vertical-position: {{ module.vertical_position or 50 }}%;">
<div class="hero-content hero-content--{{ module.text_alignment or 'center' }}">
<h1 class="company-name">{{ module.company_name }}</h1>
<h2 class="main-headline">{{ module.main_headline }}</h2>
<div class="description">
{% inline_rich_text field="description" value="{{ module.description }}" %}
</div>
<div class="cta-section">
{% if module.show_cta_bubble and module.cta_text %}
<div class="cta-bubble">
<p class="cta-text">{{ module.cta_text }}</p>
</div>
{% endif %}
<a href="{{ module.button_link }}" class="cta-button">
<span class="button-text">{{ module.button_label }}</span>
</a>
</div>
</div>
</div>
</section>
{{ require_css("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css") }}
/* ==================================
Sales Hero Module Styles
================================== */
.sales-hero {
position: relative;
min-height: 600px;
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
background-attachment: scroll;
color: white;
overflow: hidden;
}
/* Main Container */
.hero-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
padding: 80px 20px;
width: 100%;
height: 100%;
}
.hero-container::before {
content: '';
position: absolute;
top: var(--vertical-position, 50%);
left: var(--horizontal-position, 50%);
transform: translate(-50%, -50%);
width: 1px;
height: 1px;
z-index: 1;
}
/* ==================================
Content Section
================================== */
.hero-content {
position: absolute;
top: var(--vertical-position, 50%);
left: var(--horizontal-position, 50%);
transform: translate(-50%, -50%);
max-width: 600px;
min-width: 300px;
z-index: 3;
}
/* Text Alignment Options */
.hero-content--left {
text-align: left;
}
.hero-content--center {
text-align: center;
}
.hero-content--right {
text-align: right;
}
/* Company Name */
.company-name {
font-size: 38px;
font-weight: 700;
margin: 0 0 15px 0;
color: white;
font-family: 'Helvetica Neue', Arial, sans-serif;
letter-spacing: -0.5px;
animation: fadeInUp 0.8s ease-out;
}
/* Main Headline */
.main-headline {
font-size: 42px;
font-weight: 700;
margin: 0 0 25px 0;
line-height: 1.3;
color: white;
font-family: 'Helvetica Neue', Arial, sans-serif;
letter-spacing: -0.5px;
animation: fadeInUp 0.8s ease-out 0.2s both;
}
/* Description */
.description {
font-size: 18px;
line-height: 1.7;
margin: 0 0 50px 0;
opacity: 0.95;
font-weight: 400;
animation: fadeInUp 0.8s ease-out 0.4s both;
}
/* Rich text elements styling */
.description p {
margin-bottom: 1em;
}
.description strong {
font-weight: 700;
}
.description em {
font-style: italic;
}
/* ==================================
CTA Section
================================== */
.cta-section {
position: relative;
animation: fadeInUp 0.8s ease-out 0.6s both;
display: flex;
flex-direction: column;
}
/* Alignment for CTA section */
.hero-content--left .cta-section {
align-items: flex-start;
}
.hero-content--center .cta-section {
align-items: center;
}
.hero-content--right .cta-section {
align-items: flex-end;
}
/* CTA Bubble */
.cta-bubble {
background: #FFD700;
color: #333;
padding: 15px 22px;
border-radius: 25px;
margin-bottom: 20px;
position: relative;
max-width: 350px;
box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3);
}
.cta-bubble::after {
content: '';
position: absolute;
bottom: -10px;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #FFD700;
}
/* Bubble arrow positioning based on alignment */
.hero-content--left .cta-bubble::after {
left: 35px;
}
.hero-content--center .cta-bubble::after {
left: 50%;
transform: translateX(-50%);
}
.hero-content--right .cta-bubble::after {
right: 35px;
}
.cta-text {
margin: 0;
font-size: 15px;
font-weight: 600;
line-height: 1.4;
}
/* CTA Button */
.cta-button {
display: inline-flex;
align-items: center;
justify-content: center;
background: white;
color: #0066CC;
padding: 18px 35px;
border-radius: 10px;
text-decoration: none;
font-weight: 700;
font-size: 16px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
border: none;
cursor: pointer;
font-family: inherit;
min-width: 200px;
}
.cta-button:hover {
transform: translateY(-3px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
text-decoration: none;
color: #004499;
background: #f8f9ff;
}
.cta-button:active {
transform: translateY(-1px);
transition: all 0.1s;
}
.button-text {
font-size: 16px;
}
/* ==================================
Animations
================================== */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ==================================
Responsive Design
================================== */
/* Tablet Styles */
@media (max-width: 1024px) {
.hero-container {
padding: 60px 30px;
}
.hero-content {
max-width: 550px;
min-width: 280px;
}
.main-headline {
font-size: 36px;
}
.company-name {
font-size: 34px;
}
}
/* Mobile Styles */
@media (max-width: 768px) {
.sales-hero {
min-height: 500px;
}
.hero-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: auto;
min-height: 500px;
padding: 40px 20px;
}
/* Override position on mobile for better UX */
.hero-content {
position: relative !important;
top: auto !important;
left: auto !important;
transform: none !important;
max-width: 100%;
min-width: auto;
text-align: center !important;
}
.hero-content .cta-section {
align-items: center !important;
}
.hero-content .cta-bubble::after {
left: 50% !important;
right: auto !important;
transform: translateX(-50%) !important;
}
.main-headline {
font-size: 32px;
margin-bottom: 20px;
}
.company-name {
font-size: 30px;
}
.description {
font-size: 16px;
margin-bottom: 35px;
}
.cta-bubble {
max-width: 100%;
margin-bottom: 15px;
}
.cta-button {
padding: 16px 28px;
font-size: 15px;
min-width: 180px;
}
}
/* Small Mobile Styles */
@media (max-width: 480px) {
.hero-container {
padding: 30px 15px;
}
.main-headline {
font-size: 28px;
line-height: 1.4;
}
.company-name {
font-size: 26px;
}
.description {
font-size: 15px;
}
.cta-text {
font-size: 14px;
}
.cta-button {
padding: 14px 24px;
font-size: 14px;
min-width: 160px;
}
}
/* ==================================
Optimizations & Accessibility
================================== */
/* High-DPI Display Optimization */
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min--moz-device-pixel-ratio: 2),
only screen and (-o-min-device-pixel-ratio: 2/1),
only screen and (min-device-pixel-ratio: 2),
only screen and (min-resolution: 192dpi),
only screen and (min-resolution: 2dppx) {
.sales-hero {
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
}
}
/* Accessibility Enhancements */
@media (prefers-reduced-motion: reduce) {
.sales-hero *,
.sales-hero *::before,
.sales-hero *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Focus Styles for Accessibility */
.cta-button:focus {
outline: 3px solid #FFD700;
outline-offset: 2px;
}
/**
* Sales Hero Module JavaScript
* HubSpot Custom Module Enhancement Script
*/
(function() {
'use strict';
// Module initialization
const SalesHero = {
// Configuration
config: {
animationDelay: 100,
observerThreshold: 0.1,
buttonHoverDelay: 150
},
// Initialize the module
init: function() {
this.setupIntersectionObserver();
this.enhanceButtons();
this.trackAnalytics();
this.setupAccessibility();
// Wait for DOM to be fully loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', this.onDOMReady.bind(this));
} else {
this.onDOMReady();
}
},
// DOM Ready handler
onDOMReady: function() {
this.optimizePerformance();
console.log('Sales Hero Module: Initialized successfully');
},
// Setup Intersection Observer for animation triggers
setupIntersectionObserver: function() {
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
observer.unobserve(entry.target);
}
});
}, {
threshold: this.config.observerThreshold,
rootMargin: '0px 0px -50px 0px'
});
// Observe hero sections
const heroSections = document.querySelectorAll('.sales-hero');
heroSections.forEach(section => {
observer.observe(section);
});
}
},
// Enhance CTA buttons with advanced interactions
enhanceButtons: function() {
const ctaButtons = document.querySelectorAll('.cta-button');
ctaButtons.forEach(button => {
// Add ripple effect on click
button.addEventListener('click', this.createRippleEffect.bind(this));
// Enhanced hover effects
button.addEventListener('mouseenter', this.onButtonHover.bind(this));
button.addEventListener('mouseleave', this.onButtonLeave.bind(this));
// Keyboard navigation enhancement
button.addEventListener('focus', this.onButtonFocus.bind(this));
button.addEventListener('blur', this.onButtonBlur.bind(this));
});
},
// Create ripple effect for button clicks
createRippleEffect: function(e) {
const button = e.currentTarget;
const rect = button.getBoundingClientRect();
const ripple = document.createElement('span');
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
width: ${size}px;
height: ${size}px;
left: ${x}px;
top: ${y}px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
z-index: 1;
`;
// Add ripple animation CSS if not exists
if (!document.getElementById('ripple-styles')) {
const style = document.createElement('style');
style.id = 'ripple-styles';
style.textContent = `
@keyframes ripple {
to {
transform: scale(2);
opacity: 0;
}
}
.cta-button {
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
}
button.appendChild(ripple);
// Remove ripple after animation
setTimeout(() => {
if (ripple.parentNode) {
ripple.parentNode.removeChild(ripple);
}
}, 600);
},
// Button hover handler
onButtonHover: function(e) {
const button = e.currentTarget;
const icon = button.querySelector('i');
if (icon) {
setTimeout(() => {
icon.style.transform = 'translateX(5px) scale(1.1)';
}, this.config.buttonHoverDelay);
}
},
// Button leave handler
onButtonLeave: function(e) {
const button = e.currentTarget;
const icon = button.querySelector('i');
if (icon) {
icon.style.transform = 'translateX(0) scale(1)';
}
},
// Button focus handler for accessibility
onButtonFocus: function(e) {
const button = e.currentTarget;
button.style.boxShadow = '0 0 0 3px rgba(255, 215, 0, 0.5), 0 10px 30px rgba(0, 0, 0, 0.25)';
},
// Button blur handler
onButtonBlur: function(e) {
const button = e.currentTarget;
button.style.boxShadow = '0 6px 20px rgba(0, 0, 0, 0.15)';
},
// Performance optimizations
optimizePerformance: function() {
// Preload critical background images
this.preloadCriticalImages();
// Setup passive event listeners where appropriate
this.setupPassiveListeners();
// Debounce resize events
let resizeTimeout;
window.addEventListener('resize', () => {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(this.onWindowResize.bind(this), 250);
});
},
// Preload critical images
preloadCriticalImages: function() {
const heroSection = document.querySelector('.sales-hero');
if (heroSection) {
const bgImage = window.getComputedStyle(heroSection).backgroundImage;
const imageUrl = bgImage.replace(/url\\(['"]?(.*?)['"]?\\)/i, '$1');
if (imageUrl && imageUrl !== 'none') {
const img = new Image();
img.src = imageUrl;
}
}
},
// Setup passive event listeners for better performance
setupPassiveListeners: function() {
const heroSection = document.querySelector('.sales-hero');
if (heroSection) {
heroSection.addEventListener('touchstart', function() {}, {
passive: true
});
heroSection.addEventListener('touchmove', function() {}, {
passive: true
});
}
},
// Window resize handler
onWindowResize: function() {
// Recalculate any dynamic positioning if needed
const ctaBubbles = document.querySelectorAll('.cta-bubble');
ctaBubbles.forEach(bubble => {
if (window.innerWidth <= 768) {
// Mobile adjustments for bubble positioning
bubble.style.maxWidth = '100%';
} else {
bubble.style.maxWidth = '350px';
}
});
},
// Analytics tracking
trackAnalytics: function() {
const ctaButtons = document.querySelectorAll('.cta-button');
ctaButtons.forEach((button, index) => {
button.addEventListener('click', (e) => {
// HubSpot Analytics tracking
if (typeof _hsq !== 'undefined') {
_hsq.push(['trackEvent', {
eventId: 'sales_hero_cta_click',
value: button.href || button.getAttribute('data-href'),
buttonText: button.textContent.trim(),
modulePosition: index
}]);
}
// Google Analytics tracking (if available)
if (typeof gtag !== 'undefined') {
gtag('event', 'click', {
'event_category': 'Sales Hero Module',
'event_label': button.textContent.trim(),
'value': index
});
}
// Custom analytics tracking
this.sendCustomAnalytics('cta_click', {
buttonText: button.textContent.trim(),
buttonUrl: button.href,
timestamp: new Date().toISOString(),
moduleId: button.closest('.sales-hero').getAttribute('data-module-id')
});
});
});
// Track module visibility
this.trackModuleVisibility();
},
// Send custom analytics
sendCustomAnalytics: function(event, data) {
// Only send if custom tracking is enabled
if (window.salesHeroAnalytics && window.salesHeroAnalytics.enabled) {
const payload = {
event: event,
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent,
...data
};
// Send to custom endpoint if configured
if (window.salesHeroAnalytics.endpoint) {
fetch(window.salesHeroAnalytics.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
}).catch(err => {
console.warn('Sales Hero Analytics: Failed to send data', err);
});
}
}
},
// Track module visibility for engagement metrics
trackModuleVisibility: function() {
if ('IntersectionObserver' in window) {
const visibilityObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const moduleId = entry.target.getAttribute('data-module-id');
// Track module view
if (typeof _hsq !== 'undefined') {
_hsq.push(['trackEvent', {
eventId: 'sales_hero_module_viewed',
moduleId: moduleId
}]);
}
this.sendCustomAnalytics('module_viewed', {
moduleId: moduleId,
visibilityRatio: entry.intersectionRatio
});
visibilityObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.5,
rootMargin: '0px'
});
const heroSections = document.querySelectorAll('.sales-hero[data-module-id]');
heroSections.forEach(section => {
visibilityObserver.observe(section);
});
}
},
// Setup accessibility enhancements
setupAccessibility: function() {
const heroSections = document.querySelectorAll('.sales-hero');
heroSections.forEach(section => {
// Add proper ARIA labels
section.setAttribute('role', 'banner');
section.setAttribute('aria-label', 'Hero section with call-to-action');
// Enhance CTA buttons
const ctaButton = section.querySelector('.cta-button');
if (ctaButton) {
// Add ARIA attributes
ctaButton.setAttribute('role', 'button');
// Add descriptive text for screen readers
const buttonText = ctaButton.querySelector('.button-text');
const icon = ctaButton.querySelector('i');
if (buttonText && icon) {
const ariaLabel = `${buttonText.textContent.trim()}, opens in ${ctaButton.target === '_blank' ? 'new tab' : 'same tab'}`;
ctaButton.setAttribute('aria-label', ariaLabel);
}
// Add keyboard navigation support
ctaButton.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
ctaButton.click();
}
});
}
// Ensure images have proper alt text
const images = section.querySelectorAll('img');
images.forEach(img => {
if (!img.alt || img.alt.trim() === '') {
console.warn('Sales Hero Module: Image missing alt text', img.src);
img.setAttribute('role', 'presentation');
}
});
// Add skip link for keyboard users
this.addSkipLink(section);
});
},
// Add skip link for accessibility
addSkipLink: function(section) {
const skipLink = document.createElement('a');
skipLink.href = '#content-after-hero';
skipLink.textContent = 'Skip to main content';
skipLink.className = 'skip-link';
skipLink.style.cssText = `
position: absolute;
top: -40px;
left: 6px;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
z-index: 1000;
border-radius: 4px;
font-size: 14px;
transition: top 0.3s;
`;
skipLink.addEventListener('focus', function() {
this.style.top = '6px';
});
skipLink.addEventListener('blur', function() {
this.style.top = '-40px';
});
section.insertBefore(skipLink, section.firstChild);
},
// Error handling and fallbacks
handleErrors: function() {
window.addEventListener('error', (e) => {
if (e.target.tagName === 'IMG' && e.target.closest('.sales-hero')) {
console.warn('Sales Hero Module: Image error handled', e.target.src);
e.target.style.display = 'none';
}
});
},
// Module cleanup (useful for SPA applications)
cleanup: function() {
// Remove event listeners to prevent memory leaks
const ctaButtons = document.querySelectorAll('.cta-button');
ctaButtons.forEach(button => {
button.replaceWith(button.cloneNode(true));
});
console.log('Sales Hero Module: Cleaned up successfully');
},
// Development helpers
debug: function() {
if (window.location.search.includes('hero-debug=true')) {
const debugInfo = {
modules: document.querySelectorAll('.sales-hero').length,
buttons: document.querySelectorAll('.cta-button').length,
images: document.querySelectorAll('.sales-hero img').length,
hasIntersectionObserver: 'IntersectionObserver' in window,
performance: performance.now()
};
console.table(debugInfo);
// Add visual debug indicators
document.querySelectorAll('.sales-hero').forEach((section, index) => {
const debugBadge = document.createElement('div');
debugBadge.textContent = `Hero Module ${index + 1}`;
debugBadge.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: red;
color: white;
padding: 5px 10px;
font-size: 12px;
z-index: 9999;
border-radius: 3px;
`;
section.appendChild(debugBadge);
});
}
}
};
// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
SalesHero.init();
SalesHero.debug();
});
} else {
SalesHero.init();
SalesHero.debug();
}
// Expose module for external access
window.SalesHeroModule = SalesHero;
// Handle page visibility changes (for analytics)
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
SalesHero.sendCustomAnalytics('page_hidden', {
timeOnPage: performance.now()
});
} else {
SalesHero.sendCustomAnalytics('page_visible', {
returnTime: performance.now()
});
}
});
})();
We can customize this sample to match your specific business requirements.
Book Free ConsultationThe Department Classification Library is an AI-powered automatic classification tool that runs in the Google Apps Script environment. It uses ChatGPT or Gemini to automatically classify company department names into predefined business segments.
This module is designed to visually showcase the features of a product or service by arranging images and text in an alternating layout. It uses scroll-triggered animations to engage users.
Learn how to implement a custom "Animated Counter" module in HubSpot to visually highlight your company's achievements and KPIs. This guide provides the complete HTML, CSS, JavaScript, and field configuration, allowing you to create a module that is intuitive even for non-developers.
This guide explains how to use "PhoneFormatter," a convenient Google Apps Script (GAS) library that allows you to batch-format international phone numbers in a Google Sheet. Easily convert numbers into their proper, hyphenated format simply by providing a country name in English, Japanese, or even abbreviated form.
Do you ever face the tedious task of managing address lists from various countries like Japan, the USA, and the UK in Google Sheets, wishing you could easily separate them by country, state, or city?
This article introduces "AddressParserLibrary," a Google Apps Script library that automates this data cleaning and parsing process with a single click.
Once you add the library, anyone can easily implement address parsing by making minor adjustments to the provided sample code. We will walk through everything from setup to execution in a step-by-step guide that is clear even for those unfamiliar with programming. Start boosting your daily productivity today!