How to Migrate from Typeform to Formbricks in 2026
How to Migrate from Typeform to Formbricks in 2026
TL;DR
Typeform charges $25–83/month and caps responses on every plan. Formbricks is the open source alternative for in-app surveys, NPS, CSAT, and feedback collection — self-hosted, unlimited responses, and built specifically for product teams who want to survey users inside their app rather than redirect them to a separate form URL. This guide walks through the complete migration: deploying Formbricks, recreating your surveys, embedding the widget, configuring triggers, and connecting your data pipeline.
Key Takeaways
- Typeform Basic ($25/month) limits you to 100 responses/month — Formbricks self-hosted is unlimited
- Formbricks (AGPL-3.0, 9K+ stars) is built for in-app surveys — target specific users, trigger on events, show inside your product
- Question type mapping is 1:1 for most types — NPS, rating, multiple choice, open text all exist in Formbricks
- Webhooks let you pipe responses to Slack, Notion, Airtable, or your backend in real time
- The key difference: Typeform creates standalone form pages; Formbricks creates embedded surveys that appear inside your app to specific user segments
- Self-hosting on a $6/month VPS eliminates Typeform's $300–1,000/year bill
Why Teams Switch from Typeform
Typeform's pricing model has a fundamental mismatch for SaaS products. You pay per response — the more your product grows, the more you pay for user research. The tiers:
- Free: 10 responses/month
- Basic: $25/month — 100 responses/month
- Plus: $50/month — 1,000 responses/month
- Business: $83/month — 10,000 responses/month
A SaaS with 500 active users running a quarterly NPS survey needs 500 responses every 3 months (~170/month). That's the Plus plan at $50/month, $600/year — for surveys.
More critically, Typeform is designed for standalone form pages. Users leave your product, fill out a form on typeform.com, and return. For in-app NPS, post-feature surveys, or churn feedback modals, this creates friction. Formbricks solves both problems: no response limits, and surveys appear inside your product.
Step 1: Deploy Formbricks
Option A: Docker Compose (recommended for production)
# docker-compose.yml
services:
postgres:
image: postgres:15-alpine
restart: unless-stopped
environment:
POSTGRES_DB: formbricks
POSTGRES_USER: formbricks
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
formbricks:
image: ghcr.io/formbricks/formbricks:latest
restart: unless-stopped
ports:
- "3000:3000"
depends_on:
- postgres
environment:
DATABASE_URL: postgresql://formbricks:password@postgres:5432/formbricks
NEXTAUTH_SECRET: your-nextauth-secret-min-32-chars
NEXTAUTH_URL: https://surveys.yourdomain.com
NEXT_PUBLIC_WEBAPP_URL: https://surveys.yourdomain.com
# SMTP for survey invitation emails
MAIL_FROM: surveys@yourdomain.com
SMTP_HOST: smtp.resend.com
SMTP_PORT: 587
SMTP_SECURE_ENABLED: "1"
SMTP_USER: resend
SMTP_PASSWORD: re_your_api_key
# File uploads (local or S3)
UPLOADS_DIR: /home/nextjs/apps/web/uploads
volumes:
- uploads:/home/nextjs/apps/web/uploads
volumes:
postgres_data:
uploads:
# Start Formbricks
docker compose up -d
# Check logs
docker compose logs -f formbricks
Option B: One-Line Docker (quick test)
docker run -d \
--name formbricks \
-p 3000:3000 \
-v formbricks_data:/app/data \
-e NEXTAUTH_SECRET=your-secret-min-32-chars \
-e NEXTAUTH_URL=http://localhost:3000 \
-e NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000 \
ghcr.io/formbricks/formbricks:latest
Step 1b: Reverse Proxy with Caddy
# /etc/caddy/Caddyfile
surveys.yourdomain.com {
reverse_proxy localhost:3000
}
sudo systemctl restart caddy
# Caddy auto-provisions SSL via Let's Encrypt
Step 1c: Create your account
Navigate to https://surveys.yourdomain.com and create your admin account. You'll land on the Formbricks dashboard where you can create your first environment.
Step 2: Understand the Typeform → Formbricks Mental Model
Before recreating surveys, understand the key conceptual difference:
Typeform: A form is a URL. You share the link or embed an iframe. Anyone with the link can fill it out.
Formbricks: A survey is attached to an environment. Your app connects to the environment, identifies users, and Formbricks decides who to show which survey based on targeting rules.
This means Formbricks surveys are:
- Targeted — only specific users (new signups, churning users, power users) see specific surveys
- Triggered — surveys appear at the right moment (after completing a feature, after X days, on exit intent)
- Contextual — users fill them out without leaving your app
Step 3: Map and Recreate Your Surveys
Question Type Mapping
| Typeform Feature | Formbricks Equivalent | Notes |
|---|---|---|
| Welcome screen | Survey intro card | Same — configure in survey builder |
| Short text | Open text (short) | Identical |
| Long text | Open text (long) | Identical |
| Multiple choice | Multiple choice | Identical, supports multi-select |
| Single choice | Single choice | Identical |
| Rating (stars) | Rating (1–5) | Same concept |
| Opinion scale | Rating (1–10) | Extended range available |
| NPS | NPS question type | Native NPS with 0–10 scale |
| Dropdown | Single choice | Use single choice with many options |
| Date | Open text | No native date picker |
| File upload | ❌ | Not available — Typeform-only |
| Payment | ❌ | Not available — Typeform-only |
| Thank you screen | Thank you card | Same |
| Logic jumps | Survey logic | Available via condition builder |
| Hidden fields | Hidden fields | Supported for user attributes |
Recreating an NPS Survey
In Typeform, NPS was a standalone form. In Formbricks, NPS is a first-class survey type:
- Create Survey → Select "NPS" template
- Set the question: "How likely are you to recommend [Product] to a friend?"
- Add follow-up text question (auto-branches based on score):
- Score 0–6: "What's the main reason for your score?"
- Score 7–8: "What could we improve?"
- Score 9–10: "What do you love most?"
- Configure targeting: Run this survey every 90 days for active users
Recreating a Multi-Step Survey
Survey: Post-Onboarding Feedback (5 steps)
Step 1: Single choice
"How did you find out about us?"
Options: Search engine, Social media, Friend referral, Product Hunt, Other
Step 2: Rating (1–5)
"How easy was your onboarding experience?"
(Shows only if step 1 answer is NOT "Friend referral")
Step 3: Open text
"What was the most helpful part of onboarding?"
Step 4: Open text
"Is there anything that confused you?"
Step 5: Thank you card
"Thanks for your feedback! It helps us improve."
Step 4: Embed the Formbricks Widget
This is the main integration step. Add the Formbricks SDK to your app — it connects to your environment, identifies users, and renders surveys when triggered.
JavaScript (Vanilla / CDN)
<!-- Add before </head> or before </body> -->
<script type="text/javascript">
!function(){
var apiHost = "https://surveys.yourdomain.com";
var t = document.createElement("script");
t.type = "text/javascript";
t.async = true;
t.src = apiHost + "/js/formbricks.umd.cjs";
var e = document.getElementsByTagName("script")[0];
e.parentNode.insertBefore(t, e);
t.onload = function() {
window.formbricks.init({
environmentId: "your-environment-id",
apiHost: apiHost,
userId: "user_123", // Your user's ID
attributes: {
email: "user@example.com",
plan: "pro",
daysActive: "45",
hasCompletedOnboarding: "true",
},
});
};
}();
</script>
React / Next.js
npm install @formbricks/js
// app/providers.tsx (or your root layout)
'use client';
import { useEffect } from 'react';
import formbricks from '@formbricks/js/app';
interface FormbricksProviderProps {
userId: string;
userEmail: string;
userPlan: string;
}
export function FormbricksProvider({ userId, userEmail, userPlan }: FormbricksProviderProps) {
useEffect(() => {
formbricks.init({
environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENV_ID!,
apiHost: process.env.NEXT_PUBLIC_FORMBRICKS_HOST!,
userId,
attributes: {
email: userEmail,
plan: userPlan,
},
});
}, [userId]);
return null;
}
// app/layout.tsx
import { FormbricksProvider } from './providers';
import { auth } from '@/lib/auth';
export default async function RootLayout({ children }) {
const session = await auth();
return (
<html>
<body>
{children}
{session?.user && (
<FormbricksProvider
userId={session.user.id}
userEmail={session.user.email}
userPlan={session.user.plan}
/>
)}
</body>
</html>
);
}
Step 5: Configure Survey Triggers
Formbricks triggers replace Typeform's static URLs. Surveys appear automatically when conditions are met.
Trigger Types
Page visit: Show survey when user visits a specific URL path
// In Formbricks dashboard: Survey → Triggers → "Page URL"
// Condition: URL contains "/dashboard" and user hasn't seen this survey
Custom events: Trigger when user completes an action in your app
// Fire a custom event from your app
formbricks.track("completed_first_export");
formbricks.track("upgraded_to_pro");
formbricks.track("used_feature_X");
// In Formbricks dashboard: Survey → Triggers → "Code"
// Select: "completed_first_export"
Exit intent: Show survey when user is about to leave
// Configure in Formbricks dashboard:
// Survey → Triggers → "Exit Intent"
// Good for churn surveys on pricing or account pages
Targeting Filters (Audience)
// Show NPS survey only to:
// - Users with plan = "pro" OR "enterprise"
// - Who have been active for more than 30 days
// - Who haven't seen this survey in 90 days
// Set up via: Survey → Audience → Add Filter
// Attribute: "plan" equals "pro" OR "enterprise"
// Attribute: "daysActive" greater than "30"
Step 6: Set Up Webhooks
Pipe Formbricks responses to your existing data stack instead of logging into another dashboard.
// Formbricks webhook payload structure
{
"event": "responseFinished",
"data": {
"id": "resp_abc123",
"surveyId": "survey_xyz",
"surveyName": "NPS Survey - Q1 2026",
"personId": "person_user123",
"data": {
"nps_question": 9,
"followup_text": "Love the export speed!"
},
"meta": {
"userAgent": "...",
"url": "https://app.yourdomain.com/dashboard"
},
"createdAt": "2026-03-15T10:23:00Z"
}
}
// Next.js API route to receive Formbricks webhooks
// app/api/webhooks/formbricks/route.ts
import { NextRequest } from 'next/server';
export async function POST(req: NextRequest) {
const payload = await req.json();
if (payload.event === 'responseFinished') {
const { surveyName, data, personId } = payload.data;
// Log to your database
await db.survey_responses.create({
survey: surveyName,
userId: personId,
responses: data,
});
// Send NPS to Slack
if (surveyName.includes('NPS') && data.nps_question <= 6) {
await slack.postMessage({
channel: '#product',
text: `🚨 Detractor NPS (${data.nps_question}/10): "${data.followup_text}"`,
});
}
}
return new Response('ok');
}
Step 7: Cancel Typeform
- Export any historical response data from Typeform (Settings → Responses → Export CSV)
- Note all active form URLs and set up redirects if needed
- Cancel from Typeform Settings → Billing
What You Gain
- Unlimited responses — no plan-based caps
- In-app surveys — users never leave your product
- User targeting — show surveys to specific segments
- Event-based triggers — surveys appear at the right moment
- Full data ownership — responses stay in your database
- Webhook pipeline — real-time data to Slack, Notion, Airtable, your backend
What You Lose vs Typeform
- Polished standalone form UX — Typeform's conversational one-question-at-a-time UI is better for public-facing forms
- Advanced question types — file upload and payment collection aren't available
- Public form pages — Formbricks is designed for in-app, not shareable URLs (though link surveys are available)
- Non-technical setup — embedding the SDK requires adding code; Typeform is truly no-code
When to Keep Typeform
Formbricks is the right switch if you're running in-app surveys for your own product users. Typeform is better for:
- Public-facing lead generation forms
- External customer research (no app integration needed)
- File upload collection
- Beautiful branded form pages shared via URL
Cost Comparison
| Solution | Annual Cost |
|---|---|
| Typeform Basic (100 resp/mo) | $300/year |
| Typeform Plus (1K resp/mo) | $600/year |
| Typeform Business (10K resp/mo) | $996/year |
| Formbricks Cloud (free tier) | $0 |
| Formbricks self-hosted (VPS) | $60–120/year |
What Typeform Features Don't Exist in Formbricks
Being clear about what you're giving up prevents post-migration regret. Formbricks is an excellent tool for its design intent (in-app product surveys), but it genuinely does not replicate every Typeform capability.
Typeform's one-question-at-a-time conversational format is its signature UX for external-facing forms. A beautifully designed Typeform with animated transitions, full-screen question layouts, and branded visual design delivers a polished form experience that external respondents notice and appreciate. Formbricks' link surveys (non-in-app forms shared via URL) use a more conventional multi-field layout. For public-facing lead generation or research surveys where brand presentation matters, Typeform's visual quality is a real differentiator that Formbricks' link surveys don't match.
File upload fields are available in Typeform but not in Formbricks as of early 2026. If your forms collect file submissions (resumes, design files, documentation), Formbricks is not a complete Typeform replacement for those workflows. Alternative: use a dedicated file collection tool (Heyform supports file uploads) or build a custom file upload step in your application before triggering the Formbricks survey.
Payment collection via Stripe is available in Typeform's Business and higher plans. This enables simple checkout flows within a form — collecting payment card details and charging for products or event registrations. Formbricks has no payment collection feature. If your Typeform forms collect payments, you need a separate checkout tool (Stripe Payment Links, Lemon Squeezy, or a custom implementation) before migrating to Formbricks.
Typeform's Calculator field performs mathematical operations across form responses (calculating scores, totals, or personalized values based on answers). Formbricks has no equivalent built-in calculation field. Complex scoring logic must move to webhook-based processing: receive the Formbricks response via webhook and calculate scores in your application backend.
Typeform also has stronger third-party native integrations in its marketplace — direct HubSpot, Salesforce, Mailchimp, and Google Sheets integrations without requiring Zapier as middleware. Formbricks' native integrations are more limited; the robust integration path is via webhooks to a middleware tool (n8n, Zapier, Make.com). This adds a dependency for teams that relied on Typeform's direct integrations.
Building Equivalent Workflows in Formbricks
The section above covers what you can't replicate. This section covers how to rebuild the workflows that Typeform was actually handling for most teams, because the majority of Typeform use cases map cleanly to Formbricks with modest configuration work.
NPS surveys are the canonical Formbricks use case. In Typeform, an NPS survey was either a link you sent via email or embedded in a page. In Formbricks, NPS runs as an in-app survey triggered 30 days after signup (or based on whatever behavioral trigger is appropriate). The Formbricks NPS template includes the 0–10 rating question and a follow-up open text question, pre-configured for NPS methodology. Set the display frequency (don't show more than once per quarter), configure the audience (show only to active users, not churned ones), and deploy via the JavaScript SDK. The survey appears contextually in your product rather than requiring a separate email send.
Lead qualification forms that were Typeform embeds on landing pages move to either Heyform (for traditional form layout) or Typebot (for conversational format). Both tools offer embeddable forms with the same embed code approach Typeform used. If the lead qualification logic is complex (show enterprise pricing options to companies with 100+ employees, show SMB options to smaller companies), Typebot's visual conditional branching is the cleanest way to implement that logic.
Contact forms and registration forms are simple enough that any tool handles them. The migration for a basic name-email-message contact form is 15 minutes: recreate the fields in Heyform, copy the embed code to your website, update your webhook endpoint.
The webhook pipeline for getting Formbricks responses into your data stack typically replaces Typeform's native integrations. A Zapier or n8n workflow that receives the Formbricks webhook payload and writes to Google Sheets, sends to HubSpot, or posts to Slack replicates what Typeform's integrations did directly. The n8n approach is self-hosted, keeping your response data from flowing through Zapier's servers — aligning with the privacy motivation for leaving Typeform in the first place.
Related: Best Open Source Form Builders 2026 · Best Open Source Typeform Alternatives 2026 · How to Self-Host Formbricks
See open source alternatives to Typeform on OSSAlt.