Ninja Forms to Google Sheets: Step-by-Step Without Zapier
Send Ninja Forms submissions directly to a Google Sheet without paying for Zapier, the Ninja Forms Google Sheets add-on, or any other middleware.
In This Guide
- Three Ways to Connect Ninja Forms to Sheets
- How the Direct Webhook Approach Works
- Step 1: Build the Sheet
- Step 2: Deploy the Apps Script
- Step 3: Connect Ninja Forms to the Webhook
- Working With Ninja Forms Field Types
- Conditional Routing: One Form, Multiple Sheets
- Keeping Spam Out of Your Sheet
- Edge Cases: File Uploads, Repeaters, Long Text
- Beyond the Basic Connection
- Recap and Next Steps
- Frequently Asked Questions
Three Ways to Connect Ninja Forms to Sheets
Ninja Forms is a long-running WordPress form plugin with a healthy add-on ecosystem. There are three common paths to Google Sheets and they have wildly different costs.
Path one is the official Ninja Forms Google Sheets add-on. It's licensed annually as part of a membership tier - typically $99-$499/year depending on the bundle. Reliable, but expensive for what it does.
Path two is Zapier. The Ninja Forms-to-Zapier add-on plus a Zapier Starter plan runs about $360/year. You also get all the Zapier downsides: polling delays, per-task fees, third-party data exposure.
Path three is a direct webhook to a Google Apps Script. One-time cost, no recurring fees, no middleware. This is what we cover here.
How the Direct Webhook Approach Works
Ninja Forms fires an action hook (`ninja_forms_after_submission`) on every successful submission. A small WordPress plugin listens for that hook, extracts the field values, and posts them to a Google Apps Script URL. Apps Script writes the row to your sheet.
No Zapier in the middle. No third-party automation account to log into. The submission moves from your visitor's browser to your WordPress server to your Google Sheet in one hop. SheetLink Forms' Ninja Forms integration implements this pattern.
This is the same architecture we recommend for every WordPress form builder - the only differences between integrations are which hook to listen on and how to read the field values.
Step 1: Build the Sheet
Create a fresh Google Sheet. Name the tab something specific - "NF Contact Submissions" instead of just "Sheet1." Add column headers in row 1 that match your form fields plus a few system fields: Submitted At, Form ID, IP Address (if you collect it), and any UTM parameters you track.
Freeze the header row (View > Freeze > 1 row) so it stays visible when you scroll. Apply formatting to date columns now - it's much easier than fixing 5,000 rows later. If you plan to do filtering or pivot tables, format the entire data range as a Google Sheets table (Data > Table) so new rows inherit formatting automatically.
Step 2: Deploy the Apps Script
From your sheet, open Extensions > Apps Script. Paste a webhook receiver script. The plugin you use should provide the script - SheetLink Forms includes a one-click "Generate Apps Script" feature that produces a script tailored to your sheet ID and column layout.
Click Deploy, choose Web App, set "Execute as" to your account and "Who has access" to "Anyone." Copy the deployment URL. Save the URL somewhere safe - you'll paste it into WordPress in the next step. If you ever lose the URL, you can find it again under Deploy > Manage Deployments.
Step 3: Connect Ninja Forms to the Webhook
Install SheetLink Forms (or your chosen Ninja Forms-to-Sheets plugin). Open the plugin settings. Paste the Apps Script URL into the destination field. Run the test connection - if everything is wired up, the test creates a test row in your sheet that you can delete afterward.
Next, link a specific Ninja Form to the destination. The plugin reads your Ninja Forms field definitions and shows them in a mapping UI. Drag and drop, or accept the auto-mapping. Submit a test entry on the front end. Watch it land in the sheet.
If the test row never appears, the most common cause is the Apps Script "Who has access" setting being on "Only myself." Switch it to "Anyone" and redeploy.
Working With Ninja Forms Field Types
Ninja Forms has a wider field-type vocabulary than most form builders. A handful need special handling.
List fields (radio, select, multiselect) export the calculated value, not the label, by default. If you want labels in the sheet, configure the plugin to use the human-readable label.
Date and time fields export as ISO strings. Format the destination column as a Date in Google Sheets so they display correctly.
Checkbox fields export "1" or "0" by default. Most teams want "Yes" or "No" - the plugin offers a translation option.
Calculation fields export the computed total, which is exactly what you want for sales or quote forms. Lead tracking workflows often use these for deal-size segmentation.
Conditional Routing: One Form, Multiple Sheets
A common need: route Enterprise leads to a Sales sheet and Self-Serve leads to a Marketing sheet, based on a "Company Size" radio field. The direct-webhook approach supports this without Zapier filters.
In SheetLink Forms, set up two destinations (one Apps Script per target sheet). Define a routing rule on the form: "if company_size == 'Enterprise' send to Sheet A, else send to Sheet B." Submissions split automatically.
We cover the full pattern in conditional routing for WordPress forms.
Keeping Spam Out of Your Sheet
Once your form is connected to Sheets, every spam submission also lands in your sheet. Bots will find your form within weeks of going live. There are three layers of defense.
First, harden the form: enable Ninja Forms' built-in honeypot, add Cloudflare Turnstile or hCaptcha, and require a real email format on the email field. Second, filter at the plugin layer: SheetLink Forms can drop submissions from known-bad IP ranges or reject submissions that fail an Akismet check. Third, build a sheet-level filter: keep all submissions in a "Raw" tab and use a QUERY formula to populate a "Clean" tab with only legitimate entries.
For the full playbook, see filtering spam before it pollutes your sheet.
Edge Cases: File Uploads, Repeaters, Long Text
A few Ninja Forms field types need extra care.
File uploads can't be embedded in a cell. The plugin should write the file URL plus filename, size, and MIME type to dedicated columns. We cover the full approach in logging file upload metadata.
Repeater fields (Ninja Forms calls these "Repeating Fieldsets") have two strategies: flatten into a single cell with separators, or expand each repeater row into its own sheet row. Choose flatten for simple cases and expand when you need to query each item independently.
Long text (textarea fields) work fine but Sheets has a 50,000-character cell limit. If you collect long-form content like job applications, truncate or split into multiple cells before writing.
Beyond the Basic Connection
A direct Ninja Forms-to-Sheets connection is the foundation. Real value comes from what you build on top.
Layer in AI lead scoring to grade every submission so reps focus on the hottest leads first. Fan out to your CRM with the CRM Fan-Out add-on so HubSpot and Sheets stay in sync. Build a Google Sheets dashboard with charts and pivot tables that update in real time. None of this requires Zapier.
Recap and Next Steps
You replaced a $360/year Zapier subscription with a one-time plugin purchase, eliminated a third party from your data path, and reduced submission-to-sheet latency from minutes to seconds.
The same architecture works for every form on your site - Contact Form 7, Gravity Forms, WPForms, Fluent Forms, Formidable, Elementor Pro, and WooCommerce checkouts. Once you have the Apps Script set up for one form, additional forms reuse the same infrastructure.
Frequently Asked Questions
Do I need the Ninja Forms Google Sheets add-on?
No. The direct webhook approach works with the free version of Ninja Forms and does not require any official Ninja Forms membership tier.
Will this work with Ninja Forms multi-part forms?
Yes. Multi-part forms fire the same submission hook on completion. All collected fields across all steps are sent to Sheets in a single row.
How do I handle file uploads?
File uploads are stored on your WordPress server. The plugin writes the file URL plus metadata (filename, size, MIME type) to your sheet. You cannot embed the file itself in a cell.
Can I send the same submission to multiple sheets?
Yes. SheetLink Forms supports multi-destination routing - the same Ninja Forms submission can write to two or more sheets simultaneously, each with its own field mapping.
How does conditional routing work?
You define rules based on field values - for example, "if budget > $10,000 send to Sales sheet, else send to Marketing sheet." The plugin evaluates rules at submission time and posts to the matching destination.
What if my Google Apps Script hits a quota limit?
Free Google accounts get 20,000 URL fetch calls per day. Most WordPress sites use 50-500 per day, so quota is rarely an issue. If you do hit it, upgrade to Google Workspace which raises the limit to 100,000.
How is this different from Zapier?
Direct webhook delivery is faster (seconds vs. minutes), cheaper (one-time purchase vs. monthly fees), and removes a third party from your data path. Zapier still wins when you need to chain many non-Sheets apps in a single workflow.
Will future Ninja Forms updates break the integration?
The integration uses a stable Ninja Forms action hook (`ninja_forms_after_submission`) that has been in place for years. Major Ninja Forms releases sometimes change internal APIs, but plugin maintainers test against new versions before each release.
Stop Paying for the Ninja Forms Sheets Add-On
Direct webhook delivery. Unlimited submissions. One-time payment.