Watch Webinar: Figma - Design to Code in 80% Less Time

Announcing Visual Copilot - Figma to production in half the time logo
Talk to Us
Contact Sales
Talk to Us










Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required



Get StartedLogin

The Builder Visual Editor helps you add event handlers, bind to state, and even add custom JavaScript that runs on your page.

Tip: To add custom HTML to your Page or Section, use the Custom Code Block rather than custom JavaScript.

In Builder, you can bind state values to Builder blocks and implement custom actions when users interact with your content.

For detailed instructions on incorporating state bindings or action handlers, visit Building Interactivity Using State and Actions.

When adding custom JavaScript code within a state binding or action handler, remember that you needn't use the return keyword to yield a value. Instead, choose from these four examples:

For straightforward, one-line expressions, you can write code directly in the code editor without the return statement:

state.showWelcomeMessage ? 'Say Hello' : 'Say Goodbye'

For more intricate logic, export a default value:

let greeting;
if (justLoggedIn) {
  value = 'Welcome';
} else {
  value = 'hi';
export default greeting;

You can access Builder state in both state bindings and action handlers. While state bindings are typically closely bound to Builder, you can also modify the state value within the binding. For example:

// use the plain value from state

// uppercase the state value

// return a different value depending on state property
state.someBooleanValue ? 'yes' : 'no

Action handlers introduce an additional object you can access: event.

This event object represents the HTML event triggered by the selected action. You can leverage event to access the event's target element or invoke methods such as preventDefault or stopPropagation:

// access the value attribute (ie from an input)
// and store it in builder state
state.someStateProp = event.currentTarget.value;

// if you have a link with an href, you might want to stop
// default browser navigation and handle this yourself
var targetElementId =;
var elementToScrollTo = document.getElementById(targetElementId);
elementToScrollTo.scrollIntoView({ behavior: 'smooth' });

To add custom styles or JavaScript to your content:

  1. In the content entry, go to the Data tab.
  2. Expand the Code section.
  3. Click the Edit Custom JS + CSS button.
  4. In the window that opens, you can put your CSS on the left and your JavaScript on the right.

This example shows adding some custom CSS to a Page and then applying it to elements on the Page.

The CSS in below—which the video features–applies a margin and blue color to links (the a tag), and a yellow background color to any element with .my-class:

/* Style all link elements */
a {
     margin: 10px;
     color: blue;

/* Style all elements with the class name "my-class" */
.my-class {
	background-color: yellow;

To use the CSS, add the code to the Custom Code editor and then apply the styles either by applying a class to an element or creating elements that would naturally inherit those styles.

The following video shows how to add custom CSS and apply it to elements. A written explanation follows the video.

Any element that has the .my-class applied inherits the .my-class styles as soon as .my-class is applied to that element. In this example, when the Box is given the class .my-class, its background immediately turns yellow.

Any elements that are styled directly in the CSS, such as links in this example, are styled automatically. This happens in the video as soon as the copy becomes a link.

You can run JS client side and/or server side using Builder.isBrowser and Builder.isServer. By default, any code not wrapped with Builder.isBrowser or Builder.isServer is run on Builder's servers.

To run code client-side, wrap it in if (Builder.isBrowser) {}.

For example, suppose you're rendering your Builder content lazily on the client and you want to support linking directly to certain sections of a page based on the ID attribute of the section. You could do this with some custom JavaScript:

if (Builder.isBrowser) {
    const el = location.hash &&

    el.scrollIntoView({ behavior: 'smooth' });

You also have access to fetch() on the client and server. For server side data, you can export a default promise that resolves with the necessary data before responding:

async function main() {
  if (Builder.isServer) {
    // Place any code here you want to only run on 
    // the server. Any  data fetched on the server 
    // will be available to re-hydrate on the client
    // if added to the state object
    await fetch(someUrl)
      .then(res => res.json())
      .then(data => {
        // set the data on the state object so 
        // you can access it from your components
        state.someData = data;
  if (Builder.isBrowser) {
    // Place code that you only want to run 
    // in the browser (client-side only) here
    // For example, anything that uses 
    // document/window access or DOM manipulation

export default main();

In the provided example, data fetched on the server is stored on the state object and can be accessed as data bindings in both the server and client UIs. For more details on fetching and using data, refer to Dynamic Preview URLs.

Remember to exercise caution and consider the impact on performance and security when adding custom code to your site. For instance, when incorporating custom event listeners, ensure the use of passive events for proper handling.

When adding your custom JavaScript code, the useful builder values include:

  • Builder.isServer: Use to determine if the code is running on the server-side (such as in a Node.js environment) or not. It returns true if the code is executing on the server, and false if it's running in a browser.
  • Builder.isBrowser: Use to check if the code is running in a browser environment. It returns true if the code is executing in a web browser, and false otherwise, including server-side.
  • Builder.isPreviewing: Use to check if the code is currently in preview mode within the Visual Editor. It returns true if the code is being previewed in the Visual Editor, and false if it's not in preview mode.
  • Builder.isEditing: Use to check if the code is currently being edited within the editor. It returns true if the code is being edited, and false if it's not being edited.

For the source code, visit GitHub.

Tip: If your custom code isn't delivering expected results when working with page elements or third-party scripts, the event loop's asynchronous nature might be the reason. Consider using setTimeout() or conditional checks to time your code accurately and synchronize it with the page's rendering process.

For more information on the global objects available, visit:

Up next

3rd party libraries

Was this article helpful?


Visual CMS

Theme Studio for Shopify

Sign up


Featured Integrations





Get In Touch

Chat With Us




© 2020, Inc.


Privacy Policy

Terms of Service


Get the latest from

By submitting, you agree to our Privacy Policy