@funnelsgrove/cli 0.1.14 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/step-contract-v2.json +733 -0
- package/dist/analyticsOutput.d.ts +30 -15
- package/dist/analyticsOutput.js +45 -28
- package/dist/apiClient.d.ts +85 -0
- package/dist/apiClient.js +225 -8
- package/dist/cli.d.ts +149 -1
- package/dist/cli.js +1232 -71
- package/dist/diagnosticOutput.d.ts +42 -0
- package/dist/diagnosticOutput.js +83 -0
- package/dist/docsOutput.d.ts +19 -0
- package/dist/docsOutput.js +73 -0
- package/dist/docsTransaction.d.ts +81 -0
- package/dist/docsTransaction.js +1755 -0
- package/dist/funnelValidation.d.ts +14 -0
- package/dist/funnelValidation.js +297 -0
- package/dist/localSync.d.ts +79 -0
- package/dist/localSync.js +428 -53
- package/dist/projectValidator.d.ts +27 -0
- package/dist/projectValidator.js +208 -0
- package/dist/reskin.js +27 -1
- package/dist/stepContractMigration.d.ts +71 -0
- package/dist/stepContractMigration.js +1323 -0
- package/dist/templateDocs.js +8 -25
- package/docs-release-history.json +66 -0
- package/legacy-docs-catalog.json +1012 -0
- package/package.json +13 -4
- package/template_docs/.funnelsgrove-docs.json +144 -0
- package/template_docs/AGENTS.md +30 -58
- package/template_docs/CLAUDE.md +0 -2
- package/template_docs/docs/funnelsgrove/START-HERE.md +73 -0
- package/template_docs/docs/funnelsgrove/contracts/analytics-events.md +59 -0
- package/template_docs/docs/funnelsgrove/contracts/content-answers.md +44 -0
- package/template_docs/docs/funnelsgrove/contracts/flow-routing.md +41 -0
- package/template_docs/docs/funnelsgrove/contracts/payments.md +42 -0
- package/template_docs/docs/funnelsgrove/contracts/step-metadata.md +57 -0
- package/template_docs/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
- package/template_docs/docs/funnelsgrove/qa/analytics.md +43 -0
- package/template_docs/docs/funnelsgrove/qa/local.md +42 -0
- package/template_docs/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
- package/template_docs/docs/funnelsgrove/qa/publish.md +32 -0
- package/template_docs/docs/funnelsgrove/recipes/add-experiment.md +34 -0
- package/template_docs/docs/funnelsgrove/recipes/add-step.md +33 -0
- package/template_docs/docs/funnelsgrove/recipes/edit-step.md +31 -0
- package/template_docs/docs/funnelsgrove/steps/INDEX.md +26 -0
- package/template_docs/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/checkout.md +120 -0
- package/template_docs/docs/funnelsgrove/steps/form_input.md +115 -0
- package/template_docs/docs/funnelsgrove/steps/intro_hero.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
- package/template_docs/docs/funnelsgrove/steps/paywall_offer.md +115 -0
- package/template_docs/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
- package/template_docs/docs/funnelsgrove/steps/purchase_completed.md +117 -0
- package/template_docs/docs/funnelsgrove/steps/single_step_choice.md +122 -0
- package/template_docs/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
- package/template_docs/docs/funnelsgrove/steps/social_proof.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
- package/template_docs/docs/funnelsgrove/steps/subscription_management.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/upsell_offer.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/value_prop_story.md +110 -0
- package/template_docs/funnel-docs.config.json +43 -0
- package/template_scaffold/.env.example +41 -0
- package/template_scaffold/.funnelsgrove-contract-tools.json +19 -0
- package/template_scaffold/.funnelsgrove-docs.json +144 -0
- package/template_scaffold/.funnelsgrove-scaffold.json +1078 -0
- package/template_scaffold/AGENTS.md +42 -0
- package/template_scaffold/CLAUDE.md +1 -0
- package/template_scaffold/PLAN.md +81 -0
- package/template_scaffold/PRODUCT_SENSE.md +28 -0
- package/template_scaffold/context/build-context.md +34 -0
- package/template_scaffold/docs/AGENT_FUNNEL_IMPLEMENTATION_SPEC.md +5 -0
- package/template_scaffold/docs/ARCHITECTURE.md +5 -0
- package/template_scaffold/docs/FLOW_CONFIG_AND_ROUTING.md +5 -0
- package/template_scaffold/docs/PAYWALL_AND_PAYMENTS.md +5 -0
- package/template_scaffold/docs/README.md +5 -0
- package/template_scaffold/docs/funnelsgrove/START-HERE.md +73 -0
- package/template_scaffold/docs/funnelsgrove/contracts/analytics-events.md +59 -0
- package/template_scaffold/docs/funnelsgrove/contracts/content-answers.md +44 -0
- package/template_scaffold/docs/funnelsgrove/contracts/flow-routing.md +41 -0
- package/template_scaffold/docs/funnelsgrove/contracts/payments.md +42 -0
- package/template_scaffold/docs/funnelsgrove/contracts/step-metadata.md +57 -0
- package/template_scaffold/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
- package/template_scaffold/docs/funnelsgrove/qa/analytics.md +43 -0
- package/template_scaffold/docs/funnelsgrove/qa/local.md +42 -0
- package/template_scaffold/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
- package/template_scaffold/docs/funnelsgrove/qa/publish.md +32 -0
- package/template_scaffold/docs/funnelsgrove/recipes/add-experiment.md +34 -0
- package/template_scaffold/docs/funnelsgrove/recipes/add-step.md +33 -0
- package/template_scaffold/docs/funnelsgrove/recipes/edit-step.md +31 -0
- package/template_scaffold/docs/funnelsgrove/steps/INDEX.md +26 -0
- package/template_scaffold/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/checkout.md +120 -0
- package/template_scaffold/docs/funnelsgrove/steps/form_input.md +115 -0
- package/template_scaffold/docs/funnelsgrove/steps/intro_hero.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
- package/template_scaffold/docs/funnelsgrove/steps/paywall_offer.md +115 -0
- package/template_scaffold/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
- package/template_scaffold/docs/funnelsgrove/steps/purchase_completed.md +117 -0
- package/template_scaffold/docs/funnelsgrove/steps/single_step_choice.md +122 -0
- package/template_scaffold/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
- package/template_scaffold/docs/funnelsgrove/steps/social_proof.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
- package/template_scaffold/docs/funnelsgrove/steps/subscription_management.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/upsell_offer.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/value_prop_story.md +110 -0
- package/template_scaffold/docs/references/funnel-sdk-user-answers.md +5 -0
- package/template_scaffold/eslint.config.mjs +16 -0
- package/template_scaffold/funnel-agent-docs.test.ts +699 -0
- package/template_scaffold/funnel-docs.config.json +43 -0
- package/template_scaffold/funnel.config.json +5 -0
- package/template_scaffold/gitignore.template +5 -0
- package/template_scaffold/next-env.d.ts +6 -0
- package/template_scaffold/next.config.ts +53 -0
- package/template_scaffold/package-lock.json +7737 -0
- package/template_scaffold/package.json +37 -0
- package/template_scaffold/package.test.ts +23 -0
- package/template_scaffold/public/claimbee/bee.png +0 -0
- package/template_scaffold/public/claimbee/device-iphone.png +0 -0
- package/template_scaffold/public/claimbee/device-macbook.png +0 -0
- package/template_scaffold/public/claimbee/device-none.png +0 -0
- package/template_scaffold/public/claimbee/device-watch.png +0 -0
- package/template_scaffold/public/claimbee/glow.svg +3 -0
- package/template_scaffold/public/claimbee/steps-sprite-alt.png +0 -0
- package/template_scaffold/public/claimbee/steps-sprite-default.png +0 -0
- package/template_scaffold/public/claimbee/testimonial-avatar.png +0 -0
- package/template_scaffold/public/claimbee/testimonial-star.svg +3 -0
- package/template_scaffold/public/paywall/ai-claim-assistant.png +0 -0
- package/template_scaffold/public/paywall/claim-history.png +0 -0
- package/template_scaffold/public/paywall/clear-progress.png +0 -0
- package/template_scaffold/public/paywall/hero.png +0 -0
- package/template_scaffold/public/paywall/money-alerts.png +0 -0
- package/template_scaffold/public/paywall/money-back-badge.png +0 -0
- package/template_scaffold/public/paywall/paywall-image.png +0 -0
- package/template_scaffold/public/paywall/r1.png +0 -0
- package/template_scaffold/public/paywall/r2.png +0 -0
- package/template_scaffold/public/paywall/r3.png +0 -0
- package/template_scaffold/public/paywall/r4.png +0 -0
- package/template_scaffold/public/paywall/r5.png +0 -0
- package/template_scaffold/public/paywall/r6.png +0 -0
- package/template_scaffold/public/paywall/special-offer-gift.png +0 -0
- package/template_scaffold/public/please/bee.png +0 -0
- package/template_scaffold/public/please/device-iphone.png +0 -0
- package/template_scaffold/public/please/device-macbook.png +0 -0
- package/template_scaffold/public/please/device-none.png +0 -0
- package/template_scaffold/public/please/device-watch.png +0 -0
- package/template_scaffold/public/please/glow.svg +3 -0
- package/template_scaffold/public/please/steps-sprite-alt.png +0 -0
- package/template_scaffold/public/please/steps-sprite-default.png +0 -0
- package/template_scaffold/public/please/testimonial-avatar.png +0 -0
- package/template_scaffold/public/please/testimonial-star.svg +3 -0
- package/template_scaffold/public/upsell/upgrade-hero.png +0 -0
- package/template_scaffold/src/app/[stepId]/page.test.tsx +59 -0
- package/template_scaffold/src/app/[stepId]/page.tsx +62 -0
- package/template_scaffold/src/app/globals.css +49 -0
- package/template_scaffold/src/app/layout.test.ts +26 -0
- package/template_scaffold/src/app/layout.tsx +61 -0
- package/template_scaffold/src/app/page.tsx +8 -0
- package/template_scaffold/src/app/sdk/page.tsx +673 -0
- package/template_scaffold/src/app/subscription-dashboard/page.tsx +274 -0
- package/template_scaffold/src/assets/claimbee/bee.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-iphone.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-macbook.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-none.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-watch.png +0 -0
- package/template_scaffold/src/assets/claimbee/glow.svg +3 -0
- package/template_scaffold/src/assets/claimbee/steps-sprite-alt.png +0 -0
- package/template_scaffold/src/assets/claimbee/steps-sprite-default.png +0 -0
- package/template_scaffold/src/assets/claimbee/testimonial-avatar.png +0 -0
- package/template_scaffold/src/assets/claimbee/testimonial-star.svg +3 -0
- package/template_scaffold/src/components/FunnelEditorPanel.tsx +194 -0
- package/template_scaffold/src/components/FunnelFlow.test.tsx +17 -0
- package/template_scaffold/src/components/FunnelFlow.tsx +114 -0
- package/template_scaffold/src/components/FunnelStepImage.test.ts +15 -0
- package/template_scaffold/src/components/FunnelStepImage.tsx +28 -0
- package/template_scaffold/src/components/step/FunnelStepHeader.tsx +35 -0
- package/template_scaffold/src/config/billing.plans.test.ts +143 -0
- package/template_scaffold/src/config/billing.plans.ts +69 -0
- package/template_scaffold/src/config/billing.test.plans.ts +32 -0
- package/template_scaffold/src/config/experiments.generated.ts +4 -0
- package/template_scaffold/src/config/experiments.test.ts +12 -0
- package/template_scaffold/src/config/experiments.ts +9 -0
- package/template_scaffold/src/config/funnel.config.ts +12 -0
- package/template_scaffold/src/config/funnel.manifest.test.ts +166 -0
- package/template_scaffold/src/config/funnel.manifest.ts +139 -0
- package/template_scaffold/src/config/offer-sets.generated.ts +4 -0
- package/template_scaffold/src/contract/funnel-project.validation.test.ts +80 -0
- package/template_scaffold/src/contract/funnel-project.validation.ts +44 -0
- package/template_scaffold/src/contract/funnel-validator.vite.config.ts +11 -0
- package/template_scaffold/src/contract/golden/cancellation_offer.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/checkout.fixture.ts +37 -0
- package/template_scaffold/src/contract/golden/form_input.fixture.ts +28 -0
- package/template_scaffold/src/contract/golden/golden-fixtures.test.ts +190 -0
- package/template_scaffold/src/contract/golden/intro_hero.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/multi_select_choice.fixture.ts +37 -0
- package/template_scaffold/src/contract/golden/paywall_offer.fixture.ts +30 -0
- package/template_scaffold/src/contract/golden/progress_interstitial.fixture.ts +28 -0
- package/template_scaffold/src/contract/golden/purchase_completed.fixture.ts +33 -0
- package/template_scaffold/src/contract/golden/single_step_choice.fixture.ts +36 -0
- package/template_scaffold/src/contract/golden/single_step_choice_emoji.fixture.ts +36 -0
- package/template_scaffold/src/contract/golden/social_proof.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/subscription_handoff.fixture.ts +30 -0
- package/template_scaffold/src/contract/golden/subscription_management.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/summary_confirmation.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/upsell_offer.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/value_prop_story.fixture.ts +27 -0
- package/template_scaffold/src/contract/validate-funnel.cli.test.ts +180 -0
- package/template_scaffold/src/contract/validate-funnel.cli.ts +199 -0
- package/template_scaffold/src/runtime/checkout-runtime-config.test.ts +60 -0
- package/template_scaffold/src/runtime/checkout-runtime-config.ts +26 -0
- package/template_scaffold/src/runtime/funnel-runtime.test.ts +25 -0
- package/template_scaffold/src/runtime/funnel-runtime.ts +118 -0
- package/template_scaffold/src/runtime/step-content-context.test.ts +38 -0
- package/template_scaffold/src/runtime/step-content-context.ts +65 -0
- package/template_scaffold/src/runtime/step-registry.ts +66 -0
- package/template_scaffold/src/runtime/step-variable-values.ts +31 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.integration.test.ts +203 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.test.ts +76 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.ts +53 -0
- package/template_scaffold/src/steps/content/email-capture.content.ts +29 -0
- package/template_scaffold/src/steps/content/manage-subscription.content.ts +62 -0
- package/template_scaffold/src/steps/content/paywall.content.ts +191 -0
- package/template_scaffold/src/steps/content/step-01.content.ts +23 -0
- package/template_scaffold/src/steps/content/step-02.content.ts +77 -0
- package/template_scaffold/src/steps/content/step-03.content.ts +40 -0
- package/template_scaffold/src/steps/content/step-04.content.ts +49 -0
- package/template_scaffold/src/steps/content/step-32-paywall.content.ts +352 -0
- package/template_scaffold/src/steps/content/subscription-started.content.ts +68 -0
- package/template_scaffold/src/steps/editor/email-capture.editor.ts +58 -0
- package/template_scaffold/src/steps/editor/manage-subscription.editor.ts +179 -0
- package/template_scaffold/src/steps/editor/paywall.editor.ts +232 -0
- package/template_scaffold/src/steps/editor/step-01.editor.ts +22 -0
- package/template_scaffold/src/steps/editor/step-02.editor.ts +41 -0
- package/template_scaffold/src/steps/editor/step-03.editor.ts +58 -0
- package/template_scaffold/src/steps/editor/step-04.editor.ts +98 -0
- package/template_scaffold/src/steps/editor/step-32-paywall.editor.ts +478 -0
- package/template_scaffold/src/steps/editor/subscription-started.editor.ts +131 -0
- package/template_scaffold/src/steps/index.ts +25 -0
- package/template_scaffold/src/steps/paywall-checkout-options.test.ts +104 -0
- package/template_scaffold/src/steps/paywall-checkout-options.ts +130 -0
- package/template_scaffold/src/steps/pricing/paywall-b.pricing.ts +12 -0
- package/template_scaffold/src/steps/pricing/paywall.pricing.ts +12 -0
- package/template_scaffold/src/steps/pricing/shared-plan-order.ts +17 -0
- package/template_scaffold/src/steps/pricing/upsell-form.pricing.ts +16 -0
- package/template_scaffold/src/steps/shared-header-contract.test.ts +27 -0
- package/template_scaffold/src/steps/step-01.test.ts +38 -0
- package/template_scaffold/src/steps/step-01.tsx +108 -0
- package/template_scaffold/src/steps/step-02.test.ts +43 -0
- package/template_scaffold/src/steps/step-02.tsx +140 -0
- package/template_scaffold/src/steps/step-03.test.ts +15 -0
- package/template_scaffold/src/steps/step-03.tsx +262 -0
- package/template_scaffold/src/steps/step-04.test.ts +32 -0
- package/template_scaffold/src/steps/step-04.tsx +673 -0
- package/template_scaffold/src/steps/step-31-email-capture.test.ts +22 -0
- package/template_scaffold/src/steps/step-31-email-capture.tsx +195 -0
- package/template_scaffold/src/steps/step-32-paywall.test.ts +770 -0
- package/template_scaffold/src/steps/step-32-paywall.tsx +2253 -0
- package/template_scaffold/src/steps/step-32b-paywall-b.tsx +35 -0
- package/template_scaffold/src/steps/step-33-subscription-started.test.ts +26 -0
- package/template_scaffold/src/steps/step-33-subscription-started.tsx +86 -0
- package/template_scaffold/src/steps/step-34-upsell-form.test.ts +27 -0
- package/template_scaffold/src/steps/step-35-manage-subscription.tsx +46 -0
- package/template_scaffold/src/steps/step-content.registry.ts +45 -0
- package/template_scaffold/src/steps/step-image-migration.test.ts +20 -0
- package/template_scaffold/src/steps/styles/index.css +2 -0
- package/template_scaffold/src/steps/styles/shared/final-flow-shared.css +55 -0
- package/template_scaffold/src/steps/styles/shared/funnel-base.css +543 -0
- package/template_scaffold/src/steps/styles/shared/info-shared.css +139 -0
- package/template_scaffold/src/steps/styles/shared/progress-shared.css +117 -0
- package/template_scaffold/src/steps/styles/shared/question-shared.css +76 -0
- package/template_scaffold/src/steps/styles/shared/responsive-container.css +176 -0
- package/template_scaffold/src/steps/types.ts +7 -0
- package/template_scaffold/src/steps/use-claimbee-step-content.ts +15 -0
- package/template_scaffold/src/theme/theme.ts +81 -0
- package/template_scaffold/tsconfig.json +38 -0
- package/template_scaffold/vitest.config.ts +32 -0
- package/template_validation/.funnelsgrove-contract-tools.json +19 -0
- package/template_validation/src/contract/funnel-project.validation.ts +44 -0
- package/template_validation/src/contract/funnel-validator.vite.config.ts +11 -0
- package/template_validation/src/contract/validate-funnel.cli.ts +199 -0
- package/template_docs/docs/ab-experiments.md +0 -55
- package/template_docs/docs/analytics.md +0 -65
- package/template_docs/docs/editing-flow.md +0 -125
- package/template_docs/docs/editing-step.md +0 -125
- package/template_docs/docs/editor-and-content.md +0 -58
- package/template_docs/docs/funnel-runtime-architecture.md +0 -125
- package/template_docs/docs/meta-pixel-conversions-api.md +0 -50
- package/template_docs/docs/payment-plans-and-discounts.md +0 -106
- package/template_docs/docs/publishing-and-versioning.md +0 -117
- package/template_docs/docs/qa-checklist.md +0 -80
- package/template_docs/docs/sdk-api-endpoints.md +0 -78
- package/template_docs/docs/step-ui-guidelines.md +0 -110
- package/template_docs/docs/theme.md +0 -35
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Migrate a funnel to step contract v3
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/migration/step-contract-v3 -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
Supported read versions: `1`, `2`, `3`. Authoring and publish target version `3`. Contract v2 remains readable with `complete_registration`; migration to v3 changes that terminal type to `purchase_completed`. New v3 instructions must not author `complete_registration`.
|
|
9
|
+
|
|
10
|
+
| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
|
|
13
|
+
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
|
|
14
|
+
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
|
|
15
|
+
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
|
|
16
|
+
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
|
|
17
|
+
|
|
18
|
+
### Package release order
|
|
19
|
+
|
|
20
|
+
Release `@funnelsgrove/runtime` `0.1.59` first, then `@funnelsgrove/analytics` `0.1.36`, then `@funnelsgrove/cli` `0.1.18`. Deploy the API and funnel template only after those registry versions are available. Publishing packages and deploying production remain separately approved operational actions.
|
|
21
|
+
<!-- funnelsgrove:generated:end contract-v3/migration/step-contract-v3 -->
|
|
22
|
+
|
|
23
|
+
## Version-last policy
|
|
24
|
+
|
|
25
|
+
1. Inventory every step, component metadata export, manifest entry, answer key, route, branch, experiment, and custom analytics call.
|
|
26
|
+
2. Reclassify by behavior using the [step-type index](../steps/INDEX.md).
|
|
27
|
+
3. Restore exact reserved identities and manifest/component parity.
|
|
28
|
+
4. Move choice writes, email capture, payment events, handoff, routing, and lifecycle work to approved shared owners.
|
|
29
|
+
5. Add/update fixtures and focused tests.
|
|
30
|
+
6. Run `fgrove validate` and all [local](../qa/local.md), [analytics](../qa/analytics.md), and payment QA that applies.
|
|
31
|
+
7. Change `stepContractVersion` only after every earlier step passes.
|
|
32
|
+
|
|
33
|
+
Do not use the version field to silence diagnostics. Preserve legacy stable IDs and answer keys unless a separately planned data/analytics migration owns the change.
|
|
34
|
+
|
|
35
|
+
## v2 compatibility
|
|
36
|
+
|
|
37
|
+
Contract v2 funnels remain readable with the `complete_registration` terminal type. The v2-to-v3 migration preserves the `subscription-started` identity, route, file, transitions, and all unrelated metadata while changing only the contract version and terminal type to `purchase_completed`. New v3 authoring must never generate `complete_registration`.
|
|
38
|
+
|
|
39
|
+
The migration does not turn browser terminal reach into a trusted conversion. Only the backend emits the v3 `purchase_completed` analytics event after verifying a successful initial subscription or one-time payment. `registration_completed` remains the separate later app-link event.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Analytics QA
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/qa/analytics -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Contract key | Public event | Raw event | Allowed step types | Allowed identities | Owner | Automatic | Dedupe | Required metadata |
|
|
9
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
10
|
+
| `add_payment_info` | `add_payment_info` | `add_payment_info` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
11
|
+
| `checkout_completed` | `checkout_completed` | `checkout_completed` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
12
|
+
| `checkout_started` | `checkout_started` | `checkout_started` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
13
|
+
| `email_captured` | `email_captured` | `email_captured` | `form_input` | `email-capture` | `transactional-server` | `false` | `logical-email-conversion` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `projectId`, `funnelEndUserId`, `eventId` |
|
|
14
|
+
| `first_step_clicked` | `first_step_clicked` | `first_step_clicked` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
15
|
+
| `first_step_viewed` | `first_step_viewed` | `first_step_viewed` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
16
|
+
| `funnel_completed` | `funnel_completed` | `funnel_completed` | `purchase_completed` | `any` | `terminal-helper` | `false` | `funnel-run` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
17
|
+
| `funnel_started` | `funnel_started` | `funnel_start` | `any` | `any` | `controller` | `true` | `funnel-run` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion` |
|
|
18
|
+
| `purchase_completed` | `purchase_completed` | `purchase_completed` | _None_ | _None_ | `trusted-server` | `false` | `provider-payment` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `projectId`, `funnelEndUserId`, `eventId`, `providerPaymentId`, `purchaseKind` |
|
|
19
|
+
| `registration_completed` | `registration_completed` | `registration_completed` | _None_ | _None_ | `trusted-server` | `false` | `subscription-claim` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `projectId`, `funnelEndUserId`, `eventId`, `subscriptionClaimId` |
|
|
20
|
+
| `step_completed` | `step_completed` | `step_end` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
21
|
+
| `step_engaged` | `step_engaged` | `step_engaged` | `any` | `any` | `controller` | `false` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `durationMs` |
|
|
22
|
+
| `step_exited` | `step_exited` | `step_exit` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
23
|
+
| `step_started` | `step_started` | `step_start` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
24
|
+
<!-- funnelsgrove:generated:end contract-v3/qa/analytics -->
|
|
25
|
+
|
|
26
|
+
## Journey assertions
|
|
27
|
+
|
|
28
|
+
- Funnel start occurs once per run.
|
|
29
|
+
- Each visit has one start and exactly one completion or exit.
|
|
30
|
+
- First-step view/click dedupe correctly.
|
|
31
|
+
- If an explicit qualified policy emits `step_engaged`, it includes `durationMs` and deduplicates per visit; no default engagement event is expected.
|
|
32
|
+
- Choice steps save the exact stable ID shape before completion.
|
|
33
|
+
- Email success creates one server conversion; duplicate capture skips browser fanout; failure changes no state/lifecycle/route.
|
|
34
|
+
- Checkout helpers fire only at real boundaries with complete metadata and stable event IDs.
|
|
35
|
+
- Quiz completed requires trusted-server `purchase_completed`, deduplicated by `provider-payment`; browser `funnel_completed` is lifecycle-only and never satisfies it.
|
|
36
|
+
- `registration_completed` remains the separate later app-link claim.
|
|
37
|
+
- Preview sends no API/provider analytics.
|
|
38
|
+
- No component sends PostHog or server Meta directly.
|
|
39
|
+
- Never put raw email or other PII in analytics event metadata or logs.
|
|
40
|
+
- Only the server delivery boundary may use raw email as Meta hashing input.
|
|
41
|
+
- PostHog properties must remain non-PII.
|
|
42
|
+
|
|
43
|
+
Inspect raw events and user state, not only dashboard totals. Finish by running `fgrove validate`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Local QA
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/qa/local -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `browser-registration-completed` | _None_ | _None_ | `trusted-subscription-claim-server` |
|
|
11
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
12
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
13
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
14
|
+
| `hardcoded-navigation` | _None_ | _None_ | `manifest-flow-controller` |
|
|
15
|
+
| `provider-direct-analytics` | _None_ | _None_ | `analytics-adapter-outbox` |
|
|
16
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
17
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
18
|
+
<!-- funnelsgrove:generated:end contract-v3/qa/local -->
|
|
19
|
+
|
|
20
|
+
## Automated gate
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm run test:run
|
|
24
|
+
npm run lint
|
|
25
|
+
fgrove validate
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Run the repository’s focused tests first, then its full validation gate. Also run `npm run docs:funnel-agent:check` when editing this source bundle.
|
|
29
|
+
|
|
30
|
+
## Manual gate
|
|
31
|
+
|
|
32
|
+
- Test small 375×667, medium 393×852, large 402×874, and desktop-small 1280×800.
|
|
33
|
+
- At every declared breakpoint, require no horizontal scrolling, clipping, or overlap. Hiding overflow does not pass when content is clipped.
|
|
34
|
+
- Keep the choice/input primary CTA visible without scrolling and every interactive tap target at least 44×44 CSS px.
|
|
35
|
+
- Check pointer, keyboard, focus, loading, error, retry, refresh, back, and exit.
|
|
36
|
+
- Verify answer persistence and manifest routes.
|
|
37
|
+
- Assert every `assetId` resolves. Inspect the network to prove only current and likely-next assets preload; metadata alone is not proof.
|
|
38
|
+
- Confirm theme values come from `src/theme/theme.ts` through emitted CSS variables rather than duplicated step-local constants.
|
|
39
|
+
- Verify preview suppresses remote API/provider delivery.
|
|
40
|
+
- Inspect the console and network for errors or duplicate requests.
|
|
41
|
+
|
|
42
|
+
Complete the type-specific checklist in the [step-type index](../steps/INDEX.md).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Paywall and checkout QA
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/qa/paywall-checkout -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
### Generated contract facts — do not edit
|
|
9
|
+
|
|
10
|
+
- Step contract version: `3`
|
|
11
|
+
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
12
|
+
- Type: `paywall_offer`
|
|
13
|
+
- Family: `commerce`
|
|
14
|
+
- Description: A monetization offer that presents purchasable plans.
|
|
15
|
+
- Action owner: `step`
|
|
16
|
+
- Analytics role: `paywall`
|
|
17
|
+
- Terminal: `false`
|
|
18
|
+
- Required kind: `paywall`
|
|
19
|
+
- Allowed kinds: `paywall`
|
|
20
|
+
- Allowed semantic events: `checkout_started`, `add_payment_info`, `checkout_completed`
|
|
21
|
+
- Forbidden capabilities: `choice-write`, `email-capture`, `subscription-management`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`
|
|
22
|
+
|
|
23
|
+
#### Choice contract
|
|
24
|
+
|
|
25
|
+
_Not a choice type._
|
|
26
|
+
|
|
27
|
+
#### Automatic lifecycle events
|
|
28
|
+
|
|
29
|
+
`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`
|
|
30
|
+
|
|
31
|
+
#### Approved capability owners
|
|
32
|
+
|
|
33
|
+
- `checkout` must be owned by `named-payment-helpers`.
|
|
34
|
+
|
|
35
|
+
#### Reserved identities
|
|
36
|
+
|
|
37
|
+
- `paywall`: id=`paywall`, name=`paywall`; type=`paywall_offer`; kind=`paywall`; primary=`true`; unique=`true`
|
|
38
|
+
- `paywall-variant`: idPattern=`^paywall-[a-z0-9-]+$`, namePattern=`^paywall-[a-z0-9-]+$`; type=`paywall_offer`; kind=`paywall`; primary=`false`; unique=`false`
|
|
39
|
+
<!-- funnelsgrove:generated:end contract-v3/qa/paywall-checkout -->
|
|
40
|
+
|
|
41
|
+
## Classification and metadata
|
|
42
|
+
|
|
43
|
+
- Confirm only screens with purchasable plans are paywalls.
|
|
44
|
+
- Confirm primary and variant identities, types, kinds, paths, and component parity.
|
|
45
|
+
- Confirm no secrets or provider IDs appear in JSX/client configuration.
|
|
46
|
+
|
|
47
|
+
## Purchase paths
|
|
48
|
+
|
|
49
|
+
- Verify every plan, price, currency, discount, and eligibility rule.
|
|
50
|
+
- Test card and every enabled wallet.
|
|
51
|
+
- Test validation, decline, retry, cancel, double-submit, and provider delay.
|
|
52
|
+
- Verify named checkout events, complete metadata, one event ID, and retry deduplication.
|
|
53
|
+
- Verify success routing and the `purchase_completed` terminal handoff.
|
|
54
|
+
|
|
55
|
+
Run `fgrove validate` after all checks.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Publish QA
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/qa/publish -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `browser-registration-completed` | _None_ | _None_ | `trusted-subscription-claim-server` |
|
|
11
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
12
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
13
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
14
|
+
| `hardcoded-navigation` | _None_ | _None_ | `manifest-flow-controller` |
|
|
15
|
+
| `provider-direct-analytics` | _None_ | _None_ | `analytics-adapter-outbox` |
|
|
16
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
17
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
18
|
+
<!-- funnelsgrove:generated:end contract-v3/qa/publish -->
|
|
19
|
+
|
|
20
|
+
## Preview gate
|
|
21
|
+
|
|
22
|
+
1. Run `fgrove status`, `git status --short`, tests, lint, `fgrove validate`, and relevant local/analytics/payment QA.
|
|
23
|
+
2. Choose exactly one source path. GitHub-connected funnels use git push, `fgrove github pull`, terminal status, then publish; never use `fgrove sync up` for the same diff. Non-GitHub funnels use `fgrove sync up`.
|
|
24
|
+
3. Publish preview with a clear message.
|
|
25
|
+
4. Test the preview URL across supported breakpoints and real navigation entry points.
|
|
26
|
+
5. Confirm preview-mode suppression and production configuration separation.
|
|
27
|
+
6. Review route, analytics, answer, experiment, and payment evidence.
|
|
28
|
+
7. Confirm the `imageVariants` stage completed, supported browsers receive AVIF/WebP, and the original raster remains the fallback.
|
|
29
|
+
|
|
30
|
+
## Production gate
|
|
31
|
+
|
|
32
|
+
Publish production only after explicit approval and successful preview QA. Confirm the selected project/funnel/environment immediately before publishing, then smoke-test the live journey without creating duplicate conversions.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Recipe: add an experiment
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/recipe/add-experiment -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `browser-registration-completed` | _None_ | _None_ | `trusted-subscription-claim-server` |
|
|
11
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
12
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
13
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
14
|
+
| `hardcoded-navigation` | _None_ | _None_ | `manifest-flow-controller` |
|
|
15
|
+
| `provider-direct-analytics` | _None_ | _None_ | `analytics-adapter-outbox` |
|
|
16
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
17
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
18
|
+
<!-- funnelsgrove:generated:end contract-v3/recipe/add-experiment -->
|
|
19
|
+
|
|
20
|
+
## Procedure
|
|
21
|
+
|
|
22
|
+
1. Build and validate every control/variant step before activation.
|
|
23
|
+
2. Give each variant a stable, contract-compliant identity and normal outgoing edge.
|
|
24
|
+
3. Create the experiment through FunnelsGrove so the platform owns the database row, feature flag, and generated experiment snapshot.
|
|
25
|
+
4. Keep variant keys, labels, traffic percentages, source step, and route targets aligned.
|
|
26
|
+
5. Resolve assignment and any redirect before creating the destination step visit.
|
|
27
|
+
6. Keep the default flow valid when the experiment is stopped or assignment is unavailable.
|
|
28
|
+
7. Run experiment-focused tests, then `fgrove validate`.
|
|
29
|
+
|
|
30
|
+
## Pre-activation QA
|
|
31
|
+
|
|
32
|
+
Force every assignment, verify analytics metadata and deduplication, confirm refresh keeps assignment, test missing/invalid flags, and leave inactive variants unreachable from the default flow.
|
|
33
|
+
|
|
34
|
+
Pre-activation, missing-assignment, invalid-assignment, and fallback paths must not create phantom `step_started`, `step_completed`, or `step_exited` events.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Recipe: add a step
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/recipe/add-step -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `browser-registration-completed` | _None_ | _None_ | `trusted-subscription-claim-server` |
|
|
11
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
12
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
13
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
14
|
+
| `hardcoded-navigation` | _None_ | _None_ | `manifest-flow-controller` |
|
|
15
|
+
| `provider-direct-analytics` | _None_ | _None_ | `analytics-adapter-outbox` |
|
|
16
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
17
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
18
|
+
<!-- funnelsgrove:generated:end contract-v3/recipe/add-step -->
|
|
19
|
+
|
|
20
|
+
## Procedure
|
|
21
|
+
|
|
22
|
+
1. Choose the exact type from the [step-type index](../steps/INDEX.md).
|
|
23
|
+
2. Add the component and exported metadata.
|
|
24
|
+
3. Add matching manifest metadata, path, file path, and component key.
|
|
25
|
+
4. Add the registry entry.
|
|
26
|
+
5. Add content/editor definitions and registry entries only when builder-editable.
|
|
27
|
+
6. Add manifest edges, branches, assets, and tests required by the behavior.
|
|
28
|
+
7. Start from the type’s golden fixture and preserve answer/helper semantics.
|
|
29
|
+
8. Run focused tests, then `fgrove validate`.
|
|
30
|
+
|
|
31
|
+
## Manual QA
|
|
32
|
+
|
|
33
|
+
Render at all default breakpoints; test keyboard/pointer interaction, refresh/back/exit, answer persistence, lifecycle events, and every outgoing route. The recipe is complete only when the matching QA checklist passes.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Recipe: edit a step
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/recipe/edit-step -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
9
|
+
| --- | --- | --- | --- |
|
|
10
|
+
| `browser-registration-completed` | _None_ | _None_ | `trusted-subscription-claim-server` |
|
|
11
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
12
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
13
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
14
|
+
| `hardcoded-navigation` | _None_ | _None_ | `manifest-flow-controller` |
|
|
15
|
+
| `provider-direct-analytics` | _None_ | _None_ | `analytics-adapter-outbox` |
|
|
16
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
17
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
18
|
+
<!-- funnelsgrove:generated:end contract-v3/recipe/edit-step -->
|
|
19
|
+
|
|
20
|
+
## Procedure
|
|
21
|
+
|
|
22
|
+
1. Read the current type page from the [step-type index](../steps/INDEX.md).
|
|
23
|
+
2. Decide whether the requested behavior still matches the existing type.
|
|
24
|
+
3. Preserve stable IDs, names, paths, answer keys, option IDs, and reserved identities unless the request is an explicit migration.
|
|
25
|
+
4. Update component, content/editor, registry, manifest, and tests only where the change requires.
|
|
26
|
+
5. Keep component and manifest metadata in parity.
|
|
27
|
+
6. Run focused tests, then `fgrove validate`.
|
|
28
|
+
|
|
29
|
+
## Manual QA
|
|
30
|
+
|
|
31
|
+
Re-run the complete current interaction, not just the changed visual state. Confirm existing analytics keys, answer shapes, lifecycle outcome, and routes remain intact.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Step-type index
|
|
2
|
+
|
|
3
|
+
Choose the page whose type describes the screen's actual behavior. Do not classify from its position or visual treatment.
|
|
4
|
+
|
|
5
|
+
| Type | Family | Use |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| [`cancellation_offer`](cancellation_offer.md) | `commerce` | A cancellation retention or downsell surface. |
|
|
8
|
+
| [`checkout`](checkout.md) | `commerce` | A dedicated payment-entry screen. |
|
|
9
|
+
| [`form_input`](form_input.md) | `form` | Non-choice structured input, including reserved email capture. |
|
|
10
|
+
| [`intro_hero`](intro_hero.md) | `content` | Opening promise or low-friction entry screen. |
|
|
11
|
+
| [`multi_select_choice`](multi_select_choice.md) | `choice` | Multiple options are selected before explicit completion. |
|
|
12
|
+
| [`paywall_offer`](paywall_offer.md) | `commerce` | A monetization offer that presents purchasable plans. |
|
|
13
|
+
| [`progress_interstitial`](progress_interstitial.md) | `transition` | Progress, calculation, loading, reveal, or transition screen. |
|
|
14
|
+
| [`purchase_completed`](purchase_completed.md) | `terminal` | The canonical terminal shown after a verified initial purchase. |
|
|
15
|
+
| [`single_step_choice`](single_step_choice.md) | `choice` | Exactly one standard option is selected. |
|
|
16
|
+
| [`single_step_choice_emoji`](single_step_choice_emoji.md) | `choice` | Exactly one emoji-led option is selected. |
|
|
17
|
+
| [`social_proof`](social_proof.md) | `content` | Testimonials, reviews, credibility, or evidence. |
|
|
18
|
+
| [`subscription_handoff`](subscription_handoff.md) | `commerce` | A non-terminal app, store, or deep-link handoff. |
|
|
19
|
+
| [`subscription_management`](subscription_management.md) | `commerce` | A screen for managing or inspecting an existing subscription. |
|
|
20
|
+
| [`summary_confirmation`](summary_confirmation.md) | `content` | A summary, review, or confirmation before the next action. |
|
|
21
|
+
| [`upsell_offer`](upsell_offer.md) | `commerce` | A post-purchase or upgrade offer. |
|
|
22
|
+
| [`value_prop_story`](value_prop_story.md) | `content` | Benefit, explanation, motivation, or narrative value screen. |
|
|
23
|
+
|
|
24
|
+
Contract version: `3`
|
|
25
|
+
|
|
26
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# `cancellation_offer`
|
|
2
|
+
|
|
3
|
+
## Use when / do not use when
|
|
4
|
+
|
|
5
|
+
Use for cancellation retention or a downsell. Do not use for subscription overview, acquisition paywall, or ordinary upsell.
|
|
6
|
+
|
|
7
|
+
## Exact metadata contract
|
|
8
|
+
|
|
9
|
+
<!-- funnelsgrove:generated:start contract-v3/step/cancellation_offer -->
|
|
10
|
+
### Generated contract facts — do not edit
|
|
11
|
+
|
|
12
|
+
- Step contract version: `3`
|
|
13
|
+
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
14
|
+
- Type: `cancellation_offer`
|
|
15
|
+
- Family: `commerce`
|
|
16
|
+
- Description: A cancellation retention or downsell surface.
|
|
17
|
+
- Action owner: `step`
|
|
18
|
+
- Analytics role: _none_
|
|
19
|
+
- Terminal: `false`
|
|
20
|
+
- Required kind: `cancellation`
|
|
21
|
+
- Allowed kinds: `cancellation`
|
|
22
|
+
- Allowed semantic events: _None_
|
|
23
|
+
- Forbidden capabilities: `choice-write`, `email-capture`, `checkout`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`
|
|
24
|
+
|
|
25
|
+
#### Choice contract
|
|
26
|
+
|
|
27
|
+
_Not a choice type._
|
|
28
|
+
|
|
29
|
+
#### Automatic lifecycle events
|
|
30
|
+
|
|
31
|
+
`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`
|
|
32
|
+
|
|
33
|
+
#### Approved capability owners
|
|
34
|
+
|
|
35
|
+
- `subscription-management` must be owned by `runtime-subscription-helpers`.
|
|
36
|
+
|
|
37
|
+
#### Reserved identities
|
|
38
|
+
|
|
39
|
+
_No reserved identity for this type._
|
|
40
|
+
|
|
41
|
+
#### Golden fixture source
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type { FunnelManifestStep, FunnelStepMeta } from '@funnelsgrove/runtime';
|
|
45
|
+
|
|
46
|
+
const manifestStep = {
|
|
47
|
+
id: 'save-offer',
|
|
48
|
+
name: 'save-offer',
|
|
49
|
+
path: '/save-offer',
|
|
50
|
+
filePath: 'src/steps/step-save-offer.tsx',
|
|
51
|
+
componentKey: 'stepSaveOffer',
|
|
52
|
+
type: 'cancellation_offer',
|
|
53
|
+
kind: 'cancellation',
|
|
54
|
+
title: 'Stay with us',
|
|
55
|
+
} as const satisfies FunnelManifestStep;
|
|
56
|
+
|
|
57
|
+
const componentMeta = {
|
|
58
|
+
id: 'save-offer',
|
|
59
|
+
name: 'save-offer',
|
|
60
|
+
type: 'cancellation_offer',
|
|
61
|
+
kind: 'cancellation',
|
|
62
|
+
figmaNodeId: 'golden:cancellation-offer',
|
|
63
|
+
title: 'Stay with us',
|
|
64
|
+
description: 'Offer a retention path before cancellation.',
|
|
65
|
+
} as const satisfies FunnelStepMeta;
|
|
66
|
+
|
|
67
|
+
export const goldenFixture = {
|
|
68
|
+
stepType: 'cancellation_offer',
|
|
69
|
+
manifestStep,
|
|
70
|
+
componentMeta,
|
|
71
|
+
helper: 'runtime subscription helpers',
|
|
72
|
+
} as const;
|
|
73
|
+
```
|
|
74
|
+
<!-- funnelsgrove:generated:end contract-v3/step/cancellation_offer -->
|
|
75
|
+
|
|
76
|
+
## Interaction and persisted answer shape
|
|
77
|
+
|
|
78
|
+
Use runtime subscription helpers for keep/cancel/offer actions. Do not persist provider state as a funnel answer.
|
|
79
|
+
|
|
80
|
+
## Automatic lifecycle events
|
|
81
|
+
|
|
82
|
+
The controller owns the step outcome; subscription APIs own cancellation state transitions.
|
|
83
|
+
|
|
84
|
+
## Required semantic conversions
|
|
85
|
+
|
|
86
|
+
None in the browser unless a separate server-owned event contract is added.
|
|
87
|
+
|
|
88
|
+
## Approved shared helpers
|
|
89
|
+
|
|
90
|
+
Use runtime subscription helpers and manifest routing.
|
|
91
|
+
|
|
92
|
+
## MUST rules
|
|
93
|
+
|
|
94
|
+
- Preserve the cancellation kind.
|
|
95
|
+
- Make accept, decline, and final cancellation outcomes unambiguous.
|
|
96
|
+
|
|
97
|
+
## NEVER rules
|
|
98
|
+
|
|
99
|
+
- Never claim a save before server confirmation.
|
|
100
|
+
- Never send provider analytics directly.
|
|
101
|
+
|
|
102
|
+
## Golden template or fixture
|
|
103
|
+
|
|
104
|
+
See the [embedded canonical fixture](#golden-fixture-source) generated from `cancellation_offer.fixture.ts`.
|
|
105
|
+
|
|
106
|
+
## Validation command
|
|
107
|
+
|
|
108
|
+
Run `fgrove validate`.
|
|
109
|
+
|
|
110
|
+
## Manual QA and completion criteria
|
|
111
|
+
|
|
112
|
+
Test keep, accept offer, continue cancellation, failures/retries, refreshed state, and every resulting route.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# `checkout`
|
|
2
|
+
|
|
3
|
+
## Use when / do not use when
|
|
4
|
+
|
|
5
|
+
Use for a dedicated payment-entry screen. Do not use for plan merchandising without payment entry or for subscription management.
|
|
6
|
+
|
|
7
|
+
## Exact metadata contract
|
|
8
|
+
|
|
9
|
+
<!-- funnelsgrove:generated:start contract-v3/step/checkout -->
|
|
10
|
+
### Generated contract facts — do not edit
|
|
11
|
+
|
|
12
|
+
- Step contract version: `3`
|
|
13
|
+
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
14
|
+
- Type: `checkout`
|
|
15
|
+
- Family: `commerce`
|
|
16
|
+
- Description: A dedicated payment-entry screen.
|
|
17
|
+
- Action owner: `step`
|
|
18
|
+
- Analytics role: _none_
|
|
19
|
+
- Terminal: `false`
|
|
20
|
+
- Required kind: _none_
|
|
21
|
+
- Allowed kinds: _None_
|
|
22
|
+
- Allowed semantic events: `checkout_started`, `add_payment_info`, `checkout_completed`
|
|
23
|
+
- Forbidden capabilities: `choice-write`, `email-capture`, `subscription-management`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`
|
|
24
|
+
|
|
25
|
+
#### Choice contract
|
|
26
|
+
|
|
27
|
+
_Not a choice type._
|
|
28
|
+
|
|
29
|
+
#### Automatic lifecycle events
|
|
30
|
+
|
|
31
|
+
`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`
|
|
32
|
+
|
|
33
|
+
#### Approved capability owners
|
|
34
|
+
|
|
35
|
+
- `checkout` must be owned by `named-payment-helpers`.
|
|
36
|
+
|
|
37
|
+
#### Reserved identities
|
|
38
|
+
|
|
39
|
+
_No reserved identity for this type._
|
|
40
|
+
|
|
41
|
+
#### Golden fixture source
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import type { FunnelManifestStep, FunnelStepMeta } from '@funnelsgrove/runtime';
|
|
45
|
+
|
|
46
|
+
const manifestStep = {
|
|
47
|
+
id: 'checkout',
|
|
48
|
+
name: 'checkout',
|
|
49
|
+
path: '/checkout',
|
|
50
|
+
filePath: 'src/steps/step-checkout.tsx',
|
|
51
|
+
componentKey: 'stepCheckout',
|
|
52
|
+
type: 'checkout',
|
|
53
|
+
title: 'Secure checkout',
|
|
54
|
+
} as const satisfies FunnelManifestStep;
|
|
55
|
+
|
|
56
|
+
const componentMeta = {
|
|
57
|
+
id: 'checkout',
|
|
58
|
+
name: 'checkout',
|
|
59
|
+
type: 'checkout',
|
|
60
|
+
figmaNodeId: 'golden:checkout',
|
|
61
|
+
title: 'Secure checkout',
|
|
62
|
+
description: 'Collect payment through shared checkout UI.',
|
|
63
|
+
} as const satisfies FunnelStepMeta;
|
|
64
|
+
|
|
65
|
+
export const goldenFixture = {
|
|
66
|
+
stepType: 'checkout',
|
|
67
|
+
manifestStep,
|
|
68
|
+
componentMeta,
|
|
69
|
+
requiredEventMetadata: [
|
|
70
|
+
'funnelId',
|
|
71
|
+
'funnelVersionId',
|
|
72
|
+
'environment',
|
|
73
|
+
'stepContractVersion',
|
|
74
|
+
'stepId',
|
|
75
|
+
'stepName',
|
|
76
|
+
'stepType',
|
|
77
|
+
'eventId',
|
|
78
|
+
],
|
|
79
|
+
semanticHelpers: ['trackCheckoutStarted', 'trackPaymentInfoSubmitted', 'trackCheckoutCompleted'],
|
|
80
|
+
} as const;
|
|
81
|
+
```
|
|
82
|
+
<!-- funnelsgrove:generated:end contract-v3/step/checkout -->
|
|
83
|
+
|
|
84
|
+
## Interaction and persisted answer shape
|
|
85
|
+
|
|
86
|
+
The payment package owns payment state. Do not persist card, wallet, price, or provider data as funnel answers.
|
|
87
|
+
|
|
88
|
+
## Automatic lifecycle events
|
|
89
|
+
|
|
90
|
+
The controller owns step lifecycle. Payment helpers own semantic conversion boundaries and event IDs.
|
|
91
|
+
|
|
92
|
+
## Required semantic conversions
|
|
93
|
+
|
|
94
|
+
Use the named checkout-started, payment-info, and checkout-completed helpers with the complete required metadata returned by runtime context.
|
|
95
|
+
|
|
96
|
+
## Approved shared helpers
|
|
97
|
+
|
|
98
|
+
Use `trackCheckoutStarted`, `trackPaymentInfoSubmitted`, `trackCheckoutCompleted`, and shared checkout UI/runtime helpers.
|
|
99
|
+
|
|
100
|
+
## MUST rules
|
|
101
|
+
|
|
102
|
+
- Keep secrets server-side and provider IDs in configuration.
|
|
103
|
+
- Reuse one event ID per logical conversion and allow safe retries.
|
|
104
|
+
|
|
105
|
+
## NEVER rules
|
|
106
|
+
|
|
107
|
+
- Never capture raw payment details yourself.
|
|
108
|
+
- Never send incomplete, fabricated, or direct-provider analytics.
|
|
109
|
+
|
|
110
|
+
## Golden template or fixture
|
|
111
|
+
|
|
112
|
+
See the [embedded canonical fixture](#golden-fixture-source) generated from `checkout.fixture.ts`.
|
|
113
|
+
|
|
114
|
+
## Validation command
|
|
115
|
+
|
|
116
|
+
Run `fgrove validate`.
|
|
117
|
+
|
|
118
|
+
## Manual QA and completion criteria
|
|
119
|
+
|
|
120
|
+
Test all payment methods, validation, decline, retry, success, deduplication, required metadata, and post-success routing.
|