Brand and design · Hi-fi screens · S15 Paywall · Paywall
Data-binding map: S15 Paywall · Paywall
Data-binding map of Paywall · Paywall: every field to its source, and what each required state shows.
Generated by
botgumi-design indexfrom../../screens.json. Edit that file, not this page.
Every field S15 shows and where it comes from.
| Field | Source (endpoint or local state) | Format | Fallback |
|---|---|---|---|
| score | api GET /paywall diagnostic.overall · paywall.diagnostic.overall |
display | — |
| band label | api GET /paywall diagnostic.band_label · CCR-12 / derived from D3 |
band.* |
— |
| weakest | api GET /paywall diagnostic.weakest_label · paywall.diagnostic.weakest_label (Accept-Language) |
paywall.weakest |
hide line |
| title skill | api GET /paywall diagnostic.one_action_title · paywall.diagnostic.one_action_title (Accept-Language) |
paywall.title |
generic title without skill |
| K slider | local paywall.selectedWeeklyDays · local:paywall.selectedWeeklyDays, default onboarding.weekly_days (CCR-7) |
3 / 5 / 7 detents | 5 |
| K slider | local onboarding.weekly_days |
||
| projection | derived projection · derived: paywall.benchmarks[] where weekly_days = K and baseline_bucket = bucket(diagnostic.overall) → day14_avg_overall, sample_n, weakest_dim_avg_delta |
paywall.projection (+ weakest_delta) — see paywall.md |
sample_n < 30 or missing → paywall.projection.insufficient (no number) |
| pilot label | api GET /paywall benchmark_source · paywall.benchmark_source = pilot_benchmark → paywall.benchmark_label (Accept-Language) |
amber tag | paywall.source.pilot key |
| pilot label | api GET /paywall benchmark_label |
||
| calendar days | api GET /paywall plan_preview.days[] · paywall.plan_preview.days[] + derived: practice pattern for K + streak milestones reachable by that pattern + billing day = trial_days |
7-col grid, Monday first | if plan missing: hide calendar, keep timeline |
| calendar days | derived practice_pattern |
||
| timeline dates | derived trial_timeline · derived: today + trial_days − 1 (reminder), today + trial_days (billing), plan day 14 |
Date.FormatStyle |
— |
| billing price | store displayPrice · storekit[id].displayPrice + subscriptionPeriod |
paywall.timeline.billing.* |
paywall.timeline.billing.loading |
| billing price | store subscriptionPeriod |
||
| product cards | api GET /paywall products[] · paywall.products[] (kind, trial_days, is_default, badge — badge Accept-Language) × storekit[id] (displayPrice, price, introductoryOffer, isEligibleForIntroOffer) |
per-month = price / 12 with priceFormatStyle |
StoreKit not loaded → skeleton cards, CTA disabled |
| product cards | store product |
||
| CTA + caption | derived cta_caption · derived: selected product, trial eligibility, billing date |
paywall.cta.trial / paywall.cta.subscribe + caption |
loading / purchasing / failed / restored states own the CTA |
| expired · stats | api GET /me stats.completed_sessions · me.stats.completed_sessions, me.stats.ability, me.focus.title |
— | ability null → "—" |
| expired · stats | api GET /me stats.ability |
||
| expired · stats | api GET /me focus.title |
||
| expired · trial end date | api GET /me entitlement.expires_at · me.entitlement.expires_at / trial_ends_at |
date | omit date |
| expired · trial end date | api GET /me entitlement.trial_ends_at |
||
| legal | api GET /paywall legal.terms_url · paywall.legal.terms_url / privacy_url |
link | bundled URLs |
| legal | api GET /paywall legal.privacy_url |
||
AppStore.sync() |
store restore · From the board's data-bind; no row in data-binding.md yet. |
||
AppStore.sync() → POST /v1/subscriptions/apple/transactions |
store restore · From the board's data-bind; no row in data-binding.md yet. |
||
AppStore.sync() → POST /v1/subscriptions/apple/transactions |
call POST /subscriptions/apple/transactions |
||
Product.purchase() |
store purchase · From the board's data-bind; no row in data-binding.md yet. |
||
Product.purchase() → POST /v1/subscriptions/apple/transactions |
store purchase · From the board's data-bind; no row in data-binding.md yet. |
||
Product.purchase() → POST /v1/subscriptions/apple/transactions |
call POST /subscriptions/apple/transactions |
||
StoreKit Product.PurchaseResult / error |
store purchase_result · From the board's data-bind; no row in data-binding.md yet. |
||
derived: band(paywall.diagnostic.overall) |
api GET /paywall diagnostic.band_label · From the board's data-bind; no row in data-binding.md yet. |
||
derived: introductoryOffer + price/12 (priceFormatStyle) |
derived monthly_price · From the board's data-bind; no row in data-binding.md yet. |
||
derived: trial end = today + trial_days; storekit.displayPrice |
derived trial_timeline · From the board's data-bind; no row in data-binding.md yet. |
||
derived: trial end = today + trial_days; storekit.displayPrice |
store displayPrice |
||
local:paywall.selectedWeeklyDays (default onboarding.weekly_days) |
local paywall.selectedWeeklyDays · From the board's data-bind; no row in data-binding.md yet. |
||
paywall.benchmark_source = pilot_benchmark → benchmark_label |
api GET /paywall benchmark_source · From the board's data-bind; no row in data-binding.md yet. |
||
paywall.benchmark_source = pilot_benchmark → benchmark_label |
api GET /paywall benchmark_label |
||
paywall.diagnostic.weakest_label (Accept-Language) |
api GET /paywall diagnostic.weakest_label · From the board's data-bind; no row in data-binding.md yet. |
||
paywall.legal.privacy_url |
api GET /paywall legal.privacy_url · From the board's data-bind; no row in data-binding.md yet. |
||
paywall.plan_preview.starts_on – ends_on |
api GET /paywall plan_preview.starts_on · From the board's data-bind; no row in data-binding.md yet. |
||
paywall.plan_preview.starts_on – ends_on |
api GET /paywall plan_preview.ends_on |
||
paywall.products[kind=annual].badge (Accept-Language) |
api GET /paywall products[].badge · From the board's data-bind; no row in data-binding.md yet. |
||
storekit.subscriptionPeriod |
store subscriptionPeriod · From the board's data-bind; no row in data-binding.md yet. |
||
storekit[clarisay.pro.annual] |
store product · From the board's data-bind; no row in data-binding.md yet. |
||
storekit[clarisay.pro.annual].displayPrice |
store displayPrice · From the board's data-bind; no row in data-binding.md yet. |
||
storekit[clarisay.pro.monthly] |
store product · From the board's data-bind; no row in data-binding.md yet. |
||
storekit[clarisay.pro.monthly].displayPrice |
store displayPrice · From the board's data-bind; no row in data-binding.md yet. |
Derived values
Computed on device; each from the sources it names.
| Value | From | How |
|---|---|---|
projection |
api GET /paywall benchmarks[].weekly_days, api GET /paywall benchmarks[].baseline_bucket, api GET /paywall benchmarks[].day14_avg_overall, api GET /paywall benchmarks[].sample_n, api GET /paywall benchmarks[].weakest_dim_avg_delta, api GET /paywall baseline.overall, local paywall.selectedWeeklyDays |
The benchmark row for K and the baseline's bucket: day-14 average, sample size and the weakest dimension's gain; hidden below the minimum sample (paywall.md). |
practice_pattern |
local paywall.selectedWeeklyDays, api GET /paywall plan_preview.days[] |
Which calendar days a K-days-a-week pattern trains, and the streak milestones it reaches. |
trial_timeline |
device clock, api GET /paywall products[].trial_days, api GET /paywall plan_preview.ends_on |
Today, the reminder the day before billing (today + trial_days − 1), billing day and plan day 14. |
cta_caption |
local paywall.selectedProduct, store isEligibleForIntroOffer, store introductoryOffer, derived trial_timeline |
The button and its caption: trial or not, and the first billing date. |
monthly_price |
store price, store introductoryOffer |
The annual price over 12, in the store's currency format. |
Binds on the boards
The data-bind values across every state.
AppStore.sync()AppStore.sync() → POST /v1/subscriptions/apple/transactionsProduct.purchase()Product.purchase() → POST /v1/subscriptions/apple/transactionsStoreKit Product.PurchaseResult / errorderived: band(paywall.diagnostic.overall)derived: introductoryOffer + price/12 (priceFormatStyle)derived: trial end = today + trial_days; storekit.displayPricelocal:paywall.selectedWeeklyDayslocal:paywall.selectedWeeklyDays (default onboarding.weekly_days)me.focus.titleme.stats.abilityme.stats.completed_sessionspaywall.benchmark_source = pilot_benchmark → benchmark_labelpaywall.diagnostic.one_action_titlepaywall.diagnostic.overallpaywall.diagnostic.weakest_label (Accept-Language)paywall.legal.privacy_urlpaywall.legal.terms_urlpaywall.plan_preview.starts_on – ends_onpaywall.products[kind=annual].badge (Accept-Language)storekit.subscriptionPeriodstorekit[clarisay.pro.annual]storekit[clarisay.pro.annual].displayPricestorekit[clarisay.pro.monthly]storekit[clarisay.pro.monthly].displayPrice
States
- Loading: From states.md (Paywall): paywall--loading-products (StoreKit) + skeleton projection (
/paywall) - Empty: From states.md (Paywall): —
- Error (retryable / not): From states.md (Paywall):
/paywallfailed → projection & calendar replaced by Retry card; products still purchasable · fatal: StoreKit unavailable → "App Store unavailable" + Restore - Offline: From states.md (Paywall): cached
/paywall; purchase disabled with "Connect to subscribe"