Tally's free plan includes unlimited forms and unlimited submissions. Not a 100-response cap, not a 10-per-month teaser. Unlimited. Among form builders that is genuinely rare, and it is why Tally shows up in so many indie hacker stacks.
So this comparison does not get to be about price. If forms are the only thing you need, Tally's free tier wins and the post ends here. The argument for an alternative is about a boundary you cannot see in the form editor: the iframe your form renders inside, and everything on the other side of it that your submissions never reach.
Tally is free and unlimited for forms, and OperatorStack does not beat it on price or on form-building features. The difference is architectural. A Tally form lives in a cross-origin iframe from tally.so, so a submission cannot carry your visitor ID, your UTM data, or your referral code unless you wire each one in by hand. An OperatorStack form posts from your own page through the same script tag as your analytics, so every submission arrives already joined to the visitor who made it.
The Iframe Is the Whole Difference
Embedding a Tally form means loading their widget script and pointing it at a hosted form:
<script src="https://tally.so/widgets/embed.js"></script>
<iframe
data-tally-src="https://tally.so/embed/wAbC12"
width="100%"
height="320"
frameborder="0"
></iframe>
That iframe is a separate document on a separate origin. The browser's same-origin policy means your page's JavaScript cannot read what the visitor typed, cannot know when they submitted, and cannot attach anything to the submission on its way out. The isolation is the browser doing its job correctly. It is also the reason the data arrives in Tally's dashboard with no memory of the page it came from.
An OperatorStack form is markup you own, submitted through the SDK that is already on the page:
<form id="feedback">
<input name="email" type="email" required />
<input name="use_case" type="text" />
<button type="submit">Send</button>
</form>
<script>
document.getElementById("feedback").addEventListener("submit", async (e) => {
e.preventDefault();
const fields = Object.fromEntries(new FormData(e.target));
await OperatorStack.submitForm("frm_abc123", fields);
});
</script>
No iframe, no second origin. The submission is a POST from your own page to /v1/f/frm_abc123.
submitForm() attaches the visitor ID automatically. It is the same ID the analytics events use, which is what makes a submission joinable to the pageviews that preceded it. You do not pass it and you cannot forget it.
Feature Comparison
| Feature | Tally | OperatorStack |
|---|---|---|
| Unlimited free submissions | Yes | Free tier limits |
| Visual block editor | Yes | No |
| Conditional logic / branching | Yes | No |
| Multi-page forms | Yes | No |
| Calculations and payments | Yes | No |
| Renders in an iframe | Yes | No |
| Field schema setup | Manual, per field | Inferred on submit |
| Shares a visitor ID with analytics | No | Yes |
| Website analytics | No | Yes (cookie-free) |
| Waitlist signup + referrals | No | Yes |
| Unified contact list | No | Yes |
| Live chat / AI chat | No | Yes |
What Tally Does Better
Plenty, and it is worth being specific rather than polite about it.
The block editor is the best in its class for the price. Typing / gives you a field picker that feels like Notion, and building a fifteen-question form takes a few minutes with no code. Conditional logic lets you branch the question flow on an answer. Calculated fields, payment collection through Stripe, multi-page flows with progress bars, partial submission capture on the Pro plan: OperatorStack has none of this and is not building toward it.
If your form is a real survey, a job application, or an order form, use Tally. This is not a close call.
Do not read "schema-on-write" as a nicer form builder. It is the absence of a form builder. If you want to drag fields around in a visual editor, OperatorStack will feel like a downgrade, because for that job it is one.
Where the Submission Actually Lands
This is the part the feature table understates.
A Tally submission lands in Tally. To get it anywhere else, you connect an integration: Google Sheets, Notion, Airtable, Slack, a webhook, or Zapier for anything not on the native list. Each integration is a pipe you configure and then have to remember exists. The row that arrives at the other end contains the answers the visitor typed and nothing about who they are.
An OperatorStack submission lands in the contact list your waitlist signups already live in, matched on email. If someone joined your waitlist in June and filled out a feedback form in August, that is one contact with two events attached, not two rows in two tools that you would have to join by hand in a spreadsheet.
Schema-on-write is what makes this cheap to set up. You never predefine fields:
// First submission creates the schema
await OperatorStack.submitForm("frm_abc123", {
email: "founder@example.com",
team_size: "1-5",
});
// Adding a field later needs no dashboard change
await OperatorStack.submitForm("frm_abc123", {
email: "founder@example.com",
team_size: "1-5",
biggest_blocker: "pricing",
});
The second call adds biggest_blocker to the form's inferred schema. In Tally, adding a question means opening the editor, adding the block, saving, and re-checking that your downstream integration still maps the new column.
Attribution: Hidden Fields vs Nothing to Do
Say you want to know which traffic source produced your best-qualified form responses.
In Tally, you build it. Define a hidden field for each parameter you care about, then append them to the embed URL and populate them from your own page script:
<iframe data-tally-src="https://tally.so/embed/wAbC12?utm_source=producthunt&ref=abc123"></iframe>
Hardcoding is wrong, so in practice you read the real values off window.location.search and rewrite data-tally-src before the widget script initializes. It works, and it is per field, per form, and quietly broken the day someone copies a stale embed snippet into a new landing page.
In OperatorStack there is no step. The script tag already recorded the visitor's first-touch referrer and UTM parameters, and submitForm() sends the visitor ID with the submission, so the join happens server-side. If the visitor arrived through a referral link, the same is true of the referral code:
const referral = OperatorStack.getReferralLink();
// { referral_code: "abc123", referral_link: "https://yoursite.com/?ref=abc123" }
The test for whether attribution is real: can you answer "which page did this person read before they filled out the form" without exporting two CSVs? With an iframe form, the answer is no, regardless of how many hidden fields you wired up.
Pricing, Honestly
| Plan | Tally | OperatorStack |
|---|---|---|
| Free | Unlimited forms and submissions | Free tier, all core features |
| Paid entry | About $29/month (less billed annually) | Paid tiers for volume |
| What paid adds | Branding removal, custom domains, partial submissions, form analytics | Higher volume |
Tally's free tier is more generous than OperatorStack's on form submissions alone. That is the honest read, and if forms are your only requirement it is the deciding number.
The comparison changes when you count what else you would otherwise be paying for. A pre-launch stack usually needs forms plus a waitlist, plus analytics, plus some referral mechanic. Tally covers the first. The other three are separate tools, separate script tags, and separate contact lists.
Which One to Pick
Pick Tally if the form is the product: long surveys, branching logic, payments, job applications, anything where the editing experience and the respondent experience matter more than what happens to the data afterward. Its free tier is excellent and you should use it.
Pick OperatorStack if the form is one of five things you need before launch and you want the submissions attached to the same contacts your waitlist and analytics already know about. The forms are plainer. The data is joined.
Running both is a legitimate answer. A Tally survey linked from your site and an OperatorStack script tag on the page do not conflict, and you get the good editor for the long form and the joined data for everything else.
Frequently Asked Questions
Is Tally actually free?
Yes, and unusually so. Tally's free plan includes unlimited forms and unlimited submissions, which is rare among form builders. The paid Pro plan (around $29 a month, less on annual billing) buys branding removal, custom domains, partial submission capture, and richer form analytics. If you only need forms, Tally's free tier is hard to beat on price.
Why would I switch from Tally if it is free?
Not for pricing. The reason is where submissions land. A Tally form renders in a cross-origin iframe served from tally.so, so your page cannot see the submission and Tally cannot see your page. Your form responses live in one system, your traffic data in another, and your waitlist in a third, with no shared identifier to join them.
Can Tally capture UTM parameters?
Yes, through hidden fields, but you wire it yourself. You define a hidden field in the form editor, then append it to the embed URL as a query parameter and populate it from your page's own JavaScript. It works. It is manual per field, per form, and it breaks silently if you change your embed snippet later.
Does OperatorStack have a visual form builder like Tally?
No. OperatorStack forms are schema-on-write: you post whatever fields you want to a form key and the schema is inferred from the first submission. There is no block editor, no conditional logic, and no multi-page flows. You write your own markup and style it with your own CSS.
Can I use Tally and OperatorStack together?
Yes, and for some setups that is the right call. Keep Tally for a long survey with branching logic, and use OperatorStack for the waitlist, analytics, and the short forms that need to feed your contact list. One script tag on the page does not conflict with a Tally embed.