> ## Documentation Index
> Fetch the complete documentation index at: https://docs.funeli.top/llms.txt
> Use this file to discover all available pages before exploring further.

# Components: paywall

> Reference for the Funeli paywall components: what each one is for, every setting with its type and default, and a working example.

A paywall needs PlanSelector, a checkout Button and LegalText. Add these components to a step in the editor and change their settings in the inspector, or ask an agent to; the settings below are the same in both.

## Plan selector

Type `PlanSelector`. Compares subscription plans. Radio cards for plans from funnel.pricing.plans (title, was/first-charge price, trial or intro label, "then \$X every N", per-day chip, badge); the selection feeds the checkout Button and \{\{plan\_\*}} placeholders. Required on every paywall; shows "No plans configured" when empty. Edit prices with set\_plan, not here.

| Setting | Type | Required | Description |
| - | - | - | - |
| `planIds` | string\[] | no | Plan ids from funnel.pricing.plans to show, in this order (unique, \<=8); empty = all plans in their pricing order. Aim for 2-3 plans Default: `[]`. |
| `defaultPlanId` | string | no | Plan preselected on load, normally the badged middle plan; omit = first shown. Must be one of planIds when planIds is set, otherwise it is ignored. A plan selected on an earlier step stays selected only if this selector shows it |
| `showPerDay` | boolean | no | Show the per-day price chip on each card, an anchoring device for long plans; hide it when plans are priced per day already Default: `true`. |
| `layout` | "vertical" \| "horizontal" | no | vertical (default) stacks cards; horizontal puts them side by side (best with 2-3 plans) |
| `priceDisplay` | "default" \| "introToRenewal" | no | introToRenewal shows "intro price → renewal price" on one line from the plan's intro and price fields |
| `cardStyle` | object | no | Overrides each plan's card style on this screen, field by field |

> [accordion] Example
>
> ```json theme={null}
> {}
> ```

## Timeline

Type `Timeline`. Maps trial dates and milestones. 2-6 vertical milestones joined by a line (first dot filled); titles accept \{\{date:+N}}. Dots show the step number when no icon is set. Static; use for trial transparency on the paywall.

| Setting | Type | Required | Description |
| - | - | - | - |
| `title` | string | no | Heading above the timeline, keep \<=40 chars |
| `items` | object\[] | yes | 2-6 milestones in chronological order joined by a line; the first dot is filled |

> [accordion] Example
>
> ```json theme={null}
> {
>   "title": "How your trial works",
>   "items": [
>     {
>       "icon": "lock",
>       "title": "Today",
>       "text": "Get full access to your plan"
>     },
>     {
>       "icon": "calendar-check",
>       "title": "{{date:+5}}",
>       "text": "We remind you before the trial ends"
>     },
>     {
>       "icon": "bell",
>       "title": "{{date:+6}}",
>       "text": "Final reminder before renewal"
>     },
>     {
>       "icon": "star",
>       "title": "{{date:+7}}",
>       "text": "Your subscription starts; cancel anytime before"
>     }
>   ]
> }
> ```

## Countdown timer

Type `CountdownTimer`. Counts down to offer expiry. mm:ss from durationSeconds, restarting on each page load (not a real deadline, so keep the claim honest); expiredLabel replaces it at zero. sticky (default) pins it to the top bar; optional compact button. Exposed as role=timer.

| Setting | Type | Required | Description |
| - | - | - | - |
| `durationSeconds` | integer | no | Seconds to count down from (30-3600), restarting on every page load or revisit; it is not a real deadline, so keep the claim honest Default: `600`. |
| `label` | string | no | Text before the clock, keep \<=30 chars to fit beside it; literal Default: `"Discount is reserved for"`. |
| `expiredLabel` | string | no | Text that replaces label and clock at 00:00, keep \<=40 chars; literal Default: `"Your discount is still available"`. |
| `sticky` | boolean | no | Pin to the top bar of the screen; false = scrolls with the content Default: `true`. |
| `button` | object | no | Optional compact CTA (always small; size is ignored) shown on the right; uses the same actions as Button. Keep its label short (\<=12 chars) |

> [accordion] Example
>
> ```json theme={null}
> {
>   "durationSeconds": 600,
>   "label": "Your discount is reserved for",
>   "expiredLabel": "Your discount is still available",
>   "sticky": true,
>   "button": {
>     "label": "Claim offer",
>     "subtitle": "Save 50%",
>     "action": "checkout",
>     "variant": "primary",
>     "icon": "arrow-right",
>     "iconPosition": "right"
>   }
> }
> ```

## Guarantee

Type `Guarantee`. Promises a money-back guarantee. Seal with the day count, title and terms; days is display-only, so it must match the real refund policy. Static.

| Setting | Type | Required | Description |
| - | - | - | - |
| `title` | string | no | Bold first line, keep \<=30 chars Default: `"Money-back guarantee"`. |
| `text` | string | yes | Terms in plain words, keep \<=120 chars; must match your real refund policy |
| `days` | integer | no | Length of the guarantee in days, shown in the round seal (display only; it does not change refund handling) Default: `30`. |

> [accordion] Example
>
> ```json theme={null}
> {
>   "text": "If you do not see visible results, we will refund your money."
> }
> ```

## Trust badges

Type `TrustBadges`. Shows payment and security marks. A secure line over vector payment-method cards in methods order, plus an optional disclaimer. Static; place near the checkout Button and list only methods you accept.

| Setting | Type | Required | Description |
| - | - | - | - |
| `text` | string | no | Line above the marks, with a shield icon, keep \<=40 chars; literal Default: `"Pay safe & secure"`. |
| `methods` | "visa" \| "mastercard" \| "amex" \| "applepay" \| "googlepay" \| "paypal"\[] | no | Payment marks in display order (1-6, no duplicates). List only methods your checkout accepts Default: `["applepay","googlepay","visa","mastercard","amex"]`. |
| `markStyle` | "light" \| "dark" | no | light: white card per mark, for a light background. dark: each mark on its own dark/brand-color card, for a dark theme. Default: `"light"`. |
| `disclaimer` | string | no | Small grey note under the badges, keep \<=60 chars, e.g. "All transactions are secure and encrypted" |
| `disclaimerIcon` | "activity" \| "alarm" \| "apple" \| "award" \| "baby" \| "battery" \| "bed" \| "bike" \| "brain" \| "calendar" \| "check" \| "chart" \| "clock" \| "coffee" \| "dumbbell" \| "flame" \| "flower" \| "footprints" \| "gift" \| "heart" \| "leaf" \| "lightning" \| "lock" \| "moon" \| "mountain" \| "music" \| "person" \| "ruler" \| "salad" \| "scale" \| "shield" \| "smile" \| "sparkles" \| "star" \| "sun" \| "target" \| "thumbs-up" \| "timer" \| "trophy" \| "upload" \| "users" \| "water" \| "yoga" \| "x" \| "zap" \| "heart-pulse" \| "stethoscope" \| "pill" \| "syringe" \| "thermometer" \| "weight" \| "hand-heart" \| "eye" \| "ear" \| "bone" \| "carrot" \| "cherry" \| "cookie" \| "pizza" \| "sandwich" \| "egg" \| "fish" \| "beef" \| "wheat" \| "cup-soda" \| "wine" \| "candy" \| "soup" \| "milk" \| "waves" \| "medal" \| "flag" \| "goal" \| "bed-double" \| "cloud-moon" \| "sunrise" \| "sunset" \| "wind" \| "feather" \| "brain-circuit" \| "book-open" \| "headphones" \| "glasses" \| "home" \| "briefcase" \| "car" \| "plane" \| "map-pin" \| "globe" \| "dog" \| "cat" \| "shopping-bag" \| "wallet" \| "credit-card" \| "piggy-bank" \| "gamepad" \| "tv" \| "smartphone" \| "laptop" \| "camera" \| "palette" \| "graduation-cap" \| "smile-plus" \| "frown" \| "meh" \| "laugh" \| "angry" \| "heart-crack" \| "party-popper" \| "check-circle" \| "x-circle" \| "alert-triangle" \| "info" \| "help-circle" \| "plus" \| "minus" \| "arrow-right" \| "trending-up" \| "trending-down" \| "bar-chart" \| "pie-chart" \| "percent" \| "tag" \| "badge-check" \| "crown" \| "gem" \| "rocket" \| "key" \| "bell" \| "mail" \| "phone" \| "message-circle" \| "search" \| "settings" \| "sliders" \| "refresh" \| "infinity" \| "hourglass" \| "calendar-check" \| "list-checks" \| "clipboard" \| "file-text" \| "lightbulb" \| "puzzle" \| "magnet" \| "anchor" \| "user-check" \| "user-plus" \| "users-round" \| "handshake" \| "thumbs-down" \| "star-half" | no | Icon shown before the disclaimer text; ignored unless disclaimer is set Default: `"lock"`. |

> [accordion] Example
>
> ```json theme={null}
> {
>   "text": "Pay safe & secure",
>   "methods": [
>     "applepay",
>     "googlepay",
>     "visa",
>     "mastercard",
>     "amex"
>   ],
>   "markStyle": "light",
>   "disclaimer": "All transactions are secure and encrypted",
>   "disclaimerIcon": "lock"
> }
> ```

## FAQ

Type `FAQ`. Answers common questions. Accordion of 1-12 Q\&As, all closed at first, one open at a time (aria-expanded); answers are plain text. Put the biggest purchase objection first.

| Setting | Type | Required | Description |
| - | - | - | - |
| `title` | string | no | Heading above the questions, keep \<=30 chars |
| `items` | object\[] | yes | 1-12 collapsed Q\&A rows, one open at a time; put the objection that blocks purchase first |

> [accordion] Example
>
> ```json theme={null}
> {
>   "title": "Frequently asked questions",
>   "items": [
>     {
>       "q": "Can I cancel anytime?",
>       "a": "Yes. You can cancel from your account before the next renewal."
>     },
>     {
>       "q": "When do I get access?",
>       "a": "Access starts immediately after a successful checkout."
>     },
>     {
>       "q": "Will this work on my phone?",
>       "a": "Yes. The experience is designed for mobile and works in modern browsers."
>     },
>     {
>       "q": "Is my information private?",
>       "a": "Your data is handled according to the privacy policy linked at checkout."
>     }
>   ]
> }
> ```

## Legal text

Type `LegalText`. Shows linked subscription terms. Small centred 11px print with [label](https://...) links. Every paywall needs one including \{\{plan\_terms}} (validate\_funnel warns otherwise). Static.

| Setting | Type | Required | Description |
| - | - | - | - |
| `text` | string | yes | Small centred 11px print, keep \<=300 chars. Supports [label](https://...) links; on paywalls include \{\{plan\_terms}} for the auto-renew terms |

> [accordion] Example
>
> ```json theme={null}
> {
>   "text": "By continuing you agree to our [Terms](https://example.com/terms)."
> }
> ```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.