Webflow Custom Code: The Complete Guide for 2026

Jerre Baumeister
Sergej Gorisek
Co-founder
Summarize with AI
Table of contents

A client came to us a few years ago with a brief that made a junior developer on the team laugh. They wanted a homepage where a 3D particle constellation reacted to mouse movement, filters updated instantly without a page reload, and a multi-step form that validated in real time. "Can Webflow do that?" they asked.

It can. It just needs help.

That's what Webflow custom code is for. The platform's visual builder handles the vast majority of what most sites need - but custom HTML, CSS, and JavaScript unlock everything else. This guide covers how custom code works in Webflow in 2026: where to add it, how each method behaves, real-world examples from GSAP animations to Finsweet CMS filtering, and how to use AI tools to generate Webflow-compatible scripts without starting from scratch.

At Flowout, our custom code development team has built everything from enterprise CMS filtering systems to custom cursor effects and real-time API integrations. Here's what we've learned.

What Is Webflow Custom Code?

Webflow generates clean HTML, CSS, and JavaScript from its visual designer. Custom code is anything you add to that output - snippets, libraries, or full scripts that the platform wouldn't produce on its own.

The typical use cases fall into three categories:

Third-party integrations. Analytics platforms, heat mapping tools, chat widgets, CRM form handlers, and any service that needs a script tag to function. These usually go in the site-level <head> or footer.

Visual enhancements. Animation libraries like GSAP or Lenis for smooth scrolling, custom cursors, scroll-triggered effects, or 3D canvas elements that go beyond Webflow's native Interactions panel.

Functional extensions. CMS filtering, multi-step forms, dynamic search, member-gating logic, or client-side API calls that connect your Webflow site to external data sources.

Webflow's Webflow development platform supports HTML, CSS, and JavaScript. It does not execute server-side languages (Python, PHP, Ruby) in the browser - those run elsewhere and connect to your site via API calls.

The Three Places to Add Custom Code in Webflow

1. Site Settings (Global Code)

Site Settings is the place for code that needs to run on every page: analytics scripts, consent managers, global font declarations, or site-wide CSS overrides.

Navigate to your project's Site Settings → Custom Code tab. You'll find two slots:

Head Code - injected at the end of your <html><head> section, before </head>. Use this for scripts that need to load before page rendering: font declarations, CSS libraries, consent management, or any script marked with the type="module" attribute.

Footer Code - injected just before </body>. Use this for everything else. Scripts placed here load after the page content is visible, which reduces render blocking and improves your Core Web Vitals scores.

Each slot supports up to 50,000 characters. The limit matters for large inline scripts (more on workarounds below).

Important for 2026: Webflow's global site settings now also include a Scripts section in the newer interface alongside the legacy Custom Code tab. Both write to the same output, but the Scripts interface provides better visibility into what's loading and when.

2. Page Settings (Page-Specific Code)

Page Settings scopes code to a single URL - ideal for page-specific animations, custom form scripts, A/B testing payloads, or analytics events tied to one conversion page.

Access it from the Pages panel by clicking the gear icon next to any page. Scroll to the Custom Code section at the bottom. As with Site Settings, you get Head and Footer slots with 50,000 character limits each.

One thing to be aware of: Page Settings code loads after Site Settings code, which matters if your page-level script depends on a library loaded globally. Always load libraries in Site Settings and call them in Page Settings.

3. HTML Embed Component

The Embed component is the most granular option: a block you drop directly onto the Webflow canvas, placing your code exactly where it sits in the visual layout. You'll find it in the Add panel (+) → Components → Embed.

What makes it uniquely useful is that HTML and raw CSS placed inside an Embed render live inside the Webflow Designer. You can paste a custom HTML structure, add some inline CSS, and see the result without publishing. JavaScript does not run in the Designer - only on published or staging URLs.

Embeds are the right choice for:

  • Custom table structures or semantic HTML that Webflow's canvas doesn't produce natively
  • Inline SVG icons or animation triggers
  • Webflow CMS-connected code blocks - you can bind an Embed's content to a CMS field, which lets editors update code snippets without touching the Designer
  • Third-party widget embeds (maps, booking tools, social feeds) that need to sit at a specific visual position on the page

Each Embed element supports up to 50,000 characters.

Working Around the 50,000 Character Limit

When a script exceeds 50,000 characters, the solution is to host it externally and reference it with a single line in Webflow:

<script src="https://cdn.example.com/your-script.js" defer></script>

For teams without a dedicated CDN, the GitHub + jsDelivr workflow is reliable and free:

  1. Create a public GitHub repository and push your script file (e.g., custom.js)
  2. Get the raw GitHub URL: https://raw.githubusercontent.com/username/repo/main/custom.js
  3. Wrap it in jsDelivr's CDN: https://cdn.jsdelivr.net/gh/username/repo@main/custom.js
  4. Paste the jsDelivr URL into Webflow as a <script src=""> tag

jsDelivr automatically caches and serves the file from global edge nodes, which keeps load times fast and doesn't burden your GitHub bandwidth. Add ?v=2 to the URL to bust the cache when you update the file.

Always add defer or async to your <script> tags unless the script must run synchronously (rare). Deferred scripts load after HTML parsing is complete, which avoids blocking your page render.

Advanced Custom Code Examples

The basics - analytics tags, embed widgets - are well documented. Here's where the real functionality lives.

GSAP Animations

GSAP (GreenSock Animation Platform) is the industry standard for high-performance web animations. It handles timeline-based sequences, scroll-triggered effects, morph SVGs, and physics simulations that Webflow's native Interactions can't match.

Load GSAP via CDN in your Site Settings footer:

<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js" defer></script>

Then trigger an animation from Page Settings or an Embed:

<script>
gsap.registerPlugin(ScrollTrigger);

gsap.from(".hero-heading", {
  opacity: 0,
  y: 60,
  duration: 0.8,
  ease: "power3.out",
  scrollTrigger: {
    trigger: ".hero-heading",
    start: "top 80%"
  }
});
</script>

This fades in an element with the class hero-heading as it enters the viewport. The class name matches whatever you've set in the Webflow Designer's element settings. Our Webflow interactions team uses GSAP for complex timeline sequences where multiple elements need to animate in precise choreography.

Finsweet CMS Filter

Webflow's native CMS doesn't include client-side filtering - if you want visitors to filter blog posts, case studies, or product listings by category without a page reload, you need a script. Finsweet Attributes provides a no-code approach via data attributes.

Load the Finsweet library before </body>:

<script async src="https://cdn.finsweet.com/files/cms-attributes-v1.js"></script>

Then add fs-cmsfilter-field and fs-cmsfilter-element attributes to your Webflow elements from the Designer's custom attributes panel. Finsweet reads these attributes and wires up the filtering logic automatically. No custom JavaScript required. The result: instant, accessible, SEO-safe filtering that works with your existing Webflow CMS integration.

Multi-Step Forms

Webflow's native form component handles single-step submissions. Multi-step forms - the kind with a progress indicator and conditional logic - need custom code.

The approach: create each "step" as a <div> with a unique ID, hide all but the first step with CSS, and use JavaScript to show/hide on button clicks. Add validation logic before advancing steps.

<style>
  .form-step { display: none; }
  .form-step.active { display: block; }
</style>

<script>
  document.addEventListener("DOMContentLoaded", function () {
    let currentStep = 0;
    const steps = document.querySelectorAll(".form-step");

    function showStep(index) {
      steps.forEach((el, i) => el.classList.toggle("active", i === index));
    }

    document.querySelectorAll(".next-btn").forEach(btn => {
      btn.addEventListener("click", () => {
        if (currentStep < steps.length - 1) showStep(++currentStep);
      });
    });

    document.querySelectorAll(".prev-btn").forEach(btn => {
      btn.addEventListener("click", () => {
        if (currentStep > 0) showStep(--currentStep);
      });
    });

    showStep(0);
  });
</script>

For production multi-step forms on enterprise Webflow projects, we typically add real-time validation, analytics events per step, and integration with HubSpot or Salesforce on submit.

Custom Cursor

A custom cursor replaces the browser's default pointer with a branded element - a common request on design-forward sites. The implementation creates a <div> that follows mouse coordinates:

<div id="custom-cursor"></div>

<style>
  #custom-cursor {
    width: 20px;
    height: 20px;
    background: #FF6B35;
    border-radius: 50%;
    position: fixed;
    pointer-events: none;
    z-index: 9999;
    transform: translate(-50%, -50%);
    transition: width 0.2s, height 0.2s;
  }
</style>

<script>
  const cursor = document.getElementById("custom-cursor");
  document.addEventListener("mousemove", e => {
    cursor.style.left = e.clientX + "px";
    cursor.style.top = e.clientY + "px";
  });

  document.querySelectorAll("a, button").forEach(el => {
    el.addEventListener("mouseenter", () => {
      cursor.style.width = "40px";
      cursor.style.height = "40px";
    });
    el.addEventListener("mouseleave", () => {
      cursor.style.width = "20px";
      cursor.style.height = "20px";
    });
  });
</script>

Place this in an HTML Embed at the top of your body content, or in Site Settings footer code if you want it globally. Always disable the default cursor in CSS: * { cursor: none; } - and add a @media (pointer: coarse) query to hide the custom cursor on touch devices where it's irrelevant.

Smooth Scroll with Lenis

Webflow's native scroll is the browser default. For the buttery, momentum-based scroll seen on award-winning sites, Lenis is the go-to open-source library:

<script src="https://cdn.jsdelivr.net/npm/@studio-freight/lenis@1.0.42/dist/lenis.min.js"></script>
<script>
  const lenis = new Lenis({
    duration: 1.2,
    easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
  });

  function raf(time) {
    lenis.raf(time);
    requestAnimationFrame(raf);
  }
  requestAnimationFrame(raf);
</script>

Lenis also integrates with GSAP ScrollTrigger, so your scroll-triggered animations stay in sync with the smooth scrolling. This combination is what we use on our own portfolio and on design-forward client builds.

AI-Assisted Custom Code in Webflow

The most significant shift in how we write Webflow custom code over the past two years is AI tooling. Generating a working GSAP timeline, a Finsweet-compatible filter structure, or a multi-step form skeleton now takes minutes with the right prompt - not hours of documentation-reading.

The tools that work well for Webflow custom code:

Claude (claude.ai) - Strong for explaining code logic and generating well-commented scripts. Useful when you need to understand why something works before deploying it, or when you're integrating Webflow with external APIs.

Cursor - A code editor built on VS Code with an embedded AI assistant. Good for writing, iterating, and debugging JavaScript files that you'll then host externally and reference in Webflow.

ChatGPT - Effective for generating vanilla JavaScript patterns. Specify "Webflow-compatible" and "no jQuery dependency unless necessary" in your prompt to get cleaner output.

What prompts actually work:

Instead of "write me a multi-step form," try:

"Write a vanilla JavaScript multi-step form handler for Webflow. It should: show/hide divs with the class 'form-step', validate that required inputs are filled before advancing, show a progress bar, and work without any dependencies. The form will be placed inside a Webflow HTML Embed element."

The specificity matters - Webflow context, target element classes, dependency constraints, and where the code will live. Vague prompts produce generic output that needs heavy adaptation.

AI code still needs review. The most common issues we see in AI-generated Webflow scripts: selecting elements before the DOM is ready (fix: wrap in DOMContentLoaded), using var instead of const/let, and missing mobile edge cases. Always test on your Webflow staging domain before pushing to production.

For our SaaS clients who have development needs that go beyond Webflow's native CMS, we handle custom Webflow integrations with external systems - things that require API calls, webhooks, or server-side logic that AI tools can scaffold but can't deploy.

Best Practices for Webflow Custom Code

Load order matters. Libraries go in Site Settings. Scripts that call those libraries go in Page Settings footer or after the library tag. A script referencing a GSAP function before GSAP loads will silently fail.

Write it in a real editor first. VS Code with ESLint catches syntax errors before you paste anything into Webflow. A missing semicolon or bracket in Site Settings footer code can break your entire site's JavaScript.

Use unique IDs and classes. Multiple HTML Embeds on the same page that share element IDs will conflict. Prefix your custom element IDs (custom-cursor, fs-filter-wrapper) to avoid collisions with Webflow's generated class names.

Leverage Webflow Components for reusable embeds. If the same embed appears on five pages, convert the containing element into a Component (formerly Symbol). Update once, propagate everywhere. This is critical for anything CMS-driven.

Test on the staging domain, not the Designer. JavaScript does not execute in the Webflow Designer. Publish to your .webflow.io staging URL to test your custom code before publishing to your custom domain.

Keep the .webflow.io domain for development. Your staging domain is free and persistent. Use it as a permanent development environment - test on staging, verify in multiple browsers, then push to production.

Add defer to non-critical scripts. Any script that doesn't need to run during page rendering should carry a defer attribute. This improves Time to Interactive and Largest Contentful Paint - both factors in Google's Core Web Vitals ranking signals.

Document what you add. Leave a comment above every custom code block explaining what it does, why it's there, and when it was added. The next developer (or you, six months later) will thank you.

When to Hand Custom Code Off to a Developer

Custom code is learnable. It's also a significant time sink when things don't work, and incorrect implementations create bugs that are hard to trace.

The cases where it makes sense to work with Webflow developers rather than trying to DIY:

  • You need real-time data from an external API (weather, stock prices, user-specific CMS data)
  • You're building a multi-step form with conditional logic and CRM integration
  • The animation requires frame-by-frame choreography across multiple scroll stages
  • You're integrating payment processing or authentication logic client-side
  • You need the code to be maintainable by a non-developer team long-term

Our custom code development service handles these implementations as part of broader Webflow builds, or as standalone engagements via our hourly packages. If you're not sure whether your use case is DIY-able, the fastest way to find out is a call with our team.

Frequently Asked Questions

Can you add custom code to Webflow?

Yes. Webflow provides three dedicated locations for custom HTML, CSS, and JavaScript: Site Settings (global, loads on every page), Page Settings (scoped to a single page), and the HTML Embed component (inline, placed precisely within your layout). Each supports up to 50,000 characters. Custom code can integrate third-party tools, add animations, extend CMS functionality, and connect your site to external APIs.

How do I add JavaScript to Webflow?

Add <script> tags via Site Settings or Page Settings (under the Footer Code section, just before </body>), or inside an HTML Embed component. For JavaScript that depends on a library like GSAP or jQuery, load the library first in Site Settings → Footer Code, then call your functions in Page Settings or a lower Embed. JavaScript does not execute inside the Webflow Designer - preview and test your code on your .webflow.io staging domain.

Does Webflow support custom HTML?

Yes, fully. The HTML Embed component accepts any valid HTML and renders it live in the Designer (for HTML and CSS - JavaScript only runs on published URLs). You can embed custom <table> structures, <svg> elements, third-party widgets, semantic components that Webflow's canvas doesn't produce natively, and CMS-connected HTML blocks where editors update variables through the CMS dashboard.

What is Webflow embed code?

"Embed code" in Webflow typically refers to two things: (1) the HTML Embed component, which lets you drop custom HTML anywhere in your visual layout; and (2) Webflow's own embed snippet (found in Site Settings → SEO or under the site's code export) that you'd use to embed a Webflow form or other element on a non-Webflow page. For adding third-party embed code (maps, booking tools, video players), the HTML Embed component is the right place.

What is the character limit for Webflow custom code?

50,000 characters per section. This limit applies to Site Settings Head Code, Site Settings Footer Code, Page Settings Head Code, Page Settings Footer Code, and each individual HTML Embed element. For scripts that exceed this limit, host the file externally on GitHub and serve it via jsDelivr CDN, then reference it with a single <script src="..."> tag in Webflow.

Can you add custom code to Webflow on a free plan?

The HTML Embed component is available during development on any free .webflow.io staging domain. To publish custom code to a custom domain, you need a paid Webflow Site Plan or Workspace Plan. Site Settings custom code (global head/footer) requires a paid plan to publish.

How do I add Google Analytics to Webflow?

Add the GA4 measurement script via Site Settings → Custom Code → Head Code. Paste your full <script> tag (the one starting with <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX">) followed by the gtag('config', ...) block. Alternatively, add your Google Tag Manager container snippet to Site Settings head code and manage all scripts (GA4, Facebook Pixel, HubSpot, etc.) from GTM rather than adding them individually in Webflow. GTM is more maintainable when you're running multiple scripts.

Why is my custom JavaScript not working in Webflow?

The most common causes: (1) the script is running before the DOM elements it targets exist - wrap it in document.addEventListener("DOMContentLoaded", function() {...}) or move it to the footer; (2) you're testing in the Webflow Designer, where JavaScript doesn't execute - test on your staging domain; (3) there's a syntax error - check the browser console on your staging URL for error messages; (4) a library dependency (like GSAP) isn't loaded yet - ensure the library tag appears before your script tag.

How do I add custom CSS to Webflow?

For global CSS: Site Settings → Custom Code → Head Code, wrapped in <style> tags. For page-specific CSS: Page Settings → Head Code, also in <style> tags. For inline CSS targeting a specific layout section: HTML Embed component with a <style> block. Custom CSS inside an Embed renders live in the Webflow Designer, making it the fastest option for visual adjustments. Note that specificity rules still apply - if Webflow's generated CSS is more specific than your custom rule, your rule won't take effect. Use more specific selectors or add !important sparingly.

TRUSTED BY 460+ CATEGORY LEADERS

The partner that makes your marketing team unstoppable

Trusted by companies like Jasper, Stripe and Kajabi, we bring the expertise and reliability needed for high-stakes Webflow projects.
Webflow Professional Partner