Custom Java script Code for saving Form submission data in a CMS list

Hello,

I am trying to write Java Script code for storing the data submitted through a form in a CMS collection list in webflow. I have some Javascript development experience. Are there any example code available somewhere for me to get started?
Any support will be appreciated.
Please note that I am developing the site for a non-profit organization and they don’t have budget to spend on third party solutions using Zapier, Make etc.


Here is my site Read-Only: LINK
(how to share your site Read-Only link)

Hi there @gopal_aparna! Great question. Webflow does not natively support writing or updating CMS items directly from frontend JavaScript (like from a form submission). For security and performance reasons, all CMS content in Webflow is managed via the Canvas, the Editor, or the Webflow CMS API—which must be accessed via server-side code or a secure backend (to keep your API token safe). That said, here’s a basic outline of how you can achieve what you want without using paid third-party tools like Zapier or Make:

What you’ll need:

  • A form on your Webflow site
  • A backend endpoint (ie. on Firebase Functions, Supabase, Vercel, or another free tier service). This would allow you to make API calls to Webflow
  • The Webflow CMS API
  • Your CMS Collection ID and API Token (from Webflow Project Settings > Integrations)

How it could work:

  1. User submits a Webflow form
  2. Custom JavaScript catches the submission and sends the form data via fetch() to your backend
  3. Your backend receives the request, uses your Webflow CMS API token (securely stored) to create a new CMS item
  4. Webflow CMS updates with the form data

If you try to call the Webflow CMS API directly from the frontend:

  • You’ll expose your private API token (a major security risk)
  • CORS and authentication will likely block the request

So, a backend service (even on a free tier) is required to securely act as a middleman between your site and the CMS API. Hope this helps!

2 Likes

@gopal_aparna adding to Veronica’s notes, since you’re familiar with JS you might look at using Netlify’s functions, which can be written and deployed as JS. into a free Netlify middle tier. This protects your API key and prevents CORS issues.

Note however, there’s no “built in” security in these types of arrangements. If you put your serverless function URL directly in the form Action field, there is a high risk of spambots picking it up and sending you spam submissions.

Most likely, you’re better off using Webflow’s native forms and then the form submission Webhook so that results are already SPAM-checked and your middle tier isn’t directly exposed in the HTML.

Also, if you only have only 1 or 2 “endpoints” and relatively low traffic, you might want to check out Make’s automations. I believe the free plan gives you 2 automations, and a useful number of executions.

2 Likes

Thank you for the responses. I am trying a solution using Node.js (via webhook). I will post here if I am successful.

Hello,
I tried installing an Express.js API in vercel for getting the form data and inserting the record to CMS. That is not working.
API code :

export default async function handler(req, res) {
  // Add CORS headers for cross-origin requests
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

  // Handle preflight OPTIONS request
  if (req.method === "OPTIONS") {
    return res.status(200).end();
  }

  // Log the request method for debugging
  console.log("Request method:", req.method);
  console.log("Request headers:", req.headers);
  console.log("Request body:", req.body);

  // Only allow POST requests
  if (req.method !== "POST") {
    return res.status(405).json({
      error: "Method not allowed",
      received: req.method,
      expected: "POST",
    });
  }

  try {
    const formData = req.body.data || req.body;
    console.log("Form data received:", formData);

    if (!formData) {
      return res.status(400).json({ error: "Invalid form data" });
    }

    const { Name, SchoolName, City, Country } = formData;

    // Validate required environment variables
    if (!process.env.WEBFLOW_API_KEY || !process.env.WEBFLOW_COLLECTION_ID) {
      console.error("Missing required environment variables");
      return res.status(500).json({ error: "Server configuration error" });
    }

    // Create CMS item via Webflow API using fetch
    const response = await fetch(
      `https://api.webflow.com/v2/collections/${process.env.WEBFLOW_COLLECTION_ID}/items`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.WEBFLOW_API_KEY}`,
          "accept-version": "2.0.0",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          isArchived: false,
          isDraft: false,
          fieldData: {
            Name,
            Slug: `submission-${Date.now()}`,
            SchoolName,
            City,
            Country,
          },
        }),
      }
    );

    if (!response.ok) {
      const errorData = await response.text();
      console.error("Webflow API error:", response.status, errorData);
      return res.status(response.status).json({
        error: "Failed to create CMS item",
        details: errorData,
      });
    }

    const responseData = await response.json();
    console.log("CMS item created:", responseData);

    res.status(200).json({
      success: true,
      data: responseData,
    });
  } catch (error) {
    console.error("Error creating CMS item:", error.message);
    res.status(500).json({
      error: "Internal server error",
      message: error.message,
    });
  }
}

In webflow site, I created a test form and added a webhook.
But, it is not working and I think the error is that a GET request is being sent to the API instead of a POST. When I checked my form setting, it is POST. Not sure where the problem is. Also, I can see that the webhook is available for all buttons in all forms. My requirement is to have this functionality for a specific form. How to fix this?

Read only link to the website - website readonly link

the test form that was created - https://pytf-new-merged-and-improved-site.webflow.io/test-multistep-form

@Veronica-Webflow @memetican

You’ve built a standard form, with no custom Action, which means that the submit will be handled directly by Webflow**, bot-detected, SPAM-checked, and stored with form data.
If the submission passes those tests, it will any form_submission API Webhooks that you’ve defined, which will call the designated endpoints with HTTP POST.

** The exception of course is if you’ve written client-side JS code that intercepts the form submission and handles it specially.

So the first thing is probably to make sure that the form data is being captured and not classified as SPAM. You can check your received submissions under site settings for that.

If you see them, than double-check your form_submission webhook and URL that it’s calling. From there it’s just debugging your server side code.

1 Like

I was able to implement this solution in vercel. Thanks.