# Step metadata contract

Step metadata is an analytics and runtime API, not descriptive decoration. Choose the type from actual behavior and preserve stable identity.

<!-- funnelsgrove:generated:start contract-v3/contract/step-metadata -->
Step contract version: `3`

Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`

| Type | Family | Action owner | Required kind | Terminal | Meaning |
| --- | --- | --- | --- | --- | --- |
| `cancellation_offer` | `commerce` | `step` | `cancellation` | `false` | A cancellation retention or downsell surface. |
| `checkout` | `commerce` | `step` | — | `false` | A dedicated payment-entry screen. |
| `form_input` | `form` | `either` | — | `false` | Non-choice structured input, including reserved email capture. |
| `intro_hero` | `content` | `shared-shell` | — | `false` | Opening promise or low-friction entry screen. |
| `multi_select_choice` | `choice` | `either` | — | `false` | Multiple options are selected before explicit completion. |
| `paywall_offer` | `commerce` | `step` | `paywall` | `false` | A monetization offer that presents purchasable plans. |
| `progress_interstitial` | `transition` | `either` | — | `false` | Progress, calculation, loading, reveal, or transition screen. |
| `purchase_completed` | `terminal` | `step` | `subscription-handoff` | `true` | The canonical terminal shown after a verified initial purchase. |
| `single_step_choice` | `choice` | `step` | — | `false` | Exactly one standard option is selected. |
| `single_step_choice_emoji` | `choice` | `step` | — | `false` | Exactly one emoji-led option is selected. |
| `social_proof` | `content` | `shared-shell` | — | `false` | Testimonials, reviews, credibility, or evidence. |
| `subscription_handoff` | `commerce` | `step` | `subscription-handoff` | `false` | A non-terminal app, store, or deep-link handoff. |
| `subscription_management` | `commerce` | `step` | `manage-subscription` | `false` | A screen for managing or inspecting an existing subscription. |
| `summary_confirmation` | `content` | `either` | — | `false` | A summary, review, or confirmation before the next action. |
| `upsell_offer` | `commerce` | `step` | `upsell` | `false` | A post-purchase or upgrade offer. |
| `value_prop_story` | `content` | `shared-shell` | — | `false` | Benefit, explanation, motivation, or narrative value screen. |

### Reserved identities

| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
<!-- funnelsgrove:generated:end contract-v3/contract/step-metadata -->

## Required parity

For each step, the manifest and exported component metadata must agree on `id`, `name`, `type`, optional `kind`, and optional `choice`. Keep `path`, `filePath`, `componentKey`, and title in the manifest. IDs and names are durable analytics keys.

## Classification method

1. Identify the screen’s user interaction and business purpose.
2. Open the matching [step-type page](../steps/INDEX.md).
3. Copy the fixture structure, then adapt only product-specific IDs, paths, copy, and content.
4. Run `fgrove validate` before preview.

## Protected metadata

Do not rename an existing step, answer key, reserved identity, or analytics meaning as cleanup. Treat such changes as migrations with compatibility and measurement review.

## Completion check

Validation passes, metadata parity has no diagnostics, every reserved identity is exact, and analytics receives stable type/name values.
