GHL Experts

How to Add a Hero Banner Section to GoHighLevel Membership Library Pages

Add a customizable hero section with headline, subheadline, background image, and CTA button to your GoHighLevel membership library page using this JavaScript snippet.

December 6, 2020
7 min read

Why Add a Hero Section to Your GHL Membership Library

The library page in a GoHighLevel membership site is the first thing members see after logging in. It lists all available courses, categories, or content collections. Out of the box, the library page jumps straight into the content grid with no visual introduction, no branding opportunity, and no space for messaging.

A hero banner section at the top of the library page changes that. It gives you a place to welcome members, reinforce your brand, highlight new content, or drive a specific action with a call-to-action button. This is the kind of above-the-fold treatment that every modern content platform uses, and you can add it to your GHL membership site with a single JavaScript snippet.

This script works with all GoHighLevel membership themes. It targets the library page specifically and injects a fully customizable hero section above the content grid.

The Complete Code

Paste this script into your membership site's Custom JS field.

1// ****** Hero banner image start ********
2(function () {
3 const heroBanner = {
4 fontFamily: '"Roboto",sans-serif',
5 headline: "Test Headline",
6 subheadline: "Test Sub Headline",
7 bgImg: "https://assets.cdn.msgsndr.com/vJVPkXKI0ujMBULtlF3Q/media/63748e632a169ca47e3d9c3e.png",
8 minHeight: "300px",
9 button: {
10 id: "cm-hero-btn",
11 name: "See More",
12 style: "fill",
13 actionURL: "https://www.youtube.com",
14 },
15 };
16
17 const customHeroStyleSheet = `
18 :root {
19 --cm-hero-min-height: 300px;
20 --cm-container-max-width: 1080px;
21 --cm-hero-background-img: url(${heroBanner.bgImg});
22 --cm-hero-font-family: ${heroBanner.fontFamily};
23 --custom-headline-font-size: 40px;
24 --custom-headline-font-color: #000;
25 --custom-headline-font-weight: 700;
26 --custom-subheadline-font-size: 30px;
27 --custom-subheadline-font-color: #000;
28 --custom-subheadline-font-weight: 700;
29 --custom-cm-btn-border-radius: 5px;
30 --custom-cm-btn-padding: 10px 25px;
31 --custom-cm-btn-font-size: 16px;
32 --custom-cm-btn-font-weight: 700;
33 --custom-cm-btn-background-color: rgb(24, 15, 120);
34 --custom-cm-btn-font-color: #fff;
35 --custom-cm-outline-btn-background-color: transparent;
36 --custom-cm-outline-btn-font-color: rgb(24, 15, 120);
37 --custom-cm-btn-outline-border: 1px solid rgb(24, 15, 120);
38 --transition-all: all 0.3s ease-in;
39 }
40
41 .cm-hero {
42 width: 100% !important;
43 height: auto !important;
44 min-height: var(--cm-hero-min-height) !important;
45 display: flex !important;
46 align-items: center !important;
47 background-image: var(--cm-hero-background-img) !important;
48 background-position: center center !important;
49 background-repeat: no-repeat !important;
50 background-size: cover !important;
51 }
52
53 .cm-hero .cm-hero-con {
54 width: 100% !important;
55 max-width: 1080px !important;
56 margin-left: auto !important;
57 margin-right: auto !important;
58 padding: 24px !important;
59 }
60
61 .cm-hero .cm-hero-headline {
62 font-size: 40px !important;
63 font-weight: 700 !important;
64 color: #000 !important;
65 line-height: 1.2 !important;
66 font-family: var(--cm-hero-font-family) !important;
67 margin-top: 0 !important;
68 margin-bottom: 0 !important;
69 text-align: center !important;
70 }
71
72 .cm-hero .cm-hero-subheadline {
73 font-size: 30px !important;
74 font-weight: 400 !important;
75 color: #000 !important;
76 line-height: 1.4 !important;
77 font-family: var(--cm-hero-font-family) !important;
78 margin-top: 10px !important;
79 text-align: center !important;
80 margin-bottom: 0 !important;
81 }
82
83 .cm-hero .cm-hero-btn-con {
84 text-align: center !important;
85 margin-top: 30px !important;
86 }
87
88 .cm-hero .cm-hero-btn {
89 display: inline-flex !important;
90 padding: var(--custom-cm-btn-padding) !important;
91 align-items: center !important;
92 justify-content: center !important;
93 text-align: center !important;
94 font-size: var(--custom-cm-btn-font-size) !important;
95 font-weight: var(--custom-cm-btn-font-weight) !important;
96 border-radius: var(--custom-cm-btn-border-radius) !important;
97 text-decoration: none !important;
98 transition: var(--transition-all) !important;
99 }
100
101 .cm-hero .cm-hero-btn.fill {
102 background-color: var(--custom-cm-btn-background-color) !important;
103 color: var(--custom-cm-btn-font-color) !important;
104 border: 1px solid transparent !important;
105 }
106
107 .cm-hero .cm-hero-btn.fill:hover {
108 background-color: var(--custom-cm-outline-btn-background-color) !important;
109 color: var(--custom-cm-outline-btn-font-color) !important;
110 border: var(--custom-cm-btn-outline-border) !important;
111 }
112
113 .cm-hero .cm-hero-btn.outline {
114 background-color: var(--custom-cm-outline-btn-background-color) !important;
115 color: var(--custom-cm-outline-btn-font-color) !important;
116 border: var(--custom-cm-btn-outline-border) !important;
117 }
118
119 .cm-hero .cm-hero-btn.outline:hover {
120 background-color: var(--custom-cm-btn-background-color) !important;
121 color: var(--custom-cm-btn-font-weight) !important;
122 }
123 `;
124
125 const head = document.querySelector("head");
126 const style = document.createElement("style");
127 style.innerHTML = customHeroStyleSheet;
128 head.append(style);
129
130 const customHero = document.createElement("div");
131 customHero.className = "cm-hero";
132
133 customHero.innerHTML = `
134 <div class="cm-hero-con">
135 <h2 class="cm-hero-headline">${heroBanner.headline}</h2>
136 <h3 class="cm-hero-subheadline">${heroBanner.subheadline}</h3>
137 <div class="cm-hero-btn-con">
138 <a id=${heroBanner.button.id} href=${heroBanner.button.actionURL} class='cm-hero-btn ${heroBanner.button.style}'>
139 ${heroBanner.button.name}
140 </a>
141 </div>
142 </div>
143 `;
144
145 const getElementByFn = (selector, cb) => {
146 const intervalId = setInterval(() => {
147 const element = document.querySelectorAll(selector);
148 if (element.length === 1) {
149 clearInterval(intervalId);
150 cb(element[0]);
151 }
152 if (element.length > 1) {
153 clearInterval(intervalId);
154 cb(element);
155 }
156 }, 200);
157 };
158
159 const runCustomCode = (pathname) => {
160 if (!pathname.includes("library-v2")) return;
161 if (customHero.isConnected) customHero.remove();
162 getElementByFn("#library-container", (libraryCon) => {
163 const mainContainer = libraryCon.parentElement;
164 if (!mainContainer) return console.log("Menu Not inserted is because ref element not found");
165 mainContainer.insertBefore(customHero, libraryCon);
166 });
167 };
168
169 let pathname = "";
170 window.addEventListener("DOMNodeInserted", (e) => {
171 if (pathname == location.pathname) return;
172 pathname = location.pathname;
173 runCustomCode(pathname);
174 });
175})();
176// ****** Hero banner image End ********

Where to Install the Script

1. Open your GoHighLevel sub-account.

2. Navigate to Memberships and select the membership site you want to customize.

3. Go to Settings (gear icon).

4. Click the Advanced tab.

5. Paste the entire script into the Custom JS field.

6. Save your changes.

The hero banner will appear at the top of your membership library page, above the course/content grid.

How the Script Works

Configuration Object

The heroBanner object at the top of the script controls everything about the hero section:

| Property | Description | Example Value |

|----------|-------------|---------------|

| fontFamily | Font for headline and subheadline text | '"Roboto",sans-serif' |

| headline | Main heading text | "Welcome to Your Training Hub" |

| subheadline | Secondary text below the headline | "Start your learning journey here" |

| bgImg | URL of the background image | "https://your-cdn.com/banner.png" |

| minHeight | Minimum height of the hero section | "300px" |

| button.id | Unique HTML id for the CTA button | "cm-hero-btn" |

| button.name | Text displayed on the button | "Browse Courses" |

| button.style | Visual style: "fill" or "outline" | "fill" |

| button.actionURL | URL the button links to | "https://yoursite.com/courses" |

To customize the hero for your membership site, update these values in the heroBanner object. For example:

1const heroBanner = {
2 fontFamily: '"Inter", sans-serif',
3 headline: "Welcome to the Marketing Mastery Vault",
4 subheadline: "Over 200 lessons to grow your agency",
5 bgImg: "https://your-cdn.com/your-banner-image.jpg",
6 minHeight: "350px",
7 button: {
8 id: "cm-hero-btn",
9 name: "Start Learning Now",
10 style: "fill",
11 actionURL: "https://yoursite.com/getting-started",
12 },
13};

Background Image

The hero section uses a full-width background image with background-size: cover and centered positioning. This means the image will scale to fill the container regardless of screen size, cropping from the edges as needed.

For best results, use a wide image (at least 1920px wide) with important content centered. If your image has text baked in, keep critical information in the center 60% of the image to avoid cropping on smaller screens.

You can use any publicly accessible image URL. If you are hosting images through GoHighLevel's media library, upload the image to your GHL media, copy the URL, and paste it into the bgImg property.

Page Targeting

The script only activates on pages whose pathname includes "library-v2", which is the standard library page path for GHL membership sites. This means the hero will not appear on individual lesson pages, category pages, or other membership views.

If your library page uses a different path, update the condition in the runCustomCode function:

1const runCustomCode = (pathname) => {
2 if (!pathname.includes("your-custom-path")) return;
3 // rest of the function
4};

Dynamic Element Detection

Like other GHL membership customization scripts, this one uses interval-based polling to detect when the #library-container element appears in the DOM. GHL membership pages load content dynamically, so the target element may not exist when the script first runs. The polling function checks every 200 milliseconds until the element is found.

CSS Customization Reference

The stylesheet defines CSS custom properties for every visual aspect of the hero section. You can modify these in the customHeroStyleSheet string to match your brand.

Hero Section Variables

| Variable | Default | Controls |

|----------|---------|----------|

| --cm-hero-min-height | 300px | Minimum height of the hero banner |

| --cm-container-max-width | 1080px | Maximum width of the content area |

| --cm-hero-background-img | Set from config | Background image URL |

| --cm-hero-font-family | Set from config | Font for all hero text |

Headline Variables

| Variable | Default | Controls |

|----------|---------|----------|

| --custom-headline-font-size | 40px | Main headline size |

| --custom-headline-font-color | #000 | Main headline color |

| --custom-headline-font-weight | 700 | Main headline weight |

| --custom-subheadline-font-size | 30px | Subheadline size |

| --custom-subheadline-font-color | #000 | Subheadline color |

| --custom-subheadline-font-weight | 700 | Subheadline weight |

Button Variables

| Variable | Default | Controls |

|----------|---------|----------|

| --custom-cm-btn-border-radius | 5px | Button corner rounding |

| --custom-cm-btn-padding | 10px 25px | Button internal spacing |

| --custom-cm-btn-font-size | 16px | Button text size |

| --custom-cm-btn-font-weight | 700 | Button text weight |

| --custom-cm-btn-background-color | rgb(24, 15, 120) | Fill button background |

| --custom-cm-btn-font-color | #fff | Fill button text color |

| --custom-cm-outline-btn-background-color | transparent | Outline button background |

| --custom-cm-outline-btn-font-color | rgb(24, 15, 120) | Outline button text color |

| --custom-cm-btn-outline-border | 1px solid rgb(24, 15, 120) | Outline button border |

Example: Dark Theme Hero

If your membership site uses a dark color scheme, you might adjust the variables like this:

1--custom-headline-font-color: #ffffff;
2--custom-subheadline-font-color: #e0e0e0;
3--custom-cm-btn-background-color: #f59e0b;
4--custom-cm-btn-font-color: #000000;
5--custom-cm-outline-btn-font-color: #f59e0b;
6--custom-cm-btn-outline-border: 1px solid #f59e0b;

Pair this with a dark background image and you get a cohesive dark-themed hero section.

Use Cases

Welcome Banner for New Members

Use the hero to greet new members and point them to a getting-started guide or orientation course. A clear headline like "Welcome to [Your Program Name]" with a "Start Here" button reduces overwhelm and increases first-lesson completion rates.

Promotional Announcements

When you launch a new course, host a live event, or run a limited-time offer, the hero banner is the most visible place to announce it. Update the headline, subheadline, and button to promote the event, then swap back to your default after it ends.

Brand Reinforcement

A professional hero section with your brand's imagery and messaging elevates the perceived value of your membership. Members are more likely to stay engaged and refer others when the platform feels polished and intentional.

Content Navigation

If your membership has a large library, use the CTA button to direct members to a curated starting point, a recently updated course, or a content roadmap page.

Removing the CTA Button

If you want a hero section without a button, you can remove the button-related HTML from the customHero.innerHTML template:

1customHero.innerHTML = `
2 <div class="cm-hero-con">
3 <h2 class="cm-hero-headline">${heroBanner.headline}</h2>
4 <h3 class="cm-hero-subheadline">${heroBanner.subheadline}</h3>
5 </div>
6`;

This gives you a clean banner with just the headline and subheadline.

Troubleshooting

Hero does not appear: Verify that your library page URL contains "library-v2". Open the page, check the browser address bar, and confirm the path. If it uses a different path, update the condition in runCustomCode.

Background image not loading: Make sure the image URL is publicly accessible. If you copied it from GHL's media library, open the URL directly in a browser tab to confirm it loads. CORS restrictions generally do not apply to background images, but broken or private URLs will result in a blank background.

Text not readable over the background image: Adjust the headline and subheadline colors to contrast with your background image. You can also add a semi-transparent overlay by modifying the .cm-hero class:

1.cm-hero::before {
2 content: '' !important;
3 position: absolute !important;
4 top: 0 !important;
5 left: 0 !important;
6 right: 0 !important;
7 bottom: 0 !important;
8 background: rgba(0, 0, 0, 0.4) !important;
9}
10
11.cm-hero {
12 position: relative !important;
13}
14
15.cm-hero .cm-hero-con {
16 position: relative !important;
17 z-index: 1 !important;
18}

This adds a dark overlay behind the text for better readability.

Hero flickers on page navigation: The script removes and re-inserts the hero when the pathname changes. If you see a brief flicker, this is normal behavior due to the dynamic reinsertion. The polling interval of 200ms means there may be a very brief gap between page load and hero insertion.

Combining with Other Membership Customizations

This hero section script is designed to be independent. It uses its own namespaced CSS classes (.cm-hero, .cm-hero-con, etc.) and does not interfere with other membership customization scripts. You can safely use it alongside sidebar button scripts, custom navigation menus, or other JavaScript-based membership enhancements.

If you are running multiple custom scripts, paste them sequentially in the Custom JS field. Each self-executing function is wrapped in an IIFE (immediately invoked function expression), so variable names will not conflict between scripts.

Want to try HighLevel?

If you're exploring marketing automation platforms, HighLevel offers a 30-day free trial.

Start your free trial