---
title: Lifecycle of an app in OCP
slug: optimizely-connect-platform/docs/lifecycle-ocp2
docTags: 
createdAt: 2026-07-23T12:37:03.966Z
---

The lifecycle is how you manage all the stages of an app. It includes the following:

- [App installation](docId\:nlHtCPtedxv2Kqyh8ZYQ6)
- [Settings form submission](docId\:nlHtCPtedxv2Kqyh8ZYQ6)
- [Authentication](docId\:nlHtCPtedxv2Kqyh8ZYQ6)
- [App upgrades](docId\:nlHtCPtedxv2Kqyh8ZYQ6)
- [App uninstallation](docId\:nlHtCPtedxv2Kqyh8ZYQ6)

App templates generated by `ocp app init` contains a skeleton of lifecycle methods. Add any logic your application needs there.

## App installation

When an app is installed in an OCP account, the `onInstall` method is called. The method should contain any logic that is required to initialize the app, for example

- Initialization of key value storage.
- Registering webhooks in third-party services.
- Performing dynamic OCP schema amendments through the API (declarative schema changes are performed automatically by OCP before the method is called).

## Settings form submission

One of the core components in creating your app is interacting with the [\`settings.yml\`](docId\:Z6YmznHABTRVZo_O78YOS), which involves handling the actions and being able to validate keys or communicate toasts back into the OCP application.

The following is a sample `settings.yml` and the associated `onSettingsForm` from the app lifecycle that handles the interactions from it:

### settings.yml

```yaml
sections:
  - key: auth
    label: Authenticate
    properties:
      - authConfirmed
    elements:
    - type: secret
      key: client_id
      label: Client ID
      help: Get your Client ID from Vendor
    - type: secret
      key: client_secret
      label: Client Secret
      help: Get your Client Secret from Vendor
    - type: button
      label: Authorize
      style: primary
      action: authorize #<-- action passed in
      disabled:
        key: client_id
        empty: true
  - key: config
    label: Configuration
    properties:
      - canImport
    disabled:
      key: auth.authConfirmed
      equals: false
    elements:
    - type: toggle
      key: winback
      defaultValue: true
      label: Winback
      help: Toggle to send Winback segment to Vendor (engaged, winback, churned)
    - type: toggle
      key: order_likelihood
      defaultValue: true
      label: Order Likelihood
      help: Toggle to send Order Likelihood segment to Vendor (Extremely Likely, Very Likely, Likely, Unlikely)
    - type: toggle
      key: discount_affinity
      defaultValue: true
      label: Discount Affinity
      help: Toggle to send Discount Affinity segment to Vendor (Always, Sometimes, Never)
    - type: button
      label: Save
      action: save #<-- action passed in
      style: primary
    - type: button
      label: Start Initial Import
      action: import #<-- action passed in
      disabled:
        key: canImport
        equals: false
```

### `onSettingsForm`

Each time the form is submitted, you can handle interactions with the form and also set variables for use in the form to enable new sections.

```typescript
import {Vendor} from '../lib/Vendor';
  
  ...

  public async onSettingsForm(
          section: string, action: string, formData: App.SubmittedFormData
  ): Promise<App.LifecycleSettingsResult> {
    const result = new App.LifecycleSettingsResult();
    const vendor = new Vendor();
    try {
      switch (action) {
      case 'authorize': // <-- switching on the action from above
        try {
          await vendor.validateAuth(formData);
          formData.authConfirmed = true; // <-- setting a variable for use in settings.yml
          await storage.settings.put(section, formData); // <-- saving form data
          result.addToast('success', 'Authorized');
        } catch (e) {
          logger.error('issue authenticating', e);
          result.addToast('warning', 'Could not Authenticate, please validate your information is correct');
        }
        break;
      case 'save':
        try {
          await vendor.createObjects(formData);
          formData.canImport = true;
          await storage.settings.put(section, formData);
          result.addToast('success', 'Ready to Import');
        } catch (e) {
          logger.error('Issue creating objects', e);
          result.addToast('warning', 'Could not create audiences');
        }
        break;
      case 'import':
        logger.info('Starting Job');
        await App.jobs.trigger('nightly_export', {}); // <-- starting a Job
        result.addToast('info', 'Sync Started');
        break;
      }
      return result;
    } catch (e) {
      logger.error('Issue:', e);
      return result.addToast('danger', 'Sorry, an unexpected error occurred. Please try again in a moment.');
    }
  }
```

## Authentication

`onAuthorizationRequest` and `onAuthorizationGrant` are called as part of the authorization process initialized by clicking an [OAuth button](docId\:V5iqIFcSz3Zl7fFExP8mL) element type in the app settings form. See [OAuth authentication](docId\:fS7u929rUh_eCow3L6o3M) for details.

## App upgrades

When an app is upgraded to a new version, by an auto-upgrade or a manual upgrade, OCP calls the following three lifecycle methods:

- `onUpgrade` – This method is called after declarative schema changes are performed by OCP. Use it to perform dynamic schema changes through the API.
- `onFinalizeUpgrade` – This method is called after webhook URLs are created for all new functions in the version. Use it to register webhooks in a third-party service if needed.
- `onAfterUpgrade` – This method is called after the upgrade is completed. Use it to trigger any required one-off jobs.

Keep in mind the upgrade is not necessarily from the previous most recent version. The previous version of the app is provided in the `onUpgrade` method attribute.

## App uninstallation

When an app is uninstalled from an OCP account, OCP calls the `onUninstall` lifecycle method. The method should contain the logic to clean up after the app is uninstalled.

This might include invalidating authentication tokens in third-party services, removing resources from third-party services, and so on.
