The RAW element is your escape hatch for unlimited customization. When
FunnelFox’s built-in elements don’t quite fit your needs, RAW lets you
write custom code to create exactly what you want.
Common Use Cases
Custom Calculations BMI calculators, loan estimators, or any complex math based on user inputs
Third-Party Widgets Embed calendars, maps, chat widgets, or social media feeds
Advanced Styling Create unique visual effects or animations not available in standard elements
External Integrations Connect to APIs, track custom events, or sync with external services
Properties
Element Tab
HTML Content
The main code editor where you write your HTML, CSS, and JavaScript.
Supports full HTML5 syntax with embedded styles and scripts.
< div style = "padding: 20px;" >
< h3 > Custom Content </ h3 >
< button onclick = " alert ('Hello!')" > Click Me </ button >
</ div >
< script >
// Your JavaScript here
console . log ( 'RAW element loaded' );
</ script >
< style >
/* Your CSS here */
h3 { color : blue ; }
</ style >
No (default): Element renders with its own styling
Yes : Inherits theme styles (fonts, colors) from funnel settings
Important : When visibility is set to “No”, the RAW element is not
rendered in the DOM, so scripts won’t execute. Use this to conditionally
run code based on user segments.
For common properties (ID, Visibility, Styles), see Elements Overview .
Working with the Fox API
Access FunnelFox functionality through the global fox object:
< script >
// Get user input values
const name = fox . inputs . get ( 'name' );
const age = parseInt ( fox . inputs . get ( 'age' ));
// Calculate and store result
const category = age < 18 ? 'junior' : 'adult' ;
fox . inputs . set ( 'user-category' , category );
// Navigate based on logic
if ( category === 'junior' ) {
fox . navigation . goToId ( 'youth-offer' );
} else {
fox . navigation . goToId ( 'standard-offer' );
}
</ script >
See Custom Code & Fox API for complete API reference.
Examples
BMI Calculator
Calculate BMI from user inputs and display results:
< div id = "bmi-result" style = "padding: 20px; text-align: center;" >
< h3 > Your BMI Result </ h3 >
< p id = "bmi-value" style = "font-size: 24px; font-weight: bold;" ></ p >
< p id = "bmi-category" ></ p >
</ div >
< script >
// Get height and weight from previous inputs
const weight = parseFloat ( fox . inputs . get ( 'weight' ));
const height = parseFloat ( fox . inputs . get ( 'height' ));
// Calculate BMI
const bmi = weight / (( height / 100 ) * ( height / 100 ));
// Determine category
let category ;
if ( bmi < 18.5 ) category = "Underweight" ;
else if ( bmi < 25 ) category = "Normal weight" ;
else if ( bmi < 30 ) category = "Overweight" ;
else category = "Obese" ;
// Display results
document . getElementById ( 'bmi-value' ). textContent = bmi . toFixed ( 1 );
document . getElementById ( 'bmi-category' ). textContent = category ;
// Store for use in next screens
fox . inputs . set ( 'bmi' , bmi . toFixed ( 1 ));
fox . inputs . set ( 'bmi-category' , category );
</ script >
Embedded Video
Add a responsive video player:
< div style = "position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;" >
< iframe
src = "https://www.youtube.com/embed/VIDEO_ID"
style = "position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
frameborder = "0"
allowfullscreen >
</ iframe >
</ div >
Custom Timer
Create urgency with a countdown:
< div id = "timer" style = "text-align: center; padding: 20px;" >
< h2 > Offer expires in: </ h2 >
< div id = "countdown" style = "font-size: 32px; color: red;" ></ div >
</ div >
< script >
// Set timer for 10 minutes
let timeLeft = 600 ; // seconds
function updateTimer () {
const minutes = Math . floor ( timeLeft / 60 );
const seconds = timeLeft % 60 ;
document . getElementById ( 'countdown' ). textContent =
` ${ minutes } : ${ seconds . toString (). padStart ( 2 , '0' ) } ` ;
if ( timeLeft > 0 ) {
timeLeft -- ;
setTimeout ( updateTimer , 1000 );
} else {
document . getElementById ( 'countdown' ). textContent = "EXPIRED" ;
// Optionally navigate to expired offer page
fox . navigation . goToId ( 'offer-expired' );
}
}
updateTimer ();
</ script >
Dynamic Content Based on Time
Show different content based on time of day:
< div id = "greeting" style = "padding: 20px;" ></ div >
< script >
const hour = new Date (). getHours ();
const greetingEl = document . getElementById ( 'greeting' );
if ( hour < 12 ) {
greetingEl . innerHTML = '<h2>Good Morning! ☀️</h2><p>Start your day with 20% off</p>' ;
} else if ( hour < 18 ) {
greetingEl . innerHTML = '<h2>Good Afternoon! 🌤</h2><p>Midday special: Buy 2 get 1 free</p>' ;
} else {
greetingEl . innerHTML = '<h2>Good Evening! 🌙</h2><p>Night owl discount: 30% off</p>' ;
}
</ script >
External API Integration
Fetch data from your backend:
< div id = "user-data" style = "padding: 20px;" >
< p > Loading your account... </ p >
</ div >
< script >
async function loadUserData () {
const email = fox . inputs . get ( 'email' );
try {
const response = await fetch ( 'https://your-api.com/user' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({ email })
});
const data = await response . json ();
document . getElementById ( 'user-data' ). innerHTML = `
<h3>Welcome back, ${ data . name } !</h3>
<p>Your account balance: $ ${ data . balance } </p>
<p>Member since: ${ data . joinDate } </p>
` ;
// Store user data for later use
fox . inputs . set ( 'user-name' , data . name );
fox . inputs . set ( 'user-balance' , data . balance );
} catch ( error ) {
document . getElementById ( 'user-data' ). innerHTML =
'<p>Unable to load account data. Please try again.</p>' ;
}
}
loadUserData ();
</ script >
Execution Context
When Code Runs
Scripts execute immediately when the screen loads
Code runs every time a user navigates to the screen
No need for DOMContentLoaded or similar wrappers
Fox API is available immediately as window.fox
Available APIs
Full access to browser APIs:
DOM : All document methods and properties
Window : Global window object and methods
Fetch : For API calls
Local Storage : For persistent data
All JavaScript : ES6+, async/await, promises
Scope and State
Each RAW element runs in the global scope
Variables persist within the same screen
State doesn’t carry between screens (use fox.inputs.set())
Multiple RAW elements on same screen share scope
Best Practices
Keep It Simple Use RAW only when built-in elements won’t work. Native elements are
faster and more reliable.
Test Thoroughly Always test in preview mode across different devices and browsers
before publishing.
Handle Errors Wrap risky code in try-catch blocks. One JavaScript error can break
the entire funnel.
Optimize Performance Minimize external requests, avoid heavy computations, and load
resources asynchronously.
Security Considerations
No server-side code : Everything runs client-side
Validate inputs : Never trust user data
Secure API calls : Use HTTPS and proper authentication
No sensitive data : Don’t embed API keys or secrets
XSS prevention : Sanitize any user-generated content
// ❌ Bad: Blocking external script
< script src = "https://heavy-library.com/lib.js" ></ script >
// ✅ Good: Async loading
< script async src = "https://heavy-library.com/lib.js" ></ script >
// ❌ Bad: Repeated DOM queries
for ( let i = 0 ; i < 100 ; i ++ ) {
document . getElementById ( 'result' ). innerHTML += i ;
}
// ✅ Good: Single DOM update
let content = '' ;
for ( let i = 0 ; i < 100 ; i ++ ) {
content += i ;
}
document . getElementById ( 'result' ). innerHTML = content ;
Limitations
No server-side execution : All code runs in the browser
No file system access : Can’t read/write local files
Same-origin policy : CORS restrictions apply to API calls
No Node.js : Browser JavaScript only
Memory limits : Heavy operations may slow/crash browser
Troubleshooting
Check element visibility isn’t set to “No”
Look for JavaScript errors in browser console
Verify script tags are properly closed
Ensure no syntax errors in code
Check CSS specificity conflicts
Verify style tags are within the RAW element
Try using !important for overrides
Check Preserve Formatting setting
Check CORS headers on your API
Verify HTTPS is used for external calls
Look for network errors in browser console
Test API endpoint independently first
Wrap code in try-catch blocks
Check for infinite loops
Remove or comment out code sections to isolate issue
Test in preview mode before publishing
Next Steps