CLI Reference
The AppFunnel CLI lets you scaffold, develop, build, and publish headless funnels from the command line.
Installation
npm install -g appfunnelCommands
appfunnel login
Authenticate via browser OAuth. Opens your default browser to authorize. Times out after 2 minutes if not completed.
appfunnel loginappfunnel whoami
Display current auth status including email, user ID, and token expiration.
appfunnel whoamiappfunnel init
Scaffold a new funnel project.
appfunnel initInteractive prompts:
- Select a project from your account
- Select a template
- Optionally configure products — select a store, choose a price, and set trial settings (3, 7, 14, 30, or 90 day options)
appfunnel dev
Start a Vite dev server with hot module replacement.
appfunnel dev
appfunnel dev -p 3000Options:
| Flag | Description | Default |
|---|---|---|
-p, --port <n> | Port number | 5173 |
Behavior:
- Real product prices are fetched from the API
- Tracking events are mocked and logged to the console
- Watches
src/pages/for file changes and triggers reload - Watches
appfunnel.config.tsfor changes and triggers reload - Auto-prompts for
projectIdif missing from config
appfunnel build
Create a production build.
appfunnel buildValidation checks:
- CLI and SDK major.minor versions must match
- All route targets must reference existing pages
- All condition variables must be declared in config
- System variables (
page.*,device.*, etc.) are always valid
Output:
The build outputs to dist/ containing manifest.json, JS chunks, CSS, and assets.
Size limits:
- 2MB total bundle size (warning)
- 500KB per JS file (warning)
Built-in query params are always included and do not need to be declared:
utm_source, utm_medium, utm_campaign, utm_content, utm_term
appfunnel publish
Deploy to AppFunnel hosting.
appfunnel publishRequires dist/manifest.json — run appfunnel build first.
The first publish creates a new headless funnel and writes the funnelId back to your config. Subsequent publishes update the existing funnel.
Error Codes
| Code | Description | Fix |
|---|---|---|
AUTH_REQUIRED | Not logged in | Run appfunnel login |
AUTH_EXPIRED | Token expired | Run appfunnel login |
CONFIG_NOT_FOUND | No appfunnel.config.ts | Run appfunnel init or cd to project |
INVALID_ROUTE | Route target doesn’t exist | Check to value matches a page filename |
UNDEFINED_VARIABLE | Undeclared variable in condition | Add to responses, data, or queryParams in config |
VERSION_MISMATCH | CLI/SDK version incompatible | Run npm install @appfunnel-dev/sdk@latest |
BUILD_NOT_FOUND | No dist/ directory | Run appfunnel build first |
FUNNEL_NOT_HEADLESS | Target funnel is wrong type | Create new headless funnel or remove funnelId |
BUNDLE_TOO_LARGE | Total bundle exceeds 2MB | Reduce dependencies, optimize assets |
PAGE_SIZE | JS file exceeds 500KB | Split code, reduce dependencies |
INVALID_PAGE | Page file has errors | Check definePage() syntax |
NO_PAGES | No .tsx files in src/pages/ | Create at least one page |
NO_PROJECTS | No projects in account | Create a project in the dashboard |
MISSING_PROJECT_ID | Config missing projectId | Set in config or run appfunnel dev |
MISSING_INITIAL_PAGE_KEY | Missing initialPageKey in appfunnel.config.ts. | Set in config |
API_ERROR | Backend request failed | Check network and auth |
PUBLISH_FAILED | Publish request failed | Check build output and retry |
window.appfunnel External API
A global API available at window.appfunnel for third-party script integration (e.g., GTM custom HTML tags).
Variables
// Read a single variable
window.appfunnel.getVariable('email')
// Write a variable
window.appfunnel.setVariable('email', 'user@example.com')
// Read all variables
window.appfunnel.getVariables()| Method | Description |
|---|---|
getVariable(id) | Read a variable by ID |
setVariable(id, value) | Write a variable value |
getVariables() | Read all variables as an object |
Navigation
window.appfunnel.getCurrentPageId()
window.appfunnel.goToNextPage()
window.appfunnel.goBack()| Method | Description |
|---|---|
getCurrentPageId() | Returns the current page key |
goToNextPage() | Navigate forward |
goBack() | Navigate back |
Products
window.appfunnel.selectProduct('price_abc123')| Method | Description |
|---|---|
selectProduct(id) | Select a product by ID |
Payments
window.appfunnel.getCustomerId()
window.appfunnel.isPaymentAuthorized()| Method | Description |
|---|---|
getCustomerId() | Returns the payment customer ID |
isPaymentAuthorized() | Returns whether payment has been authorized |
Events
// Subscribe to an event
window.appfunnel.on('page_view', (data) => {
console.log(data)
})
// Unsubscribe
window.appfunnel.off('page_view', callback)
// Emit a custom event
window.appfunnel.callEvent('custom_action', { key: 'value' })| Method | Description |
|---|---|
on(type, callback) | Subscribe to events |
off(type, callback) | Unsubscribe from events |
callEvent(name, data?) | Emit a custom event |
Misc
window.appfunnel.openUrl('https://example.com')| Method | Description |
|---|---|
openUrl(url) | Open a URL |