How to Use GoHighLevel Custom Values for Dynamic Button Text in Funnels
Learn how to use GoHighLevel custom values to dynamically replace button headlines and sub-headlines in your funnels with this JavaScript snippet and step-by-step guide.
Why Dynamic Button Text Matters in GoHighLevel Funnels
GoHighLevel custom values are one of the platform's most powerful features for personalization. They let you insert dynamic content -- things like a contact's name, company, city, or any custom field -- directly into your funnels, emails, and workflows. The problem is that GHL's funnel builder does not natively support custom values inside button elements. You can drop a custom value into a headline or paragraph element with no issues, but the button headline and sub-headline fields do not process them.
This is a real limitation when you are building funnels that need to adapt based on the contact viewing the page. Think about use cases like personalized CTAs ("Start Your Free Trial, {{contact.first_name}}"), location-specific buttons ("Find Agents in {{contact.city}}"), or offer-specific text pulled from custom fields.
The workaround is straightforward: use a short JavaScript snippet to pull the rendered custom value text from a hidden paragraph element and inject it into the button element on the page. This article walks you through exactly how to set it up.
How Custom Values Work in GHL Funnels
Before diving into the code, here is a quick overview of how custom values behave in GHL funnels.
When you add a custom value like {{contact.first_name}} to a paragraph or headline element, GoHighLevel replaces that placeholder with the actual value when the page loads for a specific contact. This only works when the contact reaches the page through a GHL-tracked link -- for example, from an email, SMS, or workflow that includes the contact's tracking parameters.
The rendered result is plain text. If the contact's first name is "Marcus," the paragraph simply displays "Marcus" on the page. This rendering happens server-side before the page reaches the browser, which means by the time JavaScript runs, the custom value has already been replaced with the real text.
This is what makes the workaround possible. You place the custom value in a hidden paragraph element, let GHL render it, and then use JavaScript to grab that rendered text and move it into the button.
The Script
Here is the complete code for replacing button text with custom values:
1<script>2 /**************************3 * Copyright 2020 GHL Experts, All Rights Reserved4 * Author: Anas Uddin5 * Website: https://ghlexperts.com6 **************************/7 var buttonId = "#button-1139";8 var buttonHeadlineID = "#paragraph-Vs67MMjdD";9 var buttonSubHeadlineID = "#paragraph-6bMeHDtXh";1011 var buttonHeadline = document.querySelector(buttonHeadlineID + " div p").innerHTML;12 document.querySelector(buttonId + ' .main-heading-button').innerHTML = buttonHeadline;13 if(document.querySelector(buttonSubHeadlineID + " div p") && document.querySelector(buttonId + ' .sub-heading-button')) {14 var buttonSubHeadline = document.querySelector(buttonSubHeadlineID + " div p").innerHTML15 document.querySelector(buttonId + ' .sub-heading-button')[0].innerHTML = buttonSubHeadline;16 }17</script>
The script does three things:
1. Reads the rendered custom value from a hidden paragraph element on the page.
2. Injects that text into the button's main headline using the .main-heading-button class.
3. Optionally updates the sub-headline if both the source paragraph and the button sub-headline exist.
Step-by-Step Setup Instructions
Step 1: Add Hidden Paragraph Elements for Your Custom Values
In your GHL funnel editor, add one or two paragraph elements to the page. These will hold the custom values that you want to appear on your button.
• Paragraph 1 (Button Headline): Add your custom value text here. For example: Get Started, {{contact.first_name}}!
• Paragraph 2 (Button Sub-Headline): If your button has a sub-headline, add a second paragraph with that custom value. For example: Special offer for {{contact.company_name}}
After adding these elements, you need to hide them so they do not appear on the live page. Select each paragraph element, open its settings, and set the visibility to hidden. Alternatively, you can use custom CSS to hide them:
1#paragraph-Vs67MMjdD,2#paragraph-6bMeHDtXh {3 display: none;4}
Step 2: Get the Element IDs
You need three IDs: the button element ID, and the IDs of each hidden paragraph.
1. Open your funnel page in the editor.
2. Click on the button element. In the element settings panel, look for the element ID. It will look something like button-1139. Note the full selector: #button-1139.
3. Click on each hidden paragraph element. Note their IDs as well. They will look something like paragraph-Vs67MMjdD and paragraph-6bMeHDtXh.
If you cannot find the element ID in the editor, right-click the element in your browser's preview, choose "Inspect," and look for the id attribute on the element's wrapper div.
Step 3: Update the Script with Your IDs
Replace the three ID variables in the script with your actual element IDs:
1var buttonId = "#button-YOUR-BUTTON-ID";2var buttonHeadlineID = "#paragraph-YOUR-HEADLINE-PARAGRAPH-ID";3var buttonSubHeadlineID = "#paragraph-YOUR-SUBHEADLINE-PARAGRAPH-ID";
If your button does not have a sub-headline, you can leave the buttonSubHeadlineID as-is. The script includes a conditional check and will skip the sub-headline replacement if the elements do not exist.
Step 4: Add the Script to Your Funnel Page
1. Open your funnel page in the GHL editor.
2. Go to Settings (the gear icon) for the page.
3. Navigate to the Custom Code or Tracking Code section.
4. Paste the script into the Body Tracking Code (footer) section. Placing it in the footer ensures the page elements have loaded before the script runs.
5. Save and publish your funnel.
Step 5: Test with a Real Contact Link
Custom values only render when the page is loaded through a GHL-tracked link associated with a contact. To test:
1. Create a test contact in your GHL account.
2. Send yourself an email or SMS from a workflow that includes a link to the funnel page.
3. Click the link and verify that the button text updates with the contact's data.
If you load the page directly by typing the URL into your browser, the custom values will not render, and the button text will show the raw placeholder text.
When to Use This Technique
Personalized Call-to-Action Buttons
The most common use case is personalizing CTA buttons with the contact's name. A button that says "Start Your Trial, Marcus" converts better than a generic "Start Your Trial" because it signals that the page is tailored specifically to the viewer.
Location-Based CTAs
If you are running location-specific campaigns, you can use the contact's city or state custom field to create buttons like "Find Providers in {{contact.city}}" or "See {{contact.state}} Pricing."
Offer-Specific Buttons
When running multiple offers through the same funnel, you can store the offer name or discount percentage in a custom field and display it on the button: "Claim Your {{contact.discount_amount}}% Discount."
White-Label Funnels
Agencies using GHL's white-label features can use custom values to display the client's brand name on buttons, making a single funnel template work across multiple clients without manual edits.
Troubleshooting Common Issues
Button text does not change: Double-check that your element IDs are correct. Open the browser's developer console (F12) and look for JavaScript errors. The most common issue is an incorrect ID selector.
Custom value shows as raw placeholder text: This means the page was not loaded through a GHL-tracked contact link. Custom values only render when the contact is identified. Test with a real contact link from an email or SMS.
Sub-headline does not update: The script checks for the existence of both the source paragraph and the .sub-heading-button class on the button. If your button does not have a sub-headline enabled in the editor, the class will not exist and the script will skip it. Enable the sub-headline in the button settings if you need it.
Script runs before elements load: Make sure the script is placed in the footer tracking code section, not the header. If elements still are not available, wrap the code inside a DOMContentLoaded event listener:
1<script>2document.addEventListener("DOMContentLoaded", function() {3 // paste the script contents here (without the outer <script> tags)4});5</script>
Summary
GoHighLevel's funnel builder does not natively support custom values in button elements, but this JavaScript workaround gives you full control over dynamic button text. By placing custom values in hidden paragraph elements and using a short script to transfer that text into the button, you can create personalized, dynamic CTAs that adapt to each contact viewing the page. The setup takes a few minutes per funnel page and opens up use cases ranging from personalized names to location-based offers and white-label branding.
Want to try HighLevel?
If you're exploring marketing automation platforms, HighLevel offers a 30-day free trial.
Start your free trialJoin thousands of agencies using GoHighLevel to replace their entire marketing stack and boost recurring revenue.