Build a Custom Web2App Funnel With Code

Simon Steilgaard· Founder of Appfunnel· Mar 12, 2026

Engineering7 min read

Most funnel builders are great until they're not.

A web2app funnel is a web-based onboarding and checkout flow that converts visitors into paying app subscribers, typically used by mobile apps to bypass App Store fees and own the entire conversion experience. These funnels handle everything from quiz-style onboarding to Stripe checkout to deep linking users into your app.

You start with a template, tweak the colors, swap the copy, and ship. It works. Then your designer hands you a mockup that doesn't fit the grid. Your growth team wants a checkout flow the editor doesn't expose. You need conditional logic that goes beyond "if answer A, show page B." And suddenly you're fighting the tool instead of building the funnel.

If you've used FunnelFox, Web2wave, or any similar no-code funnel builder, you've probably hit this wall. With most tools the answer is: keep hacking around limitations, or rebuild it yourself. Appfunnel gives you a third option: the funnel you built by clicking is already real code you can open.

The Problem With Building a Web2App Funnel From Scratch

Building your own web funnel sounds simple. It's just a few pages with a form and a checkout, right?

Then you start listing what you actually need:

  • Stripe integration with subscription management, trials, and discount logic
  • Session tracking that persists across page reloads and return visits
  • Attribution capture for Meta fbp/fbc, Google gclid, TikTok ttclid, and UTM params
  • Analytics events for every page view, checkout start, and purchase
  • A/B testing infrastructure to experiment on different flows
  • RevenueCat sync so your app knows who paid on the web
  • Deep linking to get users from web checkout into your app
  • Variable persistence so user responses survive refreshes and are available downstream

That's not a weekend project. That's months of infrastructure work before you write a single line of funnel UI code. And then you have to maintain it.

Start Plug-and-Play, Open the Repo When You Need To

The fastest way to ship a funnel on Appfunnel is still the builder: describe your pages, get a live preview, publish. But everything you build there is real React underneath: the same funnel.ts spine and page components you'd write by hand. When point-and-click runs out, you pull the repo down and keep going. You own the frontend; the infrastructure stays handled.

One Funnel, One File

Your whole funnel is a single typed file. It holds the pages and their routing, the responses you capture, the products you sell, and the checkout provider:

// funnel.ts
import { defineFunnel } from '@appfunnel-dev/sdk'
 
export const config = defineFunnel({
	id: 'funnel',
	checkout: 'stripe',
	responses: {
		goal: { type: 'string', default: '' },
	},
	// Products are SLOTS: a local name your pages reference → a catalog product.
	products: { plan: null },
	pages: [
		{ key: 'goal', type: 'default' },
		{ key: 'plan-quiz', type: 'default' },
		{ key: 'paywall', type: 'paywall' },
		{ key: 'finish', type: 'finish' },
	],
})

Add next: [{ to, when }] to any page to branch on a response. The rest runs top to bottom.

Writing Funnel Pages in React

Each page is a .tsx file with whatever UI you want: your design system, your animations, your layout. No templates, no drag-and-drop constraints. SDK hooks handle state and navigation:

// pages/goal.tsx
import { definePage, useNavigation, useResponse } from '@appfunnel-dev/sdk'
 
export default definePage(function Goal() {
	const { next } = useNavigation()
	const [goal, setGoal] = useResponse('goal')
 
	return (
		<section className="flex flex-col items-center gap-6 p-8">
			<h1 className="text-3xl font-bold">What's your goal?</h1>
			{['weight-loss', 'muscle-gain', 'better-sleep'].map((option) => (
				<button
					key={option}
					className={`w-full rounded-xl p-4 text-lg ${
						goal === option
							? 'bg-blue-600 text-white'
							: 'bg-gray-100'
					}`}
					onClick={() => {
						setGoal(option)
						next()
					}}
				>
					{option.replace('-', ' ')}
				</button>
			))}
		</section>
	)
})

That's a real page. It stores the user's response and moves to the next step. You didn't set up any state management, routing logic, or analytics instrumentation.

Built-in Payments, Analytics & Attribution

Behind the scenes, the SDK does everything you'd otherwise build yourself. A paywall page reads a product slot and renders checkout:

// pages/paywall.tsx
import { definePage, useProduct, Checkout } from '@appfunnel-dev/sdk'
 
export default definePage(function Paywall() {
	const product = useProduct('plan')
	if (!product) return null
 
	return (
		<section>
			<h1>{product.name}</h1>
			<p>{product.price.formatted}</p>
			<Checkout product="plan" surface="element" />
		</section>
	)
})

useProduct loads pricing from your catalog, <Checkout> handles Stripe with trials and 3D Secure, and session data, attribution parameters, and user responses are persisted automatically. When a purchase completes, RevenueCat is updated for you.

Deploy With the Appfunnel CLI

The CLI handles the full lifecycle. Pull the funnel down, work locally against real data, and push it back:

# Authenticate
appfunnel login --token <your-token>
 
# Pull an existing funnel into a local repo
appfunnel pull my-funnel
 
# Start the dev server with hot reload
appfunnel dev
 
# Push your changes, then publish the draft live
appfunnel push && appfunnel publish

Your funnel is served from Appfunnel's infrastructure. No Vercel, no Netlify, no Docker. Just push and publish and it's live.

Builder or Code: When to Use Which

You don't have to pick up front. It's the same funnel either way. Here's how the two ends feel:

The builderOpening the repo
Setup timeMinutesA local pull
Design flexibilityLive previewUnlimited (React)
Checkout customizationStandard flowsFull control
Programmatic logicVisual branchingAny JavaScript
Version controlManaged for youGit-based
Team requirementNo developers neededFrontend developer or agent
Best forRapid validationProduction-grade custom funnels

Stay in the builder when you're validating a concept quickly, your team doesn't have frontend developers, or the visual editor covers what you need.

Open the repo when your design demands custom animations and branded components, your checkout flow needs multi-product bundles or conditional pricing, you need programmatic control with custom validation, or you want your funnels in version control, or handed to your coding agents.

Getting Started

Authenticate, pull a funnel, and start building:

npm install -g appfunnel
appfunnel login --token <your-token>
appfunnel pull my-funnel
cd my-funnel && npm install
appfunnel dev

Your funnel runs locally with hot reload. Every page is a React component. Every interaction is a hook. When you're done, appfunnel push && appfunnel publish puts it live.

The SDK handles payments, analytics, attribution, A/B testing, and RevenueCat sync. You build the funnel, at whatever level of control you need.

Ready to build your first custom web2app funnel? Head to the developer platform for the SDK, CLI, and MCP reference, or get started free and open the repo when you're ready.

Frequently Asked Questions

What is a web2app funnel?

A web2app funnel is a web-based onboarding and payment flow that converts website visitors into paying app subscribers. Instead of relying on the App Store or Google Play for payments (and paying 15-30% commission), you handle checkout on the web via Stripe and then deep link users into your mobile app. The funnel typically includes quiz-style onboarding, a paywall, and Stripe checkout.

Can I use my own design system?

Yes. Every page is a standard React component. You can use Tailwind, CSS Modules, styled-components, or any other styling approach. The SDK provides hooks for data and navigation. It never touches your UI.

How does Appfunnel handle payments in code?

The <Checkout> component renders Stripe against a product slot you reference with useProduct. It supports subscriptions, free trials, discount codes, and 3D Secure. When a purchase completes, the transaction syncs to RevenueCat automatically so your app can unlock premium features immediately.

What's the difference between Appfunnel and FunnelFox or Web2wave?

FunnelFox and Web2wave are no-code funnel builders: you design funnels in a visual editor using pre-built templates, and that's where it ends. Appfunnel is a plug-and-play builder where every funnel is real React underneath: build by clicking, then open the repo, write pages as code, or hand it to your agents over MCP, while Appfunnel handles payments, analytics, attribution, and deployment.

Do I need to set up my own hosting?

No. When you run appfunnel publish, your funnel is deployed to Appfunnel's CDN-backed infrastructure. There's no need to configure Vercel, Netlify, AWS, or any other hosting provider.

Share this article

Written by

Simon Steilgaard

Founder of Appfunnel

Put the funnel before the App Store

Quizzes, paywalls, and web checkout with full attribution. 2–5% in fees instead of 30%.