Developers often need a fast way to collect data without building a full backend. Tally offers a zero‑code form builder that stores answers in JSON or Google Sheets. This guide shows how to create, embed, and customize Tally forms using plain HTML, React, and Node.js. Follow each step and you’ll have a production‑ready form in minutes.
Go to tally.so and click “Sign up”. Use Google or email. After confirming, you land on the dashboard.
In Settings → Integrations, toggle “Google Sheets”. Connect your Google account and pick a spreadsheet. If you prefer JSON files, enable “Webhooks” and point them to your server.
Click “New Form”. Give it a name, e.g., Bug Report. Add fields:
Open a field’s settings, enable “Min length” and “Max length”. For the “Severity” dropdown, set “Default value” to “Low”.
Click “Publish”. Copy the share link; it looks like https://tally.so/r/wXYZ12. You’ll embed this link later.
Paste the following code where you want the form to appear:
<iframe src="https://tally.so/r/wXYZ12" width="100%" height="600" frameborder="0"></iframe>
Wrap the iframe in a div that keeps the aspect ratio on mobile:
<div style="position:relative;width:100%;padding-bottom:150%;">
<iframe src="https://tally.so/r/wXYZ12"
style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;"
allowfullscreen></iframe>
</div>
Tally supports CSS variables. Add this to your page’s <style> block to change primary color:
:root {
--tally-primary:#0d47a1;
}
Create TallyForm.jsx:
import React from 'react';
const TallyForm = ({url, height=800}) => (
<div style={{position:'relative',width:'100%',paddingBottom:`${height/10}%`}}>
<iframe
src={url}
style={{position:'absolute',top:0,left:0,width:'100%',height:'100%',border:0}}
allowFullScreen
/>
</div>
);
export default TallyForm;
Use it in any component:
import TallyForm from './TallyForm';
function BugReportPage() {
return (
<div>
<h2>Report a Bug</h2>
<TallyForm url="https://tally.so/r/wXYZ12" height={900} />
</div>
);
}
Tally can post a message event after a successful submission. Add a listener:
useEffect(() => {
const handler = e => {
if (e.origin.includes('tally.so') && e.data.type === 'tallyFormSubmitted') {
alert('Thanks for your report!');
}
};
window.addEventListener('message', handler);
return () => window.removeEventListener('message', handler);
}, []);
In the form settings, go to “Integrations → Webhooks”. Add your endpoint URL, e.g., https://example.com/tally/webhook. Set “Method” to POST and content type to JSON.
Install Express:
npm install express body-parser
Then create server.js:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/tally/webhook', (req, res) => {
const data = req.body;
console.log('New submission:', data);
// Example: store in a local JSON file
const fs = require('fs');
const path = './submissions.json';
const existing = fs.existsSync(path) ? JSON.parse(fs.readFileSync(path)) : [];
existing.push(data);
fs.writeFileSync(path, JSON.stringify(existing, null, 2));
res.status(200).send('ok');
});
app.listen(3000, () => console.log('Webhook listening on port 3000'));
The JSON payload includes form_id, answers, and metadata. Example:
{
"form_id":"wXYZ12",
"answers":{
"title":"Crash on login",
"description":"App closes after entering credentials.",
"severity":"High"
},
"metadata":{
"submitted_at":"2026-06-28T14:22:10Z",
"user_ip":"203.0.113.45"
}
}
Below is a quick side‑by‑side of Tally, Google Forms, and Typeform for typical developer needs.
| Feature | Tally | Google Forms | Typeform |
|---|---|---|---|
| Self‑hosted option | Yes (JSON/Webhook) | No | No |
| Free submission limit | 1,000/mo | Unlimited | 100/mo |
| Custom CSS | Full | Limited | Partial (Pro only) |
| File upload | Yes | Yes (Google Drive) | Yes (Pro) |
| Embedding method | Iframe or API | Iframe only | Iframe / SDK |
| API/Webhook | Yes | No | Yes (Pro) |
For most dev projects that need quick data capture and a JSON endpoint, Tally wins on flexibility and price.
Tally is a lightweight, open‑source form builder that stores responses in a simple JSON file or Google Sheet. Developers like it because it requires no backend, works with static sites, and supports custom validation.
Yes. Use the <iframe> embed code or the Tally API to load the form as a component. The guide shows a minimal React wrapper.
Enable password protection in the form settings, limit submissions to authenticated users, and store data in a private Google Sheet with restricted sharing.
The free tier allows unlimited forms, up to 1,000 submissions per month, and basic styling. For higher volume or custom branding, upgrade to Pro.
Tally does not ship a CLI, but you can script form creation with the public API. The tutorial includes a Node.js example.
Using Tally saves developers time and money. You can create a form in minutes, embed it in any site, and pull the data into your own backend with a webhook. Follow the steps above to add a bug‑report form to a static page, a React app, or a Node.js service. The comparison table shows why Tally often beats Google Forms and Typeform for developer‑centric workflows.