
While Webflow provides excellent visual design capabilities, running custom JavaScript functions on button clicks has traditionally required workarounds due to security restrictions on the onclick attribute.
This comprehensive guide introduces the brix-button-js attribute system that elegantly solves this limitation, allowing you to execute any JavaScript function by simply adding an attribute to your buttons.
Best of all, this solution requires no external libraries and can be implemented in a few minutes if your Webflow site or workspace has access to Custom Code.

Modern web applications often require custom JavaScript functionality triggered by user interactions. The brix-button-js attribute transforms Webflow's button elements into powerful triggers for any JavaScript function without complex event binding or ID management.
This implementation enables seamless function execution while maintaining Webflow's visual design workflow, creating an intelligent interaction system that bridges the gap between no-code design and custom functionality. You'll learn how to implement this versatile solution that works with any JavaScript function in your Webflow project.
Understanding the strategic value of custom button functions helps you implement interactive features effectively:
If you prefer a no-code approach to tracking button clicks, our guide to tracking Webflow button clicks with Google Tag Manager covers the setup without custom JavaScript.
Webflow blocks the direct onclick attribute for security reasons, preventing XSS attacks and maintaining platform stability. Our solution works differently — it uses a custom attribute system that Webflow allows, then connects trusted brix-button-js attribute values to your JavaScript functions using event delegation.
Before implementing the button triggers, you need to define the JavaScript functions you want to execute.
Follow these steps to set up your JavaScript functions:
Your functions are now ready to be connected to buttons using the brix-button-js system.
The implementation involves adding the core JavaScript handler to your Webflow project and configuring buttons with the brix-button-js attribute.
Here's how to add the button function execution capability:
1 - Copy the implementation script: This code handles all the magic:
<script>
/**
* BRIX Templates Button Function Executor for Webflow
* Execute any JavaScript function from button clicks using custom attributes
* @version 1.1.2
* @author BRIX Templates
*
*/
(function() {
'use strict';
// Global initialization guard
if (window.__brixButtonJSInitialized) {
console.log('ℹ️ BRIX Button JS - Already initialized globally, skipping.');
return;
}
window.__brixButtonJSInitialized = true;
// Configuration
const CONFIG = {
attributeName: 'brix-button-js',
preventDefault: true,
debug: true
};
// Cache compiled runners for better performance
const runnerCache = new Map();
// Async function constructor for supporting async/await
const AsyncFunction = Object.getPrototypeOf(async function() {}).constructor;
function log(message, data) {
if (!CONFIG.debug) return;
if (data !== undefined) {
console.log(message, data);
} else {
console.log(message);
}
}
function getButtonCode(element) {
return (element.getAttribute(CONFIG.attributeName) || '').trim();
}
function getRunner(code) {
if (runnerCache.has(code)) {
return runnerCache.get(code);
}
let runner;
try {
// Expression mode:
// Supports:
// calculate()
// multiply(5, 3)
// confirm('Are you sure?') && deleteItem()
// () => console.log('Clicked!')
runner = new AsyncFunction(
'event',
'element',
`
const result = (${code});
if (typeof result === 'function') {
return await result.call(element, event, element);
}
return await result;
`
);
} catch (error) {
// Statement mode:
// Supports:
// trackEvent(); calculate(); showMessage('Done')
runner = new AsyncFunction(
'event',
'element',
code
);
}
runnerCache.set(code, runner);
return runner;
}
async function executeButtonCode(element, event) {
const code = getButtonCode(element);
if (!code) return;
log('🤖 BRIX Button JS for Webflow - Executing: ' + code);
const runner = getRunner(code);
return await runner.call(element, event, element);
}
function isDisabled(element) {
return (
element.hasAttribute('disabled') ||
element.getAttribute('aria-disabled') === 'true'
);
}
// Main click handler
document.addEventListener('click', async function(event) {
let target = event.target;
// Text nodes do not support closest()
if (!(target instanceof Element)) {
target = target && target.parentElement;
}
if (!target) return;
const button = target.closest('[' + CONFIG.attributeName + ']');
if (!button) return;
if (isDisabled(button)) return;
if (CONFIG.preventDefault) {
event.preventDefault();
}
try {
await executeButtonCode(button, event);
} catch (error) {
console.error(
'🤖 BRIX Button JS for Webflow - Error executing: ' + getButtonCode(button),
error
);
}
});
})();
</script>2 - Add the script to Webflow:

3 - Add your custom functions: Place your function definitions either before or after the brix-button-js script > Make sure functions are in the global scope
4 - Publish your site: Click Publish in the top-right > Select your staging domain and publish (don’t publish on production until everything works perfectly)
Now let's set up your buttons to execute functions:

The brix-button-js attribute accepts different function formats depending on your needs:
Security note: The value of brix-button-js is executed as trusted JavaScript. Only use this attribute with code controlled by the site owner. Do not connect it to user-generated content, untrusted CMS fields, or external inputs that could inject unintended code.
Need async operations? The system fully supports async/await functions, promises, and complex asynchronous workflows. You can trigger API calls, animations, or any time-based operations seamlessly.
Let's look at a practical example of a "Call us now!" button that both initiates a phone call and tracks the interaction with Meta Facebook Pixel. For the complete setup guide covering all Meta Pixel events on Webflow, see our step-by-step Meta Pixel tracking guide for Webflow.
1 - Create the tracking function: Add this to your site's custom code:
// Function to initiate call and track with Meta Pixel
function trackAndCall() {
// Track the call event with Meta Facebook Pixel
if (typeof fbq !== 'undefined') {
fbq('track', 'Contact', {
content_name: 'Phone Call',
content_category: 'Call Button Click'
});
}
// Initiate the phone call
window.location.href = 'tel:+1234567890';
console.log('Call initiated and tracked');
}2 - Set up your button in Webflow:
3 - Result: When clicked, the button fires the Meta Pixel event for conversion tracking and then initiates the phone call on mobile devices, giving you valuable analytics while providing seamless user experience.
Time to ensure everything works perfectly:

Here's how to fix the most common problems:
Function not executing:
Parameters not working:
Console errors appearing:
Write a calculatePrice() function that reads input values from form fields using document.getElementById(), performs your calculation logic, and displays the result by updating a text element's .textContent. Apply brix-button-js="calculatePrice()" to your calculate button to instantly show pricing without page refresh.
Create a toggleDarkMode() function that adds/removes a class from the body element using document.body.classList.toggle('dark-mode'), then define your dark mode styles in Webflow using that class. Set brix-button-js="toggleDarkMode()" on your toggle button and optionally save the preference to localStorage for persistence.
Build an async function submitToAPI() that collects form data, uses fetch() to POST to your endpoint with proper headers and JSON body, then handles the response. Add brix-button-js="submitToAPI()" to your submit button, ensuring your function includes error handling and user feedback.
Implementing custom function execution with the brix-button-js attribute transforms your Webflow buttons into powerful interaction triggers that can execute any JavaScript logic. This solution bridges the gap between no-code design and custom functionality, enables sophisticated interactions without complex event management, and provides the flexibility needed for modern web applications.
The combination of Webflow's intuitive design interface and custom JavaScript functions creates unlimited possibilities for interactive experiences. Start with simple functions to test the implementation, then expand to more complex interactions as your needs grow.
For advanced implementations requiring complex state management, real-time data synchronization, or enterprise-level interaction patterns, our Webflow development team can create sophisticated solutions that perfectly align with your specific business requirements.

Understand Webflow's 2026 pricing update, including new Premium plan, Basic changes, bandwidth add-ons, renewal dates, and calculator tips.

Build next/previous post navigation in Webflow CMS with Reference fields or BRIX Post Nav, including sort order logic.

Add comments to Webflow CMS blog posts with Disqus or Hyvor Talk, ensuring each post has its own discussion thread.

